Tizen 2.0 Release
authorDoHyun Pyun <dh79.pyun@samsung.com>
Tue, 21 Aug 2012 11:09:33 +0000 (20:09 +0900)
committerDoHyun Pyun <dh79.pyun@samsung.com>
Tue, 21 Aug 2012 11:09:33 +0000 (20:09 +0900)
27 files changed:
bluetooth-hfp-agent/CMakeLists.txt [new file with mode: 0644]
bluetooth-hfp-agent/bluetooth-hfp-agent.c [new file with mode: 0644]
bluetooth-hfp-agent/bluetooth-hfp-agent.h [new file with mode: 0644]
bluetooth-hfp-agent/hfp_agent.xml [new file with mode: 0644]
bluetooth-hfp-agent/org.bluez.hfp_agent.service [new file with mode: 0644]
bluetooth-media-control/CMakeLists.txt [new file with mode: 0644]
bluetooth-media-control/bluetooth-media-control-internal.h [new file with mode: 0644]
bluetooth-media-control/bluetooth-media-control.c [new file with mode: 0644]
bluetooth-media-control/bluetooth-media-control.h [new file with mode: 0644]
bluetooth-media-control/bluetooth-media-control.pc.in [new file with mode: 0644]
bluetooth-pb-agent/bluetooth_pb_vcard.c [new file with mode: 0644]
bluetooth-pb-agent/bluetooth_pb_vcard.h [new file with mode: 0644]
bluetooth-telephony/CMakeLists.txt [new file with mode: 0644]
bluetooth-telephony/bluetooth-telephony-api.c [new file with mode: 0644]
bluetooth-telephony/bluetooth-telephony-api.h [new file with mode: 0644]
bluetooth-telephony/bluetooth-telephony-internal.h [new file with mode: 0644]
bluetooth-telephony/bluetooth-telephony.pc.in [new file with mode: 0644]
bluetooth-telephony/bt_telephony_frwk.xml [new file with mode: 0644]
bluetooth-telephony/marshal.list [new file with mode: 0644]
debian/libbluetooth-frwk-0.postinst [new file with mode: 0644]
lib/bluetooth-audio-api.c [new file with mode: 0644]
lib/bluetooth-audio-api.h [new file with mode: 0644]
lib/bluetooth-control-api.c [new file with mode: 0644]
lib/bluetooth-control-api.h [new file with mode: 0644]
lib/bluetooth-le/bluetooth-gatt-api.c [new file with mode: 0644]
lib/bluetooth-le/bluetooth-gatt-glue.h [new file with mode: 0644]
lib/bluetooth-le/bluetooth-gatt.xml [new file with mode: 0644]

diff --git a/bluetooth-hfp-agent/CMakeLists.txt b/bluetooth-hfp-agent/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b47a694
--- /dev/null
@@ -0,0 +1,53 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bluetooth-hfp-agent C)
+
+SET(SRCS bluetooth-hfp-agent.c)
+SET(APP_VENDOR tizen)
+SET(APP_NAME bluetooth-hfp-agent)
+SET(APP_DIR /usr/bin)
+SET(APP_LOCALEDIR /usr/share/locale)
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+       SET(CMAKE_BUILD_TYPE "Release")
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(hfp_pkg REQUIRED dbus-glib-1 vconf appsvc contacts-service)
+
+FOREACH(flag ${hfp_pkg_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+IF("${ARCH}" STREQUAL "arm")
+       ADD_DEFINITIONS("-DTARGET")
+       MESSAGE("add -DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool)
+EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bt_hfp_agent ${CMAKE_CURRENT_SOURCE_DIR}/hfp_agent.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/bluetooth_hfp_agent_glue.h")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DVENDOR=\"${APP_VENDOR}\"")
+ADD_DEFINITIONS("-DAPPNAME=\"${APP_NAME}\"")
+ADD_DEFINITIONS("-DAPP_DIR=\"${APP_DIR}\"")
+ADD_DEFINITIONS("-DAPP_LOCALEDIR=\"${APP_LOCALEDIR}\"")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${hfp_pkg_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.bluez.hfp_agent.service DESTINATION share/dbus-1/services)
diff --git a/bluetooth-hfp-agent/bluetooth-hfp-agent.c b/bluetooth-hfp-agent/bluetooth-hfp-agent.c
new file mode 100644 (file)
index 0000000..43224b8
--- /dev/null
@@ -0,0 +1,1601 @@
+/*
+ * Bluetooth-hfp-agent
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             Girishashok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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 <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <signal.h>
+
+#include "vconf.h"
+#include "vconf-keys.h"
+#include "contacts-svc.h"
+#include "appsvc.h"
+
+#include "bluetooth-hfp-agent.h"
+
+static GMainLoop *gmain_loop = NULL;
+static DBusConnection *gconn = NULL;
+
+#define BT_ERROR_INTERNAL "InternalError"
+#define BT_ERROR_NOT_AVAILABLE "NotAvailable"
+#define BT_ERROR_NOT_CONNECTED "NotConnected"
+#define BT_ERROR_BUSY "InProgress"
+#define BT_ERROR_INVALID_PARAM "InvalidArguments"
+#define BT_ERROR_ALREADY_EXSIST "AlreadyExists"
+#define BT_ERROR_ALREADY_CONNECTED "Already Connected"
+#define BT_ERROR_NO_MEMORY "No memory"
+#define BT_ERROR_I_O_ERROR "I/O error"
+#define BT_ERROR_OPERATION_NOT_AVAILABLE "Operation currently not available"
+#define BT_ERROR_BATTERY "Battery error "
+#define BT_ERROR_SIGNAL "Signal error"
+#define BT_ERROR_NO_CALL_LOG "No Call log"
+#define BT_ERROR_INVLAID_DTMF "Invalid dtmf"
+
+#define BLUEZ_SERVICE_NAME "org.bluez"
+#define TELEPHONY_CSD_INTERFACE "org.tizen.telephony.csd"
+#define TELEPHONY_CSD_OBJECT_PATH "/org/tizen/csd"
+#define TELEPHONY_APP_INTERFACE "org.tizen.csd.Call.Instance"
+
+#define BT_HFP_AGENT_SET_PROPERTY "SetProperty"
+
+/* AT+CSQ : Returns received signal strength indication.
+     Command response: +CSQ: <rssi>,<ber>
+    <ber> is not supported and has a constant value of 99, included for compatibility reasons.
+*/
+#define BT_SIGNAL_QUALITY_BER 99
+
+/*Length of the string used to send telephone number to app-svc
+   format: tel:<number>
+*/
+#define BT_MAX_TEL_NUM_STRING 20
+
+typedef struct {
+       GObject parent;
+} BtHfpAgent;
+
+typedef struct {
+       GObjectClass parent;
+} BtHfpAgentClass;
+
+GType bt_hfp_agent_get_type(void);
+
+#define BT_HFP_TYPE_AGENT (bt_hfp_agent_get_type())
+
+#define BT_HFP_AGENT(object)(G_TYPE_CHECK_INSTANCE_CAST((object), \
+                       BT_HFP_TYPE_AGENT , BtHfpAgent))
+
+#define BT_HFP_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_CAST((klass), \
+                       BT_HFP_TYPE_AGENT , BtHfpAgentClass))
+
+#define BT_HFP_IS_AGENT(object)(G_TYPE_CHECK_INSTANCE_TYPE((object), \
+                       BT_HFP_TYPE_AGENT))
+
+#define BT_HFP_IS_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), \
+                       BT_HFP_TYPE_AGENT))
+
+#define BT_HFP_AGENT_GET_CLASS(obj)(G_TYPE_INSTANCE_GET_CLASS((obj), \
+                       BT_HFP_TYPE_AGENT , BtHfpAgentClass))
+
+G_DEFINE_TYPE(BtHfpAgent, bt_hfp_agent, G_TYPE_OBJECT)
+
+static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
+                               const gchar *path, DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
+                               const gchar *path, DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
+                               const gchar *number, gint call_id,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
+                               const gchar *number, gint call_id,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
+                               const gchar *path, gint status, gint call_id,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint call_id,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
+                               const gchar *number, guint flags,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
+                               DBusGMethodInvocation *context);
+
+static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
+                               DBusGMethodInvocation *context);
+
+#include "bluetooth_hfp_agent_glue.h"
+
+static void bt_hfp_agent_init(BtHfpAgent *obj)
+{
+       DBG("+\n");
+
+       g_assert(obj != NULL);
+}
+
+static void bt_hfp_agent_finalize(GObject *obj)
+{
+       DBG("+\n");
+
+       G_OBJECT_CLASS(bt_hfp_agent_parent_class)->finalize(obj);
+}
+
+static void bt_hfp_agent_class_init(BtHfpAgentClass *klass)
+{
+       DBG("+\n");
+
+       GObjectClass *object_class = (GObjectClass *)klass;
+
+       g_assert(klass != NULL);
+
+       object_class->finalize = bt_hfp_agent_finalize;
+
+       dbus_g_object_type_install_info(BT_HFP_TYPE_AGENT,
+                                       &dbus_glib_bt_hfp_agent_object_info);
+}
+
+static GQuark __bt_hfp_agent_error_quark(void)
+{
+       DBG("+\n");
+
+       static GQuark quark = 0;
+       if (!quark)
+               quark = g_quark_from_static_string("agent");
+
+       return quark;
+}
+
+static GError *__bt_hfp_agent_set_error(bt_hfp_agent_error_t error)
+{
+       DBG("+\n");
+
+       switch (error) {
+       case BT_HFP_AGENT_ERROR_NOT_AVAILABLE:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_NOT_AVAILABLE);
+       case BT_HFP_AGENT_ERROR_NOT_CONNECTED:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_NOT_CONNECTED);
+       case BT_HFP_AGENT_ERROR_BUSY:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_BUSY);
+       case BT_HFP_AGENT_ERROR_INVALID_PARAM:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_INVALID_PARAM);
+       case BT_HFP_AGENT_ERROR_ALREADY_EXSIST:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_ALREADY_EXSIST);
+       case BT_HFP_AGENT_ERROR_ALREADY_CONNECTED:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_ALREADY_CONNECTED);
+       case BT_HFP_AGENT_ERROR_NO_MEMORY:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_NO_MEMORY);
+       case BT_HFP_AGENT_ERROR_I_O_ERROR:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_I_O_ERROR);
+       case BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                       BT_ERROR_OPERATION_NOT_AVAILABLE);
+       case BT_HFP_AGENT_ERROR_BATTERY_STATUS:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                       BT_ERROR_BATTERY);
+       case BT_HFP_AGENT_ERROR_SIGNAL_STATUS:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                       BT_ERROR_SIGNAL);
+       case BT_HFP_AGENT_ERROR_NO_CALL_LOGS:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                       BT_ERROR_NO_CALL_LOG);
+       case BT_HFP_AGENT_ERROR_INTERNAL:
+       default:
+               return g_error_new(BT_HFP_AGENT_ERROR, error,
+                                               BT_ERROR_INTERNAL);
+       }
+}
+
+static int __bt_hfp_agent_get_error(const char *error_message)
+{
+       if (error_message == NULL) {
+               DBG("Error message NULL\n");
+               return BT_HFP_AGENT_ERROR_INTERNAL;
+       }
+
+       DBG("Error message = %s \n", error_message);
+
+       if (g_strcmp0(error_message, BT_ERROR_NOT_AVAILABLE) == 0)
+               return BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
+       else if (g_strcmp0(error_message, BT_ERROR_NOT_CONNECTED) == 0)
+               return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
+       else if (g_strcmp0(error_message, BT_ERROR_BUSY) == 0)
+               return BT_HFP_AGENT_ERROR_BUSY;
+       else if (g_strcmp0(error_message, BT_ERROR_INVALID_PARAM) == 0)
+               return BT_HFP_AGENT_ERROR_INVALID_PARAM;
+       else if (g_strcmp0(error_message, BT_ERROR_ALREADY_EXSIST) == 0)
+               return BT_HFP_AGENT_ERROR_ALREADY_EXSIST;
+       else if (g_strcmp0(error_message, BT_ERROR_ALREADY_CONNECTED) == 0)
+               return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
+       else if (g_strcmp0(error_message, BT_ERROR_NO_MEMORY) == 0)
+               return BT_HFP_AGENT_ERROR_NO_MEMORY;
+       else if (g_strcmp0(error_message, BT_ERROR_I_O_ERROR) == 0)
+               return BT_HFP_AGENT_ERROR_I_O_ERROR;
+       else if (g_strcmp0(error_message,
+                               BT_ERROR_OPERATION_NOT_AVAILABLE) == 0)
+               return BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE;
+       else if (g_strcmp0(error_message, BT_ERROR_INVLAID_DTMF) == 0)
+               return BT_HFP_AGENT_ERROR_INVALID_DTMF;
+       else
+               return BT_HFP_AGENT_ERROR_INTERNAL;
+}
+
+static int __bt_hfp_agent_dbus_method_send(const char *service,
+                               const char *path, const char *interface,
+                               const char *method, gboolean response,
+                               int type, ...)
+{
+       DBusMessage *msg;
+       DBusMessage *reply;
+       DBusError err;
+       va_list args;
+       int error;
+
+       DBG("__bt_hfp_agent_dbus_method_send +\n");
+
+       msg = dbus_message_new_method_call(service, path, interface,
+                                                               method);
+       if (!msg) {
+               DBG("Unable to allocate new D-Bus %s message \n", method);
+               return BT_HFP_AGENT_ERROR_INTERNAL;
+       }
+
+       va_start(args, type);
+
+       if (!dbus_message_append_args_valist(msg, type, args)) {
+               dbus_message_unref(msg);
+               va_end(args);
+               return BT_HFP_AGENT_ERROR_INTERNAL;
+       }
+
+       va_end(args);
+
+       dbus_error_init(&err);
+
+       if (response) {
+               reply = dbus_connection_send_with_reply_and_block(gconn,
+                                                       msg, -1, &err);
+               dbus_message_unref(msg);
+
+               if (!reply) {
+                       DBG("Error returned in method call\n");
+                       if (dbus_error_is_set(&err)) {
+                               error = __bt_hfp_agent_get_error(err.message);
+                               dbus_error_free(&err);
+                               return error;
+                       } else {
+                               DBG("Error is not set\n");
+                               return BT_HFP_AGENT_ERROR_INTERNAL;
+                       }
+               }
+               dbus_message_unref(reply);
+       } else {
+               dbus_connection_send(gconn, msg, NULL);
+               dbus_message_unref(msg);
+       }
+
+       DBG("__bt_hfp_agent_dbus_method_send -\n");
+
+       return BT_HFP_AGENT_ERROR_NONE;
+}
+
+static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
+                               const gchar *path, DBusGMethodInvocation *context)
+{
+       gboolean flag = TRUE;
+       char *sender;
+       GError *error;
+       int ret;
+
+       DBG("bt_hfp_agent_register_application + \n");
+
+       if (path == NULL) {
+               DBG("Invalid Argument path\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s\n", path);
+
+       sender = dbus_g_method_get_sender(context);
+
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+                               TELEPHONY_CSD_OBJECT_PATH,
+                               TELEPHONY_CSD_INTERFACE,
+                               "RegisterTelephonyAgent", TRUE,
+                               DBUS_TYPE_BOOLEAN, &flag,
+                               DBUS_TYPE_STRING, &path,
+                               DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
+       g_free(sender);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("bt_hfp_agent_register_application - \n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
+                               const gchar *path, DBusGMethodInvocation *context)
+{
+       gboolean flag = FALSE;
+       char *sender;
+       GError *error;
+       int ret;
+
+       DBG("bt_hfp_agent_unregister_application + \n");
+
+       if (path == NULL) {
+               DBG("Invalid Argument path\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s \n", path);
+
+       sender = dbus_g_method_get_sender(context);
+
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+                               TELEPHONY_CSD_OBJECT_PATH,
+                               TELEPHONY_CSD_INTERFACE,
+                               "RegisterTelephonyAgent", TRUE,
+                               DBUS_TYPE_BOOLEAN, &flag,
+                               DBUS_TYPE_STRING, &path,
+                               DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
+       g_free(sender);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("bt_hfp_agent_unregister_application - \n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
+                               const gchar *number, gint call_id,
+                               DBusGMethodInvocation *context)
+{
+       GError *error;
+       char *sender;
+       int ret;
+
+       DBG("bt_hfp_agent_incoming_call + \n");
+
+       if (path == NULL || number == NULL) {
+               DBG("Invalid Arguments\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s\n", path);
+       DBG("Phone number = %s\n", number);
+       DBG("Call id = %d\n", call_id);
+
+       sender = dbus_g_method_get_sender(context);
+
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+                               TELEPHONY_CSD_OBJECT_PATH,
+                               TELEPHONY_CSD_INTERFACE,
+                               "Incoming", TRUE,
+                               DBUS_TYPE_STRING, &path,
+                               DBUS_TYPE_STRING, &number,
+                               DBUS_TYPE_UINT32, &call_id,
+                               DBUS_TYPE_STRING, &sender,
+                               DBUS_TYPE_INVALID);
+       g_free(sender);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("bt_hfp_agent_incoming_call - \n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
+                               const gchar *number, gint call_id,
+                               DBusGMethodInvocation *context)
+{
+       GError *error;
+       char *sender;
+       int ret;
+
+       DBG("bt_hfp_agent_outgoing_call + \n");
+
+       if (path == NULL || number == NULL) {
+               DBG("Invalid Arguments\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s\n", path);
+       DBG("Phone number = %s\n", number);
+       DBG("Call id = %d\n", call_id);
+
+       sender = dbus_g_method_get_sender(context);
+
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+                               TELEPHONY_CSD_OBJECT_PATH,
+                               TELEPHONY_CSD_INTERFACE,
+                               "Outgoing", TRUE,
+                               DBUS_TYPE_STRING, &path,
+                               DBUS_TYPE_STRING, &number,
+                               DBUS_TYPE_UINT32, &call_id,
+                               DBUS_TYPE_STRING, &sender,
+                               DBUS_TYPE_INVALID);
+       g_free(sender);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("bt_hfp_agent_outgoing_call - \n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
+                               const gchar *path, gint status, gint call_id,
+                               DBusGMethodInvocation *context)
+{
+       GError *error;
+       char *sender;
+       int ret;
+
+       DBG("bt_hfp_agent_change_call_status + \n");
+
+       if (path == NULL) {
+               DBG("Invalid Argument path\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s\n", path);
+       DBG("Status = %d\n", status);
+       DBG("Call id = %d\n", call_id);
+
+       sender = dbus_g_method_get_sender(context);
+
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
+                               TELEPHONY_CSD_OBJECT_PATH,
+                               TELEPHONY_CSD_INTERFACE,
+                               "SetCallStatus", TRUE,
+                               DBUS_TYPE_STRING, &path,
+                               DBUS_TYPE_UINT32, &status,
+                               DBUS_TYPE_UINT32, &call_id,
+                               DBUS_TYPE_STRING, &sender,
+                               DBUS_TYPE_INVALID);
+       g_free(sender);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("bt_hfp_agent_change_call_status - \n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context)
+{
+       int ret;
+       GError *error;
+       DBG("+\n");
+
+       if (path == NULL || sender == NULL) {
+               DBG("Invalid Arguments\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s \n", path);
+       DBG("Call Id = %d", call_id);
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(sender,
+                               path, TELEPHONY_APP_INTERFACE,
+                               "Answer", FALSE,
+                               DBUS_TYPE_UINT32, &call_id,
+                               DBUS_TYPE_INVALID);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("-\n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context)
+{
+       int ret;
+       GError *error;
+       DBG("+\n");
+
+       if (path == NULL || sender == NULL) {
+               DBG("Invalid Arguments\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s \n", path);
+       DBG("Call Id = %d", call_id);
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(sender,
+                               path, TELEPHONY_APP_INTERFACE,
+                               "Release", FALSE,
+                               DBUS_TYPE_UINT32, &call_id,
+                               DBUS_TYPE_INVALID);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       DBG("-\n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context)
+{
+       int ret;
+       GError *error;
+       DBG("+\n");
+
+       if (path == NULL || sender == NULL) {
+               DBG("Invalid Arguments\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s \n", path);
+       DBG("Call Id = %d", call_id);
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(sender,
+                               path, TELEPHONY_APP_INTERFACE,
+                               "Reject", FALSE,
+                               DBUS_TYPE_UINT32, &call_id,
+                               DBUS_TYPE_INVALID);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       DBG("-\n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint value,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context)
+{
+       int ret;
+       GError *error;
+       DBG("+\n");
+
+       if (path == NULL || sender == NULL) {
+               DBG("Invalid Arguments\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Application path = %s \n", path);
+       DBG("Value = %d", value);
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(sender,
+                               path, TELEPHONY_APP_INTERFACE,
+                               "Threeway", TRUE,
+                               DBUS_TYPE_UINT32, &value,
+                               DBUS_TYPE_INVALID);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       DBG("-\n");
+       return TRUE;
+}
+
+static gboolean __bt_hfp_agent_make_call(const char *number)
+{
+       bundle *b;
+       char telnum[BT_MAX_TEL_NUM_STRING];
+
+       b = bundle_create();
+       if (NULL == b)
+               return FALSE;
+
+       appsvc_set_operation(b, APPSVC_OPERATION_CALL);
+       snprintf(telnum, sizeof(telnum), "tel:%s", number);
+       appsvc_set_uri(b, telnum);
+       appsvc_add_data(b, "ctindex", "-1");
+       appsvc_run_service(b, 0, NULL, NULL);
+       bundle_free(b);
+
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
+                               DBusGMethodInvocation *context)
+{
+       GError *error;
+       int error_code;
+       char *last_number;
+
+       DBG("+ \n");
+
+       /*Get last dialed number*/
+       if (contacts_svc_connect() != CTS_SUCCESS) {
+               ERR("contacts_svc_connect failed \n");
+               error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       last_number = contacts_svc_phonelog_get_last_number(CTS_PLOG_LAST_ALL);
+
+       if (last_number == NULL) {
+               ERR("No last number \n");
+               contacts_svc_disconnect();
+               error_code = BT_HFP_AGENT_ERROR_NO_CALL_LOGS;
+               goto fail;
+       }
+
+       DBG("Last dialed number = %s\n", last_number);
+
+       contacts_svc_disconnect();
+
+       /*Make Voice call*/
+       if (!__bt_hfp_agent_make_call(last_number)) {
+               ERR("Problem launching application \n");
+               error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("-\n");
+       return TRUE;
+fail:
+       error = __bt_hfp_agent_set_error(error_code);
+       dbus_g_method_return_error(context, error);
+       g_error_free(error);
+       return FALSE;
+}
+
+static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
+                               const gchar *number, guint flags,
+                               DBusGMethodInvocation *context)
+{
+       GError *error;
+       int error_code;
+
+       DBG("+\n");
+
+       if (number == NULL) {
+               ERR("Invalid Argument\n");
+               error_code = BT_HFP_AGENT_ERROR_INVALID_PARAM;
+               goto fail;
+       }
+
+       DBG("Number = %s \n", number);
+       DBG("flags = %d", flags);
+
+       /*TODO: Make use of flags*/
+
+       /*Make Voice call*/
+       if (!__bt_hfp_agent_make_call(number)) {
+               ERR("Problem launching application \n");
+               error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("-\n");
+       return TRUE;
+fail:
+       error = __bt_hfp_agent_set_error(error_code);
+       dbus_g_method_return_error(context, error);
+       g_error_free(error);
+       DBG("-\n");
+       return FALSE;
+}
+
+static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
+                               DBusGMethodInvocation *context)
+{
+       GError *error;
+       int error_code;
+       CTSvalue *contact = NULL;
+       const char *number;
+
+       DBG("+\n");
+
+       DBG("location = %d \n", location);
+
+       /*Get number from contacts location*/
+       if (contacts_svc_connect() != CTS_SUCCESS) {
+               ERR("contacts_svc_connect failed \n");
+               error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       if (contacts_svc_get_contact_value(CTS_GET_DEFAULT_NUMBER_VALUE,
+                               location, &contact) != CTS_SUCCESS)  {
+               ERR("contacts_svc_get_contact_value failed \n");
+               error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
+               contacts_svc_disconnect();
+               goto fail;
+       }
+
+       number = contacts_svc_value_get_str(contact, CTS_NUM_VAL_NUMBER_STR);
+
+       if (number == NULL) {
+               ERR("No number at the location \n");
+               error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
+               contacts_svc_disconnect();
+               goto fail;
+       }
+
+       contacts_svc_disconnect();
+
+       /*Make Voice call*/
+       if (!__bt_hfp_agent_make_call(number)) {
+               ERR("Problem launching application \n");
+               error_code = BT_HFP_AGENT_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       dbus_g_method_return(context);
+
+       DBG("-\n");
+       return TRUE;
+fail:
+       error = __bt_hfp_agent_set_error(error_code);
+       dbus_g_method_return_error(context, error);
+       g_error_free(error);
+       DBG("-\n");
+       return FALSE;
+}
+
+static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
+                               const gchar *path, const gchar *sender,
+                               DBusGMethodInvocation *context)
+{
+       GError *error;
+       int ret;
+
+       DBG("+\n");
+
+       if (dtmf == NULL || path == NULL || sender == NULL) {
+               ERR("Invalid Argument\n");
+               error = __bt_hfp_agent_set_error(
+                                       BT_HFP_AGENT_ERROR_INVALID_PARAM);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       DBG("Dtmf = %s \n", dtmf);
+       DBG("Application path = %s \n", path);
+       DBG("Sender = %s\n", sender);
+
+       ret = __bt_hfp_agent_dbus_method_send(sender,
+                               path, TELEPHONY_APP_INTERFACE,
+                               "SendDtmf", FALSE,
+                               DBUS_TYPE_STRING, &dtmf,
+                               DBUS_TYPE_INVALID);
+
+       if (ret != BT_HFP_AGENT_ERROR_NONE) {
+               error = __bt_hfp_agent_set_error(ret);
+               dbus_g_method_return_error(context, error);
+               g_error_free(error);
+               return FALSE;
+       }
+
+       /*App Selector code here needed*/
+       dbus_g_method_return(context);
+
+       DBG("-\n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
+                               DBusGMethodInvocation *context)
+{
+       DBG("+\n");
+
+       DBG("Activate = %d \n", activate);
+
+       /*App Selector code here needed*/
+       dbus_g_method_return(context);
+
+       DBG("-\n");
+       return TRUE;
+}
+
+static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
+                               DBusGMethodInvocation *context)
+{
+       gint battery_chrg_status;
+       gint battery_capacity;
+       GError *error;
+
+       DBG("+\n");
+
+       if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
+                                               &battery_chrg_status)) {
+               DBG("VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW failed\n");
+               goto fail;
+       }
+
+       DBG("Status : %d\n", battery_chrg_status);
+
+       if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+                                               &battery_capacity)) {
+               DBG("VCONFKEY_SYSMAN_BATTERY_CAPACITY failed\n");
+               goto fail;
+       }
+
+       DBG("Capacity : %d\n", battery_capacity);
+
+       dbus_g_method_return(context, battery_chrg_status, battery_capacity);
+       DBG("-\n");
+       return TRUE;
+
+fail:
+       error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_BATTERY_STATUS);
+       dbus_g_method_return_error(context, error);
+       g_error_free(error);
+       DBG("-\n");
+       return FALSE;
+}
+
+static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
+                                       DBusGMethodInvocation *context)
+{
+       gint rssi;
+       GError *error;
+
+       DBG("+\n");
+
+       if (!vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi)) {
+               DBG("VCONFKEY_TELEPHONY_RSSI failed\n");
+               goto fail;
+       }
+
+       DBG("RSSI : %d \n", rssi);
+
+       dbus_g_method_return(context, rssi, BT_SIGNAL_QUALITY_BER);
+       DBG("-\n");
+       return TRUE;
+fail:
+       error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_SIGNAL_STATUS);
+       dbus_g_method_return_error(context, error);
+       g_error_free(error);
+       DBG("-\n");
+       return FALSE;
+}
+
+static void __bt_hfp_agent_append_variant(DBusMessageIter *iter,
+                       int type, void *val)
+{
+       DBusMessageIter value_iter;
+       const char *variant;
+
+       switch (type) {
+       case DBUS_TYPE_BOOLEAN:
+               variant = DBUS_TYPE_BOOLEAN_AS_STRING;
+               break;
+       case DBUS_TYPE_STRING:
+               variant = DBUS_TYPE_STRING_AS_STRING;
+               break;
+       case DBUS_TYPE_BYTE:
+               variant = DBUS_TYPE_BYTE_AS_STRING;
+               break;
+       case DBUS_TYPE_UINT16:
+               variant = DBUS_TYPE_UINT16_AS_STRING;
+               break;
+       case DBUS_TYPE_UINT32:
+               variant = DBUS_TYPE_UINT32_AS_STRING;
+               break;
+       case DBUS_TYPE_INT16:
+               variant = DBUS_TYPE_INT16_AS_STRING;
+               break;
+       case DBUS_TYPE_INT32:
+               variant = DBUS_TYPE_INT32_AS_STRING;
+               break;
+       case DBUS_TYPE_OBJECT_PATH:
+               variant = DBUS_TYPE_OBJECT_PATH_AS_STRING;
+               break;
+       default:
+               variant = DBUS_TYPE_VARIANT_AS_STRING;
+               break;
+       }
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, variant,
+                                                       &value_iter);
+       dbus_message_iter_append_basic(&value_iter, type, val);
+       dbus_message_iter_close_container(iter, &value_iter);
+}
+
+static gboolean __bt_hfp_agent_dbus_method_variant_send(const char *path,
+               const char *interface, const char *method, const char *name,
+               int type, void *value)
+{
+       DBusMessage *msg;
+       DBusMessage *reply;
+       DBusError err;
+       DBusMessageIter iter;
+
+       DBG(" +\n");
+
+       msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
+                       path, interface, method);
+
+       if (!msg) {
+               DBG("Unable to allocate new D-Bus %s message", method);
+               return FALSE;
+       }
+
+       dbus_message_iter_init_append(msg, &iter);
+
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+       __bt_hfp_agent_append_variant(&iter, type, value);
+
+       dbus_error_init(&err);
+
+       reply = dbus_connection_send_with_reply_and_block(gconn,
+                               msg, -1, &err);
+
+       dbus_message_unref(msg);
+
+       if (!reply) {
+               DBG("Error returned in method call\n");
+               if (dbus_error_is_set(&err)) {
+                       if (err.message != NULL) {
+                               DBG("Error message = %s\n", err.message);
+                       }
+                       dbus_error_free(&err);
+               }
+               return FALSE;
+       }
+
+       dbus_message_unref(reply);
+
+       DBG(" -\n");
+       return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_registration_status_changed(
+               bt_hfp_agent_network_registration_status_t status)
+{
+       const char *property = g_strdup("RegistrationChanged");
+
+       DBG(" +\n");
+
+       if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+                       TELEPHONY_CSD_INTERFACE,
+                       BT_HFP_AGENT_SET_PROPERTY,
+                       property, DBUS_TYPE_BYTE, &status)) {
+               DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+               g_free((void *)property);
+               return FALSE;
+       }
+       DBG(" -\n");
+
+       g_free((void *)property);
+       return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_operator_name_changed(const char *name)
+{
+       const char *property = g_strdup("OperatorNameChanged");
+
+       DBG(" +\n");
+
+       if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+                       TELEPHONY_CSD_INTERFACE,
+                       BT_HFP_AGENT_SET_PROPERTY,
+                       property, DBUS_TYPE_STRING, &name)) {
+               DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+               g_free((void *)property);
+               return FALSE;
+       }
+       DBG(" -\n");
+       g_free((void *)property);
+       return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_subscriber_number_changed(
+                                                       const char *number)
+{
+       const char *property = g_strdup("SubscriberNumberChanged");
+
+       DBG(" +\n");
+
+       if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+                       TELEPHONY_CSD_INTERFACE,
+                       BT_HFP_AGENT_SET_PROPERTY,
+                       property,
+                       DBUS_TYPE_STRING, &number)) {
+               DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+               g_free((void *)property);
+               return FALSE;
+       }
+
+       DBG(" -\n");
+       g_free((void *)property);
+       return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_signal_bar_changed(int signal_bar)
+{
+       const char *property = g_strdup("SignalBarsChanged");
+
+       DBG(" +\n");
+
+       if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+                       TELEPHONY_CSD_INTERFACE,
+                       BT_HFP_AGENT_SET_PROPERTY,
+                       property, DBUS_TYPE_INT32, &signal_bar)) {
+               DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+               g_free((void *)property);
+               return FALSE;
+       }
+
+       g_free((void *)property);
+       DBG(" -\n");
+       return TRUE;
+}
+
+static gboolean __bt_hfp_agent_send_battery_level_changed(int battery_level)
+{
+       const char *property = g_strdup("BatteryBarsChanged");
+       int battery_status;
+
+       DBG(" +\n");
+
+       /* We need to send battery status ranging from 0-5 */
+       if (battery_level < 5)
+                battery_status = 0;
+       else if (battery_level >= 100)
+               battery_status = 5;
+       else
+               battery_status = battery_level / 20 + 1;
+
+       if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
+                       TELEPHONY_CSD_INTERFACE,
+                       BT_HFP_AGENT_SET_PROPERTY,
+                       property,
+                       DBUS_TYPE_INT32, &battery_status)) {
+               DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
+               g_free((void *)property);
+               return FALSE;
+       }
+
+       DBG(" -\n");
+       g_free((void *)property);
+       return TRUE;
+}
+
+static void __bt_hfp_agent_send_battery_level(void)
+{
+       int ret;
+       int batt;
+
+       DBG(" +\n");
+
+       ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &batt);
+       if (ret != 0) {
+               DBG("vconf_get_int failed err = %d \n", ret);
+               return;
+       }
+
+       DBG("Current battery Level = [%d] \n", batt);
+
+       __bt_hfp_agent_send_battery_level_changed(batt);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_signal_status(void)
+{
+       int ret;
+       int signal_level;
+
+       DBG(" +\n");
+
+       ret = vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &signal_level);
+       if (ret != 0) {
+               DBG("vconf_get_int failed err = %d \n", ret);
+               return;
+       }
+
+       DBG("Current Signal Level = [%d] \n", signal_level);
+
+       __bt_hfp_agent_send_signal_bar_changed(signal_level);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_operator_name(void)
+{
+       char *operator_name;
+
+       DBG(" +\n");
+
+       operator_name = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME);
+       if (NULL == operator_name) {
+               DBG("vconf_get_int failed \n");
+               return;
+       }
+
+       DBG("operator_name  = [%s] \n", operator_name);
+
+       __bt_hfp_agent_send_operator_name_changed(operator_name);
+
+       free(operator_name);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_subscriber_number(void)
+{
+       char *subscriber_number
+               ;
+       DBG(" +\n");
+
+       subscriber_number = vconf_get_str(VCONFKEY_TELEPHONY_SUBSCRIBER_NUMBER);
+       if (NULL == subscriber_number) {
+               DBG("vconf_get_int failed\n");
+               return;
+       }
+
+       DBG("subscriber_number  = [%s] \n", subscriber_number);
+
+       __bt_hfp_agent_send_subscriber_number_changed(subscriber_number);
+
+       free(subscriber_number);
+
+       DBG(" -\n");
+       return;
+}
+
+static void __bt_hfp_agent_network_send( int service, int roam_status)
+{
+       int ret;
+       bt_hfp_agent_network_registration_status_t network_service;
+
+       DBG(" +\n");
+
+       switch (service) {
+       case VCONFKEY_TELEPHONY_SVCTYPE_NONE:
+       case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC:
+       case VCONFKEY_TELEPHONY_SVCTYPE_SEARCH:
+               service = 0;
+               break;
+       default:
+               service = 1;
+               break;
+       }
+
+       ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
+       if (ret != 0) {
+               DBG("Get roaming status failed err = %d\n", ret);
+               return;
+       }
+
+       if (roam_status == 0 && service == 1)
+               network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_HOME;
+       else if (roam_status == 1 && service == 1)
+               network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_ROAMING;
+       else
+               network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_UNKOWN;
+
+       DBG("Network service = %d\n", network_service);
+
+       __bt_hfp_agent_send_registration_status_changed(network_service);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_network_status(void)
+{
+       int ret;
+       int roam_status;
+       int service;
+
+
+       DBG(" +\n");
+
+       ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
+       if (ret != 0) {
+               DBG("vconf_get_int failed for \n");
+               return;
+       }
+
+       DBG("roam_status  = [%d] \n", roam_status);
+
+       ret = vconf_get_int(VCONFKEY_TELEPHONY_SVCTYPE, &service);
+       if (ret != 0) {
+               DBG("vconf_get_int failed\n");
+               return;
+       }
+
+       DBG("service  = [%d] \n", service);
+
+       __bt_hfp_agent_network_send(service, roam_status);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_send_vconf_values(void)
+{
+       __bt_hfp_agent_send_battery_level();
+       __bt_hfp_agent_send_signal_status();
+       __bt_hfp_agent_send_operator_name();
+       __bt_hfp_agent_send_subscriber_number();
+       __bt_hfp_agent_send_network_status();
+}
+
+static void __bt_hfp_agent_battery_status_cb(keynode_t *node)
+{
+       int batt = vconf_keynode_get_int(node);
+
+       DBG(" +\n");
+
+       DBG("Current Battery Level = [%d] \n", batt);
+
+       __bt_hfp_agent_send_battery_level_changed(batt);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_network_signal_status_cb(keynode_t *node)
+{
+       int signal_bar = vconf_keynode_get_int(node);
+
+       DBG(" +\n");
+
+       DBG("Current Signal Level = [%d] \n", signal_bar);
+
+       __bt_hfp_agent_send_signal_bar_changed(signal_bar);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_network_register_status_cb(keynode_t *node)
+{
+       int service = vconf_keynode_get_int(node);
+       int roam_status;
+       int ret;
+
+       DBG(" +\n");
+
+       DBG("Current Signal Level = [%d] \n", service);
+
+       ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
+       if (ret != 0) {
+               DBG("Get roaming status failed err = %d\n", ret);
+               return;
+       }
+
+       __bt_hfp_agent_network_send(service, roam_status);
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_subscribe_vconf_updates(void)
+{
+       int ret;
+
+       DBG(" +\n");
+
+       ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+                               (void *)__bt_hfp_agent_battery_status_cb, NULL);
+       if (0 != ret) {
+               DBG("Subsrciption to battery status failed err =  [%d]\n", ret);
+       }
+
+       ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_RSSI,
+                       (void *)__bt_hfp_agent_network_signal_status_cb, NULL);
+       if (0 != ret) {
+               DBG("Subsrciption to netowrk signal failed err =  [%d]\n", ret);
+       }
+
+       ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
+                       (void *)__bt_hfp_agent_network_register_status_cb, NULL);
+       if (0 != ret) {
+               DBG("Subsrciption to network failed err =  [%d]\n", ret);
+       }
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_release_vconf_updates(void)
+{
+       int ret;
+
+       DBG(" +\n");
+
+       ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+                       (vconf_callback_fn)__bt_hfp_agent_battery_status_cb);
+       if (0 != ret) {
+               DBG("vconf_ignore_key_changed failed\n");
+       }
+
+       ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_RSSI,
+               (vconf_callback_fn)__bt_hfp_agent_network_signal_status_cb);
+       if (0 != ret) {
+               DBG("vconf_ignore_key_changed failed\n");
+       }
+
+       ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
+               (vconf_callback_fn)__bt_hfp_agent_network_register_status_cb);
+       if (0 != ret) {
+               DBG("vconf_ignore_key_changed failed\n");
+       }
+
+       DBG(" -\n");
+}
+
+static void __bt_hfp_agent_sigterm_handler(int signo)
+{
+       DBG("+\n");
+
+       if (gmain_loop)
+               g_main_loop_quit(gmain_loop);
+       else
+               exit(0);
+
+       DBG("-\n");
+}
+
+int main(void)
+{
+       BtHfpAgent *bt_hfp_obj = NULL;
+       DBusGConnection *connection;
+       GError *error = NULL;
+       DBusGProxy *bus_proxy = NULL;
+       guint result;
+       int ret = EXIT_FAILURE;
+       struct sigaction sa;
+
+       g_type_init();
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_flags = SA_NOCLDSTOP;
+       sa.sa_handler = __bt_hfp_agent_sigterm_handler;
+       sigaction(SIGTERM, &sa, NULL);
+       sigaction(SIGINT, &sa, NULL);
+
+       gmain_loop = g_main_loop_new(NULL, FALSE);
+
+       if (gmain_loop == NULL) {
+               ERR("GMainLoop create failed \n");
+               return EXIT_FAILURE;
+       }
+
+       connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+       if (error != NULL) {
+               ERR("Failed connection to system bus[%s] \n", error->message);
+               g_error_free(error);
+               goto fail;
+       }
+
+       bus_proxy = dbus_g_proxy_new_for_name(connection,
+                                       DBUS_SERVICE_DBUS,
+                                       DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+       if (bus_proxy == NULL) {
+               ERR("Failed to get a proxy for D-Bus\n");
+               goto fail;
+       }
+
+       if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING,
+                       BT_HFP_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID,
+                       G_TYPE_UINT, &result, G_TYPE_INVALID)) {
+               if (error != NULL) {
+                       ERR("RequestName RPC failed[%s]\n", error->message);
+                       g_error_free(error);
+               }
+               goto fail;
+       }
+
+       DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+       if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+               ERR("Failed to get the primary well-known name.\n");
+               goto fail;
+       }
+
+       g_object_unref(bus_proxy);
+       bus_proxy = NULL;
+
+       bt_hfp_obj = g_object_new(BT_HFP_TYPE_AGENT, NULL);
+       if (bt_hfp_obj == NULL) {
+               ERR("Failed to create BtHfpAgent instance \n");
+               goto fail;
+       }
+
+       dbus_g_connection_register_g_object(connection,
+               BT_HFP_SERVICE_OBJECT_PATH, G_OBJECT(bt_hfp_obj));
+
+       gconn = dbus_g_connection_get_connection(connection);
+       if (gconn == NULL) {
+               ERR("Failed to get connection \n");
+               goto fail;
+       }
+
+       __bt_hfp_agent_send_vconf_values();
+       __bt_hfp_agent_subscribe_vconf_updates();
+
+       g_main_loop_run(gmain_loop);
+
+       ret = EXIT_SUCCESS;
+fail:
+       __bt_hfp_agent_release_vconf_updates();
+
+       if (bt_hfp_obj) {
+               dbus_g_connection_unregister_g_object(connection,
+                                               G_OBJECT(bt_hfp_obj));
+               g_object_unref(bt_hfp_obj);
+       }
+       if (bus_proxy)
+               g_object_unref(bus_proxy);
+       if (connection)
+               dbus_g_connection_unref(connection);
+       if (gmain_loop) {
+               g_main_loop_unref(gmain_loop);
+       }
+       return ret;
+}
diff --git a/bluetooth-hfp-agent/bluetooth-hfp-agent.h b/bluetooth-hfp-agent/bluetooth-hfp-agent.h
new file mode 100644 (file)
index 0000000..907b505
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Bluetooth-hfp-agent
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             Girishashok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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 __DEF_BT_HFP_AGENT_H_
+#define __DEF_BT_HFP_AGENT_H_
+
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+#define BT_HFP_AGENT_ERROR (__bt_hfp_agent_error_quark())
+
+typedef enum {
+       BT_HFP_AGENT_NETWORK_REG_STATUS_HOME,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_ROAMING,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_OFFLINE,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_SEARCHING,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_NO_SIM,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_POWEROFF,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_POWERSAFE,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_NO_COVERAGE,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_REJECTED,
+       BT_HFP_AGENT_NETWORK_REG_STATUS_UNKOWN,
+} bt_hfp_agent_network_registration_status_t;
+
+typedef enum {
+       BT_HFP_AGENT_ERROR_INTERNAL,
+       BT_HFP_AGENT_ERROR_NOT_AVAILABLE,
+       BT_HFP_AGENT_ERROR_NOT_CONNECTED,
+       BT_HFP_AGENT_ERROR_BUSY,
+       BT_HFP_AGENT_ERROR_INVALID_PARAM,
+       BT_HFP_AGENT_ERROR_ALREADY_EXSIST,
+       BT_HFP_AGENT_ERROR_ALREADY_CONNECTED,
+       BT_HFP_AGENT_ERROR_NO_MEMORY,
+       BT_HFP_AGENT_ERROR_I_O_ERROR,
+       BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE,
+       BT_HFP_AGENT_ERROR_NO_CALL_LOGS,
+       BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX,
+       BT_HFP_AGENT_ERROR_INVALID_CHLD_INDEX,
+       BT_HFP_AGENT_ERROR_BATTERY_STATUS,
+       BT_HFP_AGENT_ERROR_SIGNAL_STATUS,
+       BT_HFP_AGENT_ERROR_NOT_SUPPORTED,
+       BT_HFP_AGENT_ERROR_INVALID_NUMBER,
+       BT_HFP_AGENT_ERROR_APPLICATION,
+       BT_HFP_AGENT_ERROR_INVALID_DTMF,
+       BT_HFP_AGENT_ERROR_NONE,
+} bt_hfp_agent_error_t;
+
+#define BT_HFP_SERVICE_OBJECT_PATH "/org/bluez/hfp_agent"
+#define BT_HFP_SERVICE "org.bluez.hfp_agent"
+
+#define BT_HFP "BT_HFP"
+#define DBG(fmt, args...) SLOG(LOG_DEBUG, BT_HFP, "%s():%d "fmt,\
+                                               __func__, __LINE__, ##args)
+#define ERR(fmt, args...) SLOG(LOG_ERROR, BT_HFP, "%s():%d "fmt,\
+                                               __func__, __LINE__, ##args)
+#endif /* __DEF_BT_HFP_AGENT_H_ */
diff --git a/bluetooth-hfp-agent/hfp_agent.xml b/bluetooth-hfp-agent/hfp_agent.xml
new file mode 100644 (file)
index 0000000..d1f2303
--- /dev/null
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+  <interface name="Org.Hfp.App.Interface">
+
+    <method name="RegisterApplication">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="path"/>
+    </method>
+
+    <method name="UnregisterApplication">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="path"/>
+    </method>
+
+    <method name="IncomingCall">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="path"/>
+      <arg type="s" name="number"/>
+      <arg type="i" name="id"/>
+    </method>
+
+    <method name="OutgoingCall">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="path"/>
+      <arg type="s" name="number"/>
+      <arg type="i" name="id"/>
+    </method>
+
+    <method name="ChangeCallStatus">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="path"/>
+      <arg type="i" name="status"/>
+      <arg type="i" name="id"/>
+    </method>
+
+ </interface>
+
+ <interface name="Org.Hfp.Bluez.Interface">
+
+    <method name="AnswerCall">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+       <arg type="u" name="callid"/>
+       <arg type="s" name="path"/>
+       <arg type="s" name="sender"/>
+    </method>
+
+    <method name="ReleaseCall">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="callid"/>
+      <arg type="s" name="path"/>
+      <arg type="s" name="sender"/>
+    </method>
+
+    <method name="RejectCall">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="callid"/>
+      <arg type="s" name="path"/>
+      <arg type="s" name="sender"/>
+    </method>
+
+    <method name="ThreewayCall">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="value"/>
+      <arg type="s" name="path"/>
+      <arg type="s" name="sender"/>
+    </method>
+
+    <method name="DialLastNum">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+    </method>
+
+    <method name="DialNum">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="Number"/>
+      <arg type="u" name="flags"/>
+    </method>
+
+    <method name="DialMemory">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="i" name="location"/>
+    </method>
+
+    <method name="SendDtmf">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="dtmf"/>
+      <arg type="s" name="path"/>
+      <arg type="s" name="sender"/>
+    </method>
+
+    <method name="VoiceDial">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="b" name="activate"/>
+    </method>
+
+    <method name="GetBatteryStatus">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="i" name="bcl" direction="out"/>
+      <arg type="i" name="bcs" direction="out"/>
+    </method>
+
+    <method name="GetSignalQuality">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="i" name="rssi" direction="out"/>
+      <arg type="i" name="ber" direction="out"/>
+    </method>
+
+  </interface>
+</node>
diff --git a/bluetooth-hfp-agent/org.bluez.hfp_agent.service b/bluetooth-hfp-agent/org.bluez.hfp_agent.service
new file mode 100644 (file)
index 0000000..ec36aa3
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.bluez.hfp_agent
+Exec=/usr/bin/bluetooth-hfp-agent
diff --git a/bluetooth-media-control/CMakeLists.txt b/bluetooth-media-control/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2dee1e8
--- /dev/null
@@ -0,0 +1,47 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bluetooth-media-control C)
+
+SET(SRCS bluetooth-media-control.c)
+SET(HEADERS bluetooth-media-control.h)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include")
+SET(VERSION_MAJOR 1)
+SET(VERSION ${VERSION_MAJOR}.0.0)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(packages REQUIRED dlog dbus-glib-1)
+
+FOREACH(flag ${packages_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g ")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+IF("${ARCH}" STREQUAL "arm")
+       ADD_DEFINITIONS("-DTARGET")
+       MESSAGE("add -DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${packages_LDFLAGS})
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc @ONLY)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig)
+
+FOREACH(hfile ${HEADERS})
+       INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} DESTINATION include/bluetooth-media-control)
+ENDFOREACH(hfile)
diff --git a/bluetooth-media-control/bluetooth-media-control-internal.h b/bluetooth-media-control/bluetooth-media-control-internal.h
new file mode 100644 (file)
index 0000000..a338837
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *   bluetooth-media-control
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             Girishashok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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_MP_CONTROL_INTERNAL_H_
+#define _BT_MP_CONTROL_INTERNAL_H_
+
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <glib.h>
+#include <dlog.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+#ifndef BT_EXPORT_API
+#define BT_EXPORT_API __attribute__((visibility("default")))
+#endif
+
+#define BT_MEDIA_CONTROL "BT_MEDIA_CONTROL"
+#define DBG(fmt, args...) SLOG(LOG_DEBUG, BT_MEDIA_CONTROL, "%s():%d "fmt, __func__, __LINE__, ##args)
+#define ERR(fmt, args...) SLOG(LOG_ERROR, BT_MEDIA_CONTROL, "%s():%d "fmt, __func__, __LINE__, ##args)
+
+/* defines*/
+#define MEDIA_OBJECT_PATH_LENGTH       50
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+
+#endif /*_BT_MP_CONTROL_INTERNAL_H_*/
diff --git a/bluetooth-media-control/bluetooth-media-control.c b/bluetooth-media-control/bluetooth-media-control.c
new file mode 100644 (file)
index 0000000..4b1be3a
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ *   bluetooth-media-control
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             Girishashok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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 <unistd.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <glib.h>
+#include <string.h>
+
+#include "bluetooth-media-control-internal.h"
+#include "bluetooth-media-control.h"
+
+#define BT_ADDRESS_STR_LEN 18
+
+#define BLUEZ "org.bluez"
+#define BLUEZ_AUDIO_SINK "org.bluez.AudioSink"
+
+#define MEDIA_PLAYER_OBJECT_PATH "/Tizen/Player"
+#define MEDIA_PLAYER_INTERFACE "org.tizen.player"
+
+typedef struct {
+       media_cb_func_ptr app_cb;
+       DBusGConnection *conn;
+       DBusConnection *sys_conn;
+       void *user_data;
+} bt_media_info_t;
+
+static bt_media_info_t bt_media_info;
+
+static int __bluetooth_media_dbus_signal_send(const char *path,
+               const char *interface, const char *method, int type, ...)
+{
+       DBusMessage *msg;
+       DBusConnection *conn;
+       va_list args;
+       DBG("+\n");
+
+       conn  = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+       if (NULL == conn)
+               return FALSE;
+
+       msg = dbus_message_new_signal(path, interface, method);
+       if (!msg) {
+               DBG("Unable to allocate new D-Bus %s message", method);
+               dbus_connection_unref(conn);
+               return FALSE;
+       }
+
+       va_start(args, type);
+
+       if (!dbus_message_append_args_valist(msg, type, args)) {
+               dbus_message_unref(msg);
+               va_end(args);
+               dbus_connection_unref(conn);
+               return FALSE;
+       }
+
+       va_end(args);
+
+       if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_SIGNAL)
+               dbus_message_set_no_reply(msg, TRUE);
+
+       if (!dbus_connection_send(conn, msg, NULL)) {
+               DBG("dbus_connection_send - ERROR\n");
+               dbus_message_unref(msg);
+               dbus_connection_unref(conn);
+               return FALSE;
+       }
+       dbus_message_unref(msg);
+       dbus_connection_unref(conn);
+
+       DBG(" -\n");
+       return TRUE;
+}
+
+static void __connection_changed_cb(gboolean connected,
+                                       char *device_addr)
+{
+       media_event_param_t bt_event = { 0, };
+
+       DBG("+");
+
+       bt_event.event = connected ? BT_A2DP_CONNECTED : \
+                               BT_A2DP_DISCONNECTED;
+       bt_event.result = BT_MEDIA_ERROR_NONE;
+       bt_event.param_data = (void *)device_addr;
+
+       if (bt_media_info.app_cb)
+               bt_media_info.app_cb(bt_event.event, &bt_event, bt_media_info.user_data);
+
+       DBG("-");
+}
+
+static DBusHandlerResult __audio_sink_event_filter(
+                                       DBusConnection *conn,
+                                       DBusMessage *msg,
+                                       void *data)
+{
+       const char *path = dbus_message_get_path(msg);
+       char address[BT_ADDRESS_STR_LEN] = {0,};
+       char *dev_addr = NULL;
+       DBusMessageIter item_iter;
+       DBusMessageIter value_iter;
+       const char *property;
+
+       if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (!dbus_message_is_signal(msg, BLUEZ_AUDIO_SINK, "PropertyChanged"))
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (path != NULL) {
+               if (strcmp(path, "/") == 0) {
+                       __connection_changed_cb(FALSE, NULL);
+                       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+               }
+               dev_addr = strstr(path, "dev_");
+       }
+
+       if (dev_addr != NULL) {
+               dev_addr += 4;
+               g_strlcpy(address, dev_addr, sizeof(address));
+               g_strdelimit(address, "_", ':');
+               DBG("address is %s \n", address);
+       }
+
+       dbus_message_iter_init(msg, &item_iter);
+
+       if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
+               DBG("This is bad format dbus\n");
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       dbus_message_iter_get_basic(&item_iter, &property);
+       DBG("Property (%s)\n", property);
+
+       if (property == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (!strcmp(property, "Connected")) {
+               gboolean connected;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &connected);
+
+               __connection_changed_cb(connected, address);
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+BT_EXPORT_API int bluetooth_media_player_init(media_cb_func_ptr callback_ptr,
+                                               void *user_data)
+{
+       GError *err = NULL;
+
+       DBusError dbus_error;
+
+       DBG("+");
+
+       if (bt_media_info.conn != NULL) {
+               DBG("Already initilize");
+               bt_media_info.app_cb = callback_ptr;
+               bt_media_info.user_data = user_data;
+               return BT_MEDIA_ERROR_ALREADY_INITIALIZED;
+       }
+
+       bt_media_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
+
+       if (!bt_media_info.conn) {
+               DBG("Can not get DBUS Gconnection [%s]\n", err->message);
+               g_error_free(err);
+               goto error;
+       }
+
+       bt_media_info.sys_conn = dbus_g_connection_get_connection(bt_media_info.conn);
+
+       dbus_error_init(&dbus_error);
+       dbus_connection_add_filter(bt_media_info.sys_conn,
+                                  __audio_sink_event_filter, NULL,
+                                  NULL);
+       dbus_bus_add_match(bt_media_info.sys_conn,
+                          "type='signal',interface='"
+                          BLUEZ_AUDIO_SINK
+                          "',member='PropertyChanged'", &dbus_error);
+
+       if (dbus_error_is_set(&dbus_error)) {
+               DBG("Fail to add dbus filter signal\n");
+               dbus_error_free(&dbus_error);
+               goto error;
+       }
+
+       DBG("-\n");
+
+       bt_media_info.app_cb = callback_ptr;
+       bt_media_info.user_data = user_data;
+
+       return BT_MEDIA_ERROR_NONE;
+ error:
+       if (bt_media_info.conn) {
+               dbus_g_connection_unref(bt_media_info.conn);
+               bt_media_info.conn = NULL;
+       }
+
+       bt_media_info.sys_conn = NULL;
+       return BT_MEDIA_ERROR_INTERNAL;
+
+}
+
+BT_EXPORT_API int bluetooth_media_player_deinit(void)
+{
+       DBG("+");
+
+       if (bt_media_info.sys_conn) {
+               dbus_connection_remove_filter(bt_media_info.sys_conn,
+                                             __audio_sink_event_filter,
+                                             NULL);
+               bt_media_info.sys_conn = NULL;
+       }
+
+       if (bt_media_info.conn) {
+               dbus_g_connection_unref(bt_media_info.conn);
+               bt_media_info.conn = NULL;
+       }
+
+       bt_media_info.app_cb = NULL;
+       bt_media_info.user_data = NULL;
+
+       DBG("-");
+       return BT_MEDIA_ERROR_NONE;
+}
+
+
+BT_EXPORT_API int bluetooth_media_player_change_property(
+                       media_player_property_type type,
+                       unsigned int value)
+{
+       DBG("+\n");
+
+       if (type > POSITION)
+               return BT_MEDIA_ERROR_INTERNAL;
+
+       switch (type) {
+       case EQUILIZER:
+               if (value >= EQUILIZER_INVALID) {
+                       return BT_MEDIA_ERROR_INTERNAL;
+               }
+               break;
+       case REPEAT:
+               if (value >= REPEAT_INVALID) {
+                       return BT_MEDIA_ERROR_INTERNAL;
+               }
+               break;
+       case SHUFFLE:
+               if (value >= SHUFFLE_INVALID) {
+                       return BT_MEDIA_ERROR_INTERNAL;
+               }
+               break;
+       case SCAN:
+               if (value >= SCAN_INVALID) {
+                       return BT_MEDIA_ERROR_INTERNAL;
+               }
+               break;
+       case STATUS:
+               if (value >= STATUS_INVALID) {
+                       return BT_MEDIA_ERROR_INTERNAL;
+               }
+               break;
+       case POSITION:
+               if (0 == value) {
+                       return BT_MEDIA_ERROR_INTERNAL;
+               }
+               break;
+       }
+
+       if (!__bluetooth_media_dbus_signal_send(
+               MEDIA_PLAYER_OBJECT_PATH,
+               MEDIA_PLAYER_INTERFACE,
+               "PropertyChanged",
+               DBUS_TYPE_UINT32, &type,
+               DBUS_TYPE_UINT32, &value,
+               DBUS_TYPE_INVALID)) {
+               DBG("Error sending the PropertyChanged signal \n");
+               return BT_MEDIA_ERROR_INTERNAL;
+       }
+
+       DBG("-\n");
+       return BT_MEDIA_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_media_player_set_properties(
+                       media_player_settings_t *setting)
+{
+       DBG("+\n");
+
+       unsigned int type = 0;
+       unsigned int value = 0;
+
+       if (setting == NULL) {
+               DBG("setting is NULL");
+               return BT_MEDIA_ERROR_INTERNAL;
+       }
+
+       if (setting->equilizer < EQUILIZER_INVALID) {
+               type = EQUILIZER;
+               value = (unsigned int)setting->equilizer;
+
+               if (!__bluetooth_media_dbus_signal_send(
+                       MEDIA_PLAYER_OBJECT_PATH,
+                       MEDIA_PLAYER_INTERFACE,
+                       "PropertyChanged",
+                       DBUS_TYPE_UINT32, &type,
+                       DBUS_TYPE_UINT32, &value,
+                       DBUS_TYPE_INVALID)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+       }
+
+       if (setting->repeat < REPEAT_INVALID) {
+               type = REPEAT;
+               value = (unsigned int)setting->repeat;
+
+               if (!__bluetooth_media_dbus_signal_send(
+                       MEDIA_PLAYER_OBJECT_PATH,
+                       MEDIA_PLAYER_INTERFACE,
+                       "PropertyChanged",
+                       DBUS_TYPE_UINT32, &type,
+                       DBUS_TYPE_UINT32, &value,
+                       DBUS_TYPE_INVALID)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+       }
+
+       if (setting->shuffle < SHUFFLE_INVALID) {
+               type = SHUFFLE;
+               value = (unsigned int)setting->shuffle;
+
+               if (!__bluetooth_media_dbus_signal_send(
+                       MEDIA_PLAYER_OBJECT_PATH,
+                       MEDIA_PLAYER_INTERFACE,
+                       "PropertyChanged",
+                       DBUS_TYPE_UINT32, &type,
+                       DBUS_TYPE_UINT32, &value,
+                       DBUS_TYPE_INVALID)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+       }
+
+       if (setting->scan < SCAN_INVALID) {
+               type = SCAN;
+               value = (unsigned int)setting->scan;
+
+               if (!__bluetooth_media_dbus_signal_send(
+                       MEDIA_PLAYER_OBJECT_PATH,
+                       MEDIA_PLAYER_INTERFACE,
+                       "PropertyChanged",
+                       DBUS_TYPE_UINT32, &type,
+                       DBUS_TYPE_UINT32, &value,
+                       DBUS_TYPE_INVALID)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+       }
+
+       if (setting->status < STATUS_INVALID) {
+               type = STATUS;
+               value = (unsigned int)setting->status;
+
+               if (!__bluetooth_media_dbus_signal_send(
+                       MEDIA_PLAYER_OBJECT_PATH,
+                       MEDIA_PLAYER_INTERFACE,
+                       "PropertyChanged",
+                       DBUS_TYPE_UINT32, &type,
+                       DBUS_TYPE_UINT32, &value,
+                       DBUS_TYPE_INVALID)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+       }
+
+       if (0 != setting->position) {
+               type = POSITION;
+               value = (unsigned int)setting->position;
+
+               if (!__bluetooth_media_dbus_signal_send(
+                       MEDIA_PLAYER_OBJECT_PATH,
+                       MEDIA_PLAYER_INTERFACE,
+                       "PropertyChanged",
+                       DBUS_TYPE_UINT32, &type,
+                       DBUS_TYPE_UINT32, &value,
+                       DBUS_TYPE_INVALID)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+
+       }
+
+       DBG("-\n");
+       return BT_MEDIA_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_media_player_change_track(
+               media_metadata_attributes_t *metadata)
+{
+       DBG("+\n");
+
+       if (metadata == NULL) {
+               DBG("metadata is NULL");
+               return BT_MEDIA_ERROR_INTERNAL;
+       }
+
+       if (!__bluetooth_media_dbus_signal_send(
+               MEDIA_PLAYER_OBJECT_PATH,
+               MEDIA_PLAYER_INTERFACE,
+               "TrackChanged",
+               DBUS_TYPE_STRING, &metadata->title,
+               DBUS_TYPE_STRING, &metadata->artist,
+               DBUS_TYPE_STRING, &metadata->album,
+               DBUS_TYPE_STRING, &metadata->genre,
+               DBUS_TYPE_UINT32, &metadata->total_tracks,
+               DBUS_TYPE_UINT32, &metadata->number,
+               DBUS_TYPE_UINT32, &metadata->duration,
+               DBUS_TYPE_INVALID)) {
+               DBG("Error sending the PropertyChanged signal \n");
+               return BT_MEDIA_ERROR_INTERNAL;
+       }
+
+       DBG("-\n");
+       return BT_MEDIA_ERROR_NONE;
+}
diff --git a/bluetooth-media-control/bluetooth-media-control.h b/bluetooth-media-control/bluetooth-media-control.h
new file mode 100644 (file)
index 0000000..afb4f5b
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ *   bluetooth-media-control
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             Girishashok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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_MP_CONTROL_H_
+#define _BT_MP_CONTROL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+#define BT_MEDIA_ERROR_NONE ((int)0)
+
+#define BT_MEDIA_ERROR_BASE ((int)0)
+#define BT_MEDIA_ERROR_INTERNAL ((int)BT_MEDIA_ERROR_BASE - 0x01)
+#define BT_MEDIA_ERROR_ALREADY_INITIALIZED ((int)BT_MEDIA_ERROR_BASE - 0x02)
+
+
+typedef enum {
+       EQUILIZER = 0x00,
+       REPEAT,
+       SHUFFLE,
+       SCAN,
+       STATUS,
+       POSITION
+} media_player_property_type;
+
+typedef enum {
+       EQUILIZER_OFF = 0x01,
+       EQUILIZER_ON,
+       EQUILIZER_INVALID,
+} media_player_equilizer_status;
+
+typedef enum {
+       REPEAT_MODE_OFF = 0x01,
+       REPEAT_SINGLE_TRACK,
+       REPEAT_ALL_TRACK,
+       REPEAT_GROUP,
+       REPEAT_INVALID,
+} media_player_repeat_status;
+
+typedef enum {
+       SHUFFLE_MODE_OFF = 0x01,
+       SHUFFLE_ALL_TRACK,
+       SHUFFLE_GROUP,
+       SHUFFLE_INVALID,
+} media_player_shuffle_status;
+
+typedef enum {
+       SCAN_MODE_OFF = 0x01,
+       SCAN_ALL_TRACK,
+       SCAN_GROUP,
+       SCAN_INVALID,
+} media_player_scan_status;
+
+typedef enum {
+       STATUS_STOPPED  = 0x00,
+       STATUS_PLAYING,
+       STATUS_PAUSED,
+       STATUS_FORWARD_SEEK,
+       STATUS_REVERSE_SEEK,
+       STATUS_ERROR,
+       STATUS_INVALID
+} media_player_status;
+
+typedef struct {
+       media_player_equilizer_status equilizer;
+       media_player_repeat_status  repeat;
+       media_player_shuffle_status  shuffle;
+       media_player_scan_status scan;
+       media_player_status status;
+       unsigned int position;
+} media_player_settings_t;
+
+typedef struct {
+       const char *title;
+       const char *artist;
+       const char *album;
+       const char *genre;
+       unsigned int total_tracks;
+       unsigned int number;
+       unsigned int duration;
+} media_metadata_attributes_t;
+
+typedef enum {
+       BT_A2DP_CONNECTED,
+       BT_A2DP_DISCONNECTED
+} media_event_t;
+
+typedef struct {
+       int event;
+       int result;
+       void *param_data;
+       void *user_data;
+} media_event_param_t;
+
+typedef void (*media_cb_func_ptr)(int, media_event_param_t*, void*);
+
+
+/**
+ * @fn int bluetooth_media_player_init(media_cb_func_ptr callback_ptr, void *user_data)
+ * @brief Initialize AVRCP service and register the callback
+ *
+ * This function is a synchronous call.
+ *
+ * @param[in]   callback_ptr - Callback function (A2DP connected / Disconnected)
+ * @param[in]   user_data - User data
+ *
+ * @return  BT_MEDIA_ERROR_NONE  - Success \n
+ *              BT_MEDIA_ERROR_ALREADY_INITIALIZED   - Already initialized \n
+ *              BT_MEDIA_ERROR_INTERNAL  - Internal error \n
+ *
+ * @remark      None
+ *
+ */
+int bluetooth_media_player_init(media_cb_func_ptr callback_ptr,
+                                       void *user_data);
+
+/**
+ * @fn int bluetooth_media_player_deinit(void)
+ * @brief Deinitialize AVRCP service and register the callback
+ *
+ * This function is a synchronous call.
+ *
+ * @return  BT_MEDIA_CONTROL_SUCCESS  - Success \n
+ *              BT_MEDIA_CONTROL_ERROR - Error \n
+ *
+ * @remark      None
+ *
+ */
+int bluetooth_media_player_deinit(void);
+
+/**
+ * @fn int bluetooth_media_player_set_properties(media_player_settings_t *setting)
+ * @brief Notifies the remote bluetooth headset with change in music player settings
+ *
+ * This function is a asynchronous call.
+ * No event for this api..
+ *
+ * @return  BT_MEDIA_CONTROL_SUCCESS  - Success \n
+ *              BT_MEDIA_CONTROL_ERROR - Error \n
+ *
+ * @exception   None
+ * @param[in]   setting - The music player properties
+ *
+ * @remark       None
+ * @see         None
+ */
+int bluetooth_media_player_set_properties(
+                       media_player_settings_t *setting);
+
+/**
+ * @fn int bluetooth_media_player_change_property(media_player_property_type type,
+ *                             unsigned int value);
+ * @brief Notifies the remote bluetooth headset with change in music player settings
+ *
+ * This function is a asynchronous call.
+ * No event for this api..
+ *
+ * @return  BT_MEDIA_CONTROL_SUCCESS  - Success \n
+ *              BT_MEDIA_CONTROL_ERROR - Error \n
+ *
+ * @exception   None
+ * @param[in]   type - Type of the music player property
+ *                      value - Value of the property which is changed
+ *
+ * @remark       None
+ * @see         None
+ */
+int bluetooth_media_player_change_property(
+                       media_player_property_type type,
+                       unsigned int value);
+
+/**
+ * @fn int bluetooth_media_player_change_track(media_metadata_attributes_t metadata)
+ * @briefNotifies the remote bluetooth headset with change in media attributes of the track
+ *
+ * This function is a asynchronous call.
+ * No event for this api..
+ *
+ * @return  BT_MEDIA_CONTROL_SUCCESS  - Success \n
+ *              BT_MEDIA_CONTROL_ERROR - Error \n
+ *
+ * @exception   None
+ * @param[in]    metadata -Meida attributes
+ *
+ * @remark       None
+ * @see         None
+ */
+int bluetooth_media_player_change_track(
+                       media_metadata_attributes_t *metadata);
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+
+#endif /*_BT_MP_CONTROL_H_*/
diff --git a/bluetooth-media-control/bluetooth-media-control.pc.in b/bluetooth-media-control/bluetooth-media-control.pc.in
new file mode 100644 (file)
index 0000000..b50d952
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: bluetooth-media-control
+Description: Tizen Linux platform Bluetooth framework API
+Version: @VERSION@
+Requires: dlog dbus-glib-1 vconf
+Libs: -L${libdir} -lbluetooth-media-control
+Cflags: -I${includedir} -I${includedir}/bluetooth-media-control
diff --git a/bluetooth-pb-agent/bluetooth_pb_vcard.c b/bluetooth-pb-agent/bluetooth_pb_vcard.c
new file mode 100644 (file)
index 0000000..3b72561
--- /dev/null
@@ -0,0 +1,2126 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
+ *              Girishashok Joshi <girish.joshi@samsung.com>
+ *              Chanyeol Park <chanyeol.park@samsung.com>
+ *              Jaekyun Lee <jkyun.lee@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 <time.h>
+#include <string.h>
+#include <stdarg.h>
+
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+
+#include <dlog.h>
+#include <contacts-svc-struct.h>
+
+#include "vconf.h"
+#include "vconf-keys.h"
+
+#include "bluetooth_pb_vcard.h"
+
+#define BT_PB_AGENT    "BT_PB_AGENT"
+#define DBG(fmt, args...) SLOG(LOG_DEBUG, BT_PB_AGENT, "%s():%d "fmt, __func__, __LINE__, ##args)
+#define ERR(fmt, args...) SLOG(LOG_ERROR, BT_PB_AGENT, "%s():%d "fmt, __func__, __LINE__, ##args)
+
+#define VCARD_FORMAT_2_1 0x0
+#define VCARD_FORMAT_3_0 0x1
+
+#define VCARD_VERSION  (0x1)
+#define VCARD_FN       (0x1 << 1)      /* CTS_CF_NAME_VALUE: NAME_VALUE - CTS_NAME_VAL_DISPLAY_STR */
+#define VCARD_N                (0x1 << 2)      /* CTS_CF_NAME_VALUE: NAME_VALUE -
+                                       CTS_NAME_VAL_FIRST_STR, CTS_NAME_VAL_LAST_STR,
+                                       CTS_NAME_VAL_ADDITION_STR, CTS_NAME_VAL_SUFFIX_STR,
+                                       CTS_NAME_VAL_PREFIX_STR */
+#define VCARD_PHOTO    (0x1 << 3)      /* CTS_CF_BASE_INFO_VALUE: BASEVALUE - CTS_BASE_VAL_IMG_PATH_STR*/
+#define VCARD_BDAY     (0x1 << 4)      /* CTS_CF_EVENT_LIST: EVENTTYPE - CTS_EVENT_TYPE_BIRTH */
+#define VCARD_ADR      (0x1 << 5)      /* CTS_CF_POSTAL_ADDR_LIST: */
+#define VCARD_LABEL    (0x1 << 6)      /* not supported */
+#define VCARD_TEL      (0x1 << 7)      /* CTS_CF_NUMBER_LIST: */
+#define VCARD_EMAIL    (0x1 << 8)      /* CTS_CF_EMAIL_LIST: */
+#define VCARD_MAILER   (0x1 << 9)      /* not supported */
+#define VCARD_TZ       (0x1 << 10)     /* not supported */
+#define VCARD_GEO      (0x1 << 11)     /* not supported */
+#define VCARD_TITLE    (0x1 << 12)     /* CTS_CF_COMPANY_VALUE: COMPANYVALUE - CTS_COMPANY_VAL_JOB_TITLE_STR */
+#define VCARD_ROLE     (0x1 << 13)     /* CTS_CF_COMPANY_VALUE: COMPANYVALUE - CTS_COMPANY_VAL_ROLE_STR */
+#define VCARD_LOGO     (0x1 << 14)     /* not supported */
+#define VCARD_AGENT    (0x1 << 15)     /* not supported */
+#define VCARD_ORG      (0x1 << 16)     /* CTS_CF_COMPANY_VALUE: COMAPNYVALUE - CTS_COMPANY_VAL_NAME_STR */
+#define VCARD_NOTE     (0x1 << 17)     /* CTS_CF_BASE_INFO_VALUE: BASEVALUE - CTS_BASE_VAL_NOTE_STR */
+#define VCARD_REV      (0x1 << 18)     /* CTS_CF_BASE_INFO_VALUE: BASEVALUE - CTS_BASE_VAL_CHANGED_TIME_INT */
+#define VCARD_SOUND    (0x1 << 19)     /* not supported */
+#define VCARD_URL      (0x1 << 20)     /* CTS_CF_WEB_ADDR_LIST: */
+#define VCARD_UID      (0x1 << 21)     /* CTS_CF_BASE_INFO_VALUE: BASEVALUE - CTS_BASE_VAL_UID_STR */
+#define VCARD_KEY      (0x1 << 22)     /* not supported */
+#define VCARD_NICKNAME (0x1 << 23)     /* CTS_CF_NICKNAME_LIST: */
+#define VCARD_CATEGORIES       (0x1 << 24)     /* not supported */
+#define VCARD_PROID    (0x1 << 25)     /* not supported */
+#define VCARD_CLASS    (0x1 << 26)     /* not supported */
+#define VCARD_SORT_STRING      (0x1 << 27)     /* not supported */
+
+#define VCARD_X_IRMC_CALL_DATETIME     (0x1 << 28)
+
+#define QP_ENC_LEN     3
+#define LINEBREAK_LEN  75
+
+
+static gchar *__bluetooth_pb_vcard_escape(const gchar *str);
+
+static gchar *__bluetooth_pb_vcard_strv_concat(gchar **strv,
+                                       const gchar *delimeter);
+
+
+static gboolean __bluetooth_pb_vcard_qp_encode_check(const gchar *str);
+
+static gint __bluetooth_pb_vcard_qp_encode_strlen(const gchar *str,
+                                               gint len);
+
+static void __bluetooth_pb_vcard_qp_encode_append_to_hex(GString *string,
+                                                       const gchar *str,
+                                                       gint len,
+                                                       gint *line_pos);
+
+static void __bluetooth_pb_vcard_qp_encode_append_printable_c(GString *string,
+                                                       gchar ch,
+                                                       gint *line_pos);
+
+static void __bluetooth_pb_vcard_qp_encode_append(GString *string,
+                                               const gchar *str,
+                                               gint len,
+                                               gint *line_pos);
+
+static gchar *__bluetooth_pb_vcard_qp_encode(const gchar *str);
+
+static gchar *__bluetooth_pb_vcard_owner(guint64 filter,
+                                       guint8 format);
+
+static void __bluetooth_pb_vcard_append_param_v21(GString *string,
+                                                const gchar *param);
+
+static void __bluetooth_pb_vcard_append_qp_encode_v21(GString *string,
+                                       const gchar *name,
+                                       const gchar *param,
+                                       const gchar *value);
+
+static void __bluetooth_pb_vcard_append_base64_encode_v21(GString *string,
+                                                       const gchar *name,
+                                                       const gchar *param,
+                                                       const gchar *value,
+                                                       gsize len,
+                                                       gboolean folding);
+
+static void __bluetooth_pb_vcard_append_n_v21(GString *string,
+                                       CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_tel_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_fn_v21(GString *string,
+                                       CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_photo_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_bday_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_adr_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_email_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_title_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_role_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_org_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_note_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_rev_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_url_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_uid_v21(GString *string,
+                                               CTSstruct *contact);
+
+static void __bluetooth_pb_vcard_append_v30(GString *string,
+                                       const gchar *name,
+                                       const gchar *param,
+                                       const gchar *value);
+
+static void __bluetooth_pb_vcard_remove_v30(GString *string,
+                                       const gchar *property_name);
+
+static gchar *__bluetooth_pb_vcard_filter_v30(const gchar *vcard,
+                                       guint64 filter);
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v21(gint contact_id,
+                                                       gint phonelog_id,
+                                                       guint64 filter,
+                                                       const gchar *first_name,
+                                                       va_list args);
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v30(gint contact_id,
+                                                       gint phonelog_id,
+                                                       guint64 filter,
+                                                       const gchar *first_name,
+                                                       va_list args);
+
+static gchar *__bluetooth_pb_vcard_real_contact_with_properties(gint contact_id,
+                                                               gint phonelog_id,
+                                                               guint64 filter,
+                                                               guint8 format,
+                                                               const gchar *first_name,
+                                                               ...);
+
+static gchar *__bluetooth_pb_vcard_real_call_v21(gint phonelog_id,
+                                               guint filter,
+                                               const gchar *attr);
+
+static gchar *__bluetooth_pb_vcard_real_call_v30(gint phonelog_id,
+                                               guint filter,
+                                               const gchar *attr);
+
+static gchar *__bluetooth_pb_vcard_real_call(gint phonelog_id,
+                                       guint filter,
+                                       guint8 format,
+                                       const gchar *attr);
+
+static gchar **__bluetooth_pb_contact_add_field_str(CTSvalue *value,
+                                               int *field,
+                                               gint field_size);
+
+static gchar **__bluetooth_pb_contact_tel_param(CTSvalue *value);
+
+static gchar *__bluetooth_pb_contact_photo_type(const gchar *filename);
+
+static gchar **__bluetooth_pb_contact_addr(CTSvalue *value);
+
+static gchar **__bluetooth_pb_contact_addr_param(CTSvalue *value);
+
+static gchar *__bluetooth_pb_phonelog_datetime(gint phonelog_id);
+
+static gchar *__bluetooth_pb_fn_from_contact(CTSstruct *contact);
+
+static gchar *__bluetooth_pb_name_from_contact(CTSstruct *contact);
+
+static gchar *__bluetooth_pb_number_from_contact(CTSstruct *contact);
+
+static gint __bluetooth_pb_contact_id_from_phonelog_id(gint phonelog_id);
+
+static gchar *__bluetooth_pb_vcard_escape(const gchar *str)
+{
+       GString *escaped;
+
+       gchar *st = NULL;
+       gchar *pos = NULL;
+
+       if (str == NULL)
+               return NULL;
+
+       escaped = g_string_new(NULL);
+
+       st = (gchar *)str;
+       pos = st;
+
+       while (*pos != '\0') {
+               if (*pos == ';') {
+                       g_string_append_len(escaped, st, (pos - st));
+                       g_string_append(escaped, "\\;");
+
+                       pos++;
+                       st = pos;
+               }
+               else {
+                       pos++;
+               }
+       }
+
+       g_string_append_len(escaped, st, (pos - st));
+       return g_string_free(escaped, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_strv_concat(gchar **strv,
+                                       const gchar *separator)
+{
+       GString *string = g_string_new(NULL);
+       gint i;
+
+       for (i = 0; strv[i] != NULL; i++) {
+               if (i > 0)
+                       g_string_append(string, ";");
+
+               g_string_append(string, strv[i]);
+       }
+
+       return g_string_free(string, FALSE);
+}
+
+static gboolean __bluetooth_pb_vcard_qp_encode_check(const gchar *str)
+{
+       gchar *pos = NULL;
+
+       if (str == NULL)
+               return FALSE;
+
+       pos = (gchar *)str;
+       while (*pos != '\0') {
+               /* ascii code  ' ' : 32, '~' : 126 */
+               if ((guchar)*pos < ' ' || (guchar)*pos > '~')
+                       return TRUE;
+
+               pos++;
+       }
+       return FALSE;
+}
+
+/* get string length, which convert to quoted-printable encoding */
+static gint __bluetooth_pb_vcard_qp_encode_strlen(const gchar *str,
+                                               gint len)
+{
+       gchar *pos;
+
+       gint count = 0;
+       gint length = len;
+
+       if (str == NULL)
+               return 0;
+
+       if (strlen(str) < len )
+               length = -1;
+
+       pos = (gchar *)str;
+
+       while (*pos != '\0' && (((pos - str) < length) || length < 0)) {
+               if ((guchar)*pos == '\t') {
+                       count++;
+                       pos++;
+                       continue;
+               }
+
+               if ((guchar)*pos < ' ' || (guchar)*pos == '=') {
+                       count += QP_ENC_LEN;
+                       pos++;
+                       continue;
+               }
+
+               /* check no-ascii utf-8 character */
+               if ((guchar)*pos > '~') {
+
+                       gchar *next;
+
+                       next = g_utf8_next_char(pos);
+
+                       count += QP_ENC_LEN * (next - pos);
+                       pos = next;
+                       continue;
+               }
+
+               pos++;
+               count++;
+       }
+
+       return count;
+}
+
+/* convert to quoted printable code */
+static void __bluetooth_pb_vcard_qp_encode_append_to_hex(GString *string,
+                                                       const gchar *str,
+                                                       gint len,
+                                                       gint *line_pos)
+{
+       int i;
+
+       if (str == NULL || len == 0)
+               return;
+
+       /* add soft linebreak when it exceed */
+       if ((*line_pos + (QP_ENC_LEN * len) > LINEBREAK_LEN)) {
+               g_string_append(string, "=\r\n");
+               *line_pos = 0;
+       }
+
+       for (i = 0; i < len; i++) {
+               g_string_append_printf(string, "=%02X", (guchar)*(str+i));
+               *line_pos += QP_ENC_LEN;
+       }
+}
+
+/* append plain visiable ascii character */
+static void __bluetooth_pb_vcard_qp_encode_append_printable_c(GString *string,
+                                                       gchar ch,
+                                                       gint *line_pos)
+{
+       /* add soft linebreak when it exceed */
+       if (*line_pos + 1 > LINEBREAK_LEN) {
+               g_string_append(string, "=\r\n");
+               *line_pos = 0;
+       }
+       g_string_append_c(string, ch);
+       (*line_pos)++;
+}
+
+static void __bluetooth_pb_vcard_qp_encode_append(GString *string,
+                                               const gchar *str,
+                                               gint len,
+                                               gint *line_pos)
+{
+       gint length;
+       gint encode_len;
+
+       gint i = 0;
+
+       if (string == NULL)
+               return;
+
+       encode_len = __bluetooth_pb_vcard_qp_encode_strlen(str, len);
+
+       /* add soft linebreak when it exceed */
+       if (((*line_pos + encode_len) > LINEBREAK_LEN) && (*line_pos > 1)) {
+               g_string_append(string, "=\r\n");
+               *line_pos = 0;
+       }
+
+       length = strlen(str);
+       if (length > len)
+               length = len;
+
+       while (i < len) {
+               gchar *pos;
+
+               pos = ((gchar *)str) + i;
+
+               /* converts invisiable character and escape character '=' to quoted-printable */
+               if ((guchar)*pos != '\t' &&
+                               ((guchar)*pos < ' ' || (guchar)*pos == '=')) {
+                       __bluetooth_pb_vcard_qp_encode_append_to_hex(string, pos,
+                                       1, line_pos);
+                       i++;
+
+                       continue;
+               }
+
+               /* converts non-ascii utf-8 character to quoted-printable */
+               if ((guchar)*pos > '~') {
+                       gchar *next;
+                       int ch_len;
+
+                       next = g_utf8_next_char(pos);
+
+                       ch_len = next - pos;
+                       __bluetooth_pb_vcard_qp_encode_append_to_hex(string, pos,
+                                       ch_len, line_pos);
+                       i += ch_len;
+
+                       continue;
+               }
+
+               __bluetooth_pb_vcard_qp_encode_append_printable_c(string, *pos, line_pos);
+               i++;
+       }
+}
+
+static gchar* __bluetooth_pb_vcard_qp_encode(const gchar *str)
+{
+       GString *enc;
+
+       gchar *st_pos;
+       gchar *pos;
+
+       gint line_pos = 0;
+
+       if (str == NULL)
+               return NULL;
+
+       enc = g_string_new(NULL);
+
+       st_pos = (gchar *)str;
+       pos = (gchar *)str;
+
+       while (*pos != '\0') {
+               /* split string with given delimeter  ' ' or  '\t' */
+               if (*pos == ' '  || *pos == '\t') {
+                       __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
+                                       (pos - st_pos), &line_pos);
+
+                       st_pos = pos;
+                       pos++;
+
+                       continue;
+               }
+
+               /* split string with given delimeter '\r', '\n' or '\r\n' - newline */
+               if (*pos == '\r' || *pos == '\n' ) {
+                       __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
+                                       (pos - st_pos), &line_pos);
+
+                       /* convers newline to qp_encode with soft linebreak
+                        for example, converts \r\n to  =0D=0A=\r\n */
+                       __bluetooth_pb_vcard_qp_encode_append_to_hex(enc, "\r\n",
+                                       2, &line_pos);
+                       g_string_append(enc, "=\r\n ");
+
+                       line_pos = 1;
+
+                       if (*pos == '\r' && *(pos + 1) == '\n')
+                               pos += 2;
+                       else
+                               pos++;
+
+                       st_pos = pos;
+
+                       continue;
+               }
+
+               pos++;
+       }
+
+       __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
+                       (pos - st_pos), &line_pos);
+
+       return g_string_free(enc, FALSE);
+}
+
+
+/* FIXME: only telephony number we have, filter does not support yet */
+static gchar *__bluetooth_pb_vcard_owner(guint64 filter,
+                               guint8 format)
+{
+       GString *str = g_string_new("BEGIN:VCARD\r\n");
+       gchar *number;
+
+       number = _bluetooth_pb_number_owner();
+
+       if (number == NULL)
+               ERR("can not get vconf value from VCONFKEY_TELEPHONY_SUBSCRIBER_NUMBER\n");
+
+       switch (format) {
+       case VCARD_FORMAT_3_0:
+               g_string_append(str, "VERSION:3.0\r\n");
+               __bluetooth_pb_vcard_append_v30(str, "TEL", "TYPE=CELL", number);
+               break;
+       case VCARD_FORMAT_2_1:
+       default :
+               g_string_append(str, "VERSION:2.1\r\n");
+               __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "CELL", number);
+               break;
+
+       }
+
+       g_string_append(str, "END:VCARD\r\n");
+       g_free(number);
+
+       return g_string_free(str, FALSE);
+}
+
+static void __bluetooth_pb_vcard_append_param_v21(GString *string,
+                                                const gchar *param)
+{
+       gchar *pos = NULL;
+
+       if (param == NULL)
+               return;
+
+       pos = (gchar *)param;
+
+       while (*pos != '\0') {
+               if (*pos != ';')
+                       break;
+
+               pos++;
+       }
+
+       if (*pos != '\0')
+               g_string_append_printf(string, ";%s", pos);
+}
+
+static void __bluetooth_pb_vcard_append_qp_encode_v21(GString *string,
+                                               const gchar *name,
+                                               const gchar *param,
+                                               const gchar *value)
+{
+       GString *property = NULL;
+
+       if (name == NULL)
+               return;
+
+       property = g_string_new(name);
+       __bluetooth_pb_vcard_append_param_v21(property, param);
+
+       if (__bluetooth_pb_vcard_qp_encode_check(value)) {
+               gchar *enc = NULL;
+
+               __bluetooth_pb_vcard_append_param_v21(property,
+                               "ENCODING=QUOTED-PRINTABLE");
+               __bluetooth_pb_vcard_append_param_v21(property,
+                               "CHARSET=utf-8");
+               g_string_append(property, ":");
+
+               enc = __bluetooth_pb_vcard_qp_encode(value);
+
+               if (enc) {
+                       g_string_append(property, enc);
+                       g_free(enc);
+               }
+       } else {
+               g_string_append(property, ":");
+               if (value)
+                       g_string_append(property , value);
+       }
+
+       g_string_append_printf(string, "%s\r\n", property->str);
+
+       g_string_free(property, TRUE);
+}
+
+
+static void __bluetooth_pb_vcard_append_base64_encode_v21(GString *string,
+                                                       const gchar *name,
+                                                       const gchar *param,
+                                                       const gchar *value,
+                                                       gsize len,
+                                                       gboolean folding)
+{
+       gchar *enc = NULL;
+
+       if (name == NULL)
+               return;
+
+       g_string_append(string, name);
+
+       __bluetooth_pb_vcard_append_param_v21(string, param);
+       __bluetooth_pb_vcard_append_param_v21(string, "ENCODING=BASE64");
+
+       g_string_append(string, ":");
+
+       if (value  == NULL)
+               return;
+
+       enc = g_base64_encode((const guchar *)value, len);
+
+
+       if (folding == FALSE) {
+               g_string_append(string, enc);
+       } else {
+               gint enc_len = strlen(enc);
+               gint i = 0;
+
+               /* count ' ' size for folding */
+               gint fline_len = LINEBREAK_LEN -1;
+
+               for (i = 0; (i * fline_len) < enc_len; i++) {
+                       g_string_append(string, "\r\n ");
+                       if ((i * fline_len) + fline_len >  enc_len)
+                               g_string_append(string, enc + (i * fline_len));
+                       else
+                               g_string_append_len(string, enc + (i * fline_len), fline_len);
+               }
+
+               /* some application requires more \r\n */
+               g_string_append(string, "\r\n");
+       }
+       g_string_append(string, "\r\n");
+
+       g_free(enc);
+}
+
+static void __bluetooth_pb_vcard_append_n_v21(GString *string,
+                                       CTSstruct *contact)
+{
+       gchar *str;
+
+       str = __bluetooth_pb_name_from_contact(contact);
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "N", NULL, str);
+
+       g_free(str);
+}
+
+static void __bluetooth_pb_vcard_append_tel_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       GSList *list = NULL;
+       GSList *pos = NULL;
+
+       contacts_svc_struct_get_list(contact, CTS_CF_NUMBER_LIST, &list);
+
+       for (pos = list; pos != NULL; pos = pos->next) {
+               CTSvalue *value = (CTSvalue *)(pos->data);
+
+               gchar **paramv = NULL;
+               gchar *param = NULL;
+
+               const gchar *tel = NULL;
+               gchar *escaped = NULL;
+
+               tel  = contacts_svc_value_get_str(value, CTS_NUM_VAL_NUMBER_STR);
+               escaped = __bluetooth_pb_vcard_escape(tel);
+
+               paramv = __bluetooth_pb_contact_tel_param(value);
+               param = __bluetooth_pb_vcard_strv_concat(paramv, ";");
+
+               g_strfreev(paramv);
+
+               __bluetooth_pb_vcard_append_qp_encode_v21(string, "TEL", param, escaped);
+
+               g_free(escaped);
+               g_free(param);
+       }
+}
+
+static void __bluetooth_pb_vcard_append_fn_v21(GString *string,
+                                       CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       gchar *fn = NULL;
+       gchar *tmp = NULL;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_NAME_VALUE, &value);
+
+       tmp = __bluetooth_pb_fn_from_contact(contact);
+       fn = __bluetooth_pb_vcard_escape(tmp);
+
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "FN", NULL, fn);
+
+       g_free(tmp);
+       g_free(fn);
+}
+
+static void __bluetooth_pb_vcard_append_photo_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       const gchar *filename = NULL;
+
+       gchar *type = NULL;
+       gchar *param = NULL;
+       gchar *contents = NULL;
+
+       gsize len = 0;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_BASE_INFO_VALUE, &value);
+       filename = contacts_svc_value_get_str(value, CTS_BASE_VAL_IMG_PATH_STR);
+
+       if (filename == NULL) {
+               return;
+       }
+
+       type = __bluetooth_pb_contact_photo_type(filename);
+
+       if (type) {
+               param = g_strdup_printf("TYPE=%s", type);
+               g_free(type);
+       }
+
+       if (g_file_get_contents(filename, &contents, &len, NULL) == FALSE) {
+               ERR("can not read file contents:%s\n", filename);
+               return;
+       }
+
+       __bluetooth_pb_vcard_append_base64_encode_v21(string,
+                       "PHOTO", param, contents, len, TRUE);
+
+       g_free(param);
+       g_free(contents);
+}
+
+static void __bluetooth_pb_vcard_append_bday_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       GSList *list = NULL;
+       GSList *pos = NULL;
+
+       contacts_svc_struct_get_list(contact, CTS_CF_EVENT_LIST, &list);
+
+       for (pos = list; pos != NULL; pos = pos->next) {
+               enum EVENTTYPE  event_type;
+               gint date;
+               CTSvalue *value = (CTSvalue *) (pos->data);
+
+               event_type = contacts_svc_value_get_int(value, CTS_EVENT_VAL_TYPE_INT);
+               if (event_type != CTS_EVENT_TYPE_BIRTH)
+                       continue;
+
+               date = contacts_svc_value_get_int(value, CTS_EVENT_VAL_DATE_INT);
+               if (date > 0) {
+                       gchar *bday = NULL;
+
+                       bday = g_strdup_printf("%04d-%02d-%02d",
+                                       (date/10000), (date/100)%100, date%100);
+                       __bluetooth_pb_vcard_append_qp_encode_v21(string, "BDAY",
+                                       NULL, bday);
+                       g_free(bday);
+               }
+       }
+}
+
+static void __bluetooth_pb_vcard_append_adr_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       GSList *list = NULL;
+       GSList *pos = NULL;
+
+       contacts_svc_struct_get_list(contact, CTS_CF_POSTAL_ADDR_LIST, &list);
+
+       for (pos = list; pos != NULL; pos = pos->next) {
+               CTSvalue *value = (CTSvalue *) (pos->data);
+
+               gchar **addrv;
+               gchar **paramv;
+
+               gchar *addr;
+               gchar *param;
+
+               if (value == NULL)
+                       continue;
+
+               addrv = __bluetooth_pb_contact_addr(value);
+
+               if (addrv == NULL)
+                       continue;
+
+               addr = __bluetooth_pb_vcard_strv_concat(addrv, ";");
+               g_strfreev(addrv);
+
+               paramv = __bluetooth_pb_contact_addr_param(value);
+               param = __bluetooth_pb_vcard_strv_concat(paramv, ";");
+               g_strfreev(paramv);
+
+               __bluetooth_pb_vcard_append_qp_encode_v21(string, "ADR",
+                               param, addr);
+
+               g_free(param);
+               g_free(addr);
+       }
+}
+
+static void __bluetooth_pb_vcard_append_email_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       GSList *list = NULL;
+       GSList *pos = NULL;
+
+       contacts_svc_struct_get_list(contact, CTS_CF_EMAIL_LIST, &list);
+
+       for (pos = list; pos != NULL; pos = pos->next) {
+               CTSvalue *value = (CTSvalue *)(pos->data);
+
+               const gchar *email;
+               gchar *escaped;
+
+               if (value == NULL)
+                       continue;
+
+               email = contacts_svc_value_get_str(value, CTS_EMAIL_VAL_ADDR_STR);
+               if (email == NULL)
+                       continue;
+
+               escaped = __bluetooth_pb_vcard_escape(email);
+               __bluetooth_pb_vcard_append_qp_encode_v21(string, "EMAIL", NULL, escaped);
+
+               g_free(escaped);
+       }
+
+}
+
+static void __bluetooth_pb_vcard_append_title_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       const gchar *title;
+       gchar *escaped;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_COMPANY_VALUE, &value);
+
+       if (value == NULL)
+               return;
+
+       title = contacts_svc_value_get_str(value, CTS_COMPANY_VAL_JOB_TITLE_STR);
+
+       if (title == NULL)
+               return;
+
+       escaped = __bluetooth_pb_vcard_escape(title);
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "TITLE", NULL, escaped);
+
+       g_free(escaped);
+}
+
+static void __bluetooth_pb_vcard_append_role_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+       const gchar *role;
+       gchar *escaped;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_COMPANY_VALUE, &value);
+
+       if (value == NULL)
+               return;
+
+       role = contacts_svc_value_get_str(value, CTS_COMPANY_VAL_ROLE_STR);
+
+       if (role == NULL)
+               return;
+
+       escaped = __bluetooth_pb_vcard_escape(role);
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "ROLE", NULL, escaped);
+
+       g_free(escaped);
+}
+
+static void __bluetooth_pb_vcard_append_org_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       GString *org = NULL;
+
+       const gchar *name;
+       const gchar *department;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_COMPANY_VALUE, &value);
+
+       name = contacts_svc_value_get_str(value, CTS_COMPANY_VAL_NAME_STR);
+       department = contacts_svc_value_get_str(value, CTS_COMPANY_VAL_DEPARTMENT_STR);
+
+       if (name == NULL && department == NULL)
+               return;
+
+       org = g_string_new(NULL);
+
+       if (name) {
+               gchar *escaped;
+
+               escaped = __bluetooth_pb_vcard_escape(name);
+               g_string_append(org, escaped);
+               g_free(escaped);
+       }
+
+       g_string_append(org, ";");
+
+       if (department) {
+               gchar *escaped;
+
+               escaped = __bluetooth_pb_vcard_escape(department);
+               g_string_append(org, escaped);
+               g_free(escaped);
+       }
+
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "ORG", NULL, org->str);
+
+       g_string_free(org, TRUE);
+}
+
+static void __bluetooth_pb_vcard_append_note_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       const gchar *note;
+       gchar *escaped;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_BASE_INFO_VALUE, &value);
+
+       if (value == NULL)
+               return;
+
+       note = contacts_svc_value_get_str(value, CTS_BASE_VAL_NOTE_STR);
+
+       if (note == NULL)
+               return;
+
+       escaped = __bluetooth_pb_vcard_escape(note);
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "NOTE", NULL, escaped);
+
+       g_free(escaped);
+}
+
+static void __bluetooth_pb_vcard_append_rev_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       gint time;
+       gchar *rev;
+
+       struct tm result;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_BASE_INFO_VALUE, &value);
+
+       if (value == NULL)
+               return;
+
+       time = contacts_svc_value_get_int(value, CTS_BASE_VAL_CHANGED_TIME_INT);
+
+       if (time <= 0)
+               return;
+
+       gmtime_r((const time_t*)(&time), &result);
+
+       rev = g_strdup_printf("%04d-%02d-%02dT%02d:%02d:%02dZ",
+                       (1900 + result.tm_year), (1 + result.tm_mon), result.tm_mday,
+                       result.tm_hour, result.tm_min, result.tm_sec);
+
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "REV", NULL, rev);
+
+       g_free(rev);
+}
+
+static void __bluetooth_pb_vcard_append_url_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       GSList *list = NULL;
+       GSList *pos = NULL;
+
+       contacts_svc_struct_get_list(contact, CTS_CF_WEB_ADDR_LIST, &list);
+
+       for (pos = list; pos != NULL; pos = pos->next) {
+               CTSvalue *value = (CTSvalue *)(pos->data);
+
+               const gchar *url;
+               gchar *escaped;
+
+               if (value == NULL)
+                       continue;
+
+               url = contacts_svc_value_get_str(value, CTS_WEB_VAL_ADDR_STR);
+
+               if (url == NULL)
+                       continue;
+
+               escaped = __bluetooth_pb_vcard_escape(url);
+               __bluetooth_pb_vcard_append_qp_encode_v21(string, "URL", NULL, escaped);
+
+               g_free(escaped);
+       }
+}
+
+static void __bluetooth_pb_vcard_append_uid_v21(GString *string,
+                                               CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       const gchar *uid;
+       gchar *escaped;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_BASE_INFO_VALUE, &value);
+
+       if (value == NULL)
+               return;
+
+       uid = contacts_svc_value_get_str(value, CTS_BASE_VAL_UID_STR);
+
+       if (uid == NULL)
+               return;
+
+       escaped = __bluetooth_pb_vcard_escape(uid);
+       __bluetooth_pb_vcard_append_qp_encode_v21(string, "UID", NULL, escaped);
+
+       g_free(escaped);
+}
+
+static void __bluetooth_pb_vcard_append_v30(GString *string,
+                                       const gchar *name,
+                                       const gchar *param,
+                                       const gchar *value)
+{
+       if (string == NULL)
+               return;
+       if (name == NULL)
+               return;
+
+       g_string_append(string, name);
+
+       if (param)
+               g_string_append_printf(string, ";%s", param);
+
+       g_string_append(string, ":");
+
+       if (value)
+               g_string_append(string, value);
+
+       g_string_append(string, "\r\n");
+}
+
+static void __bluetooth_pb_vcard_remove_v30(GString *string,
+                                       const gchar *property_name)
+{
+       gchar *pos = NULL;
+       gchar *st_pos = NULL;
+
+       gboolean matched = FALSE;
+
+       if(string == NULL || property_name == NULL)
+               return;
+
+       pos = string->str;
+
+       while(*pos != '\0') {
+               if (matched == FALSE) {
+                       if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
+                               gint attrlen = 0;
+
+                               st_pos = pos;
+                               pos += 2;
+
+                               attrlen = strlen(property_name);
+                               if (g_ascii_strncasecmp(pos, property_name, attrlen) == 0) {
+                                       pos += attrlen;
+
+                                       if (*pos == ':' || *pos == ';') {
+                                               matched = TRUE;
+                                               pos++;
+                                       }
+                               }
+                               continue;
+                       }
+               }
+               else {
+                       if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
+                               pos += 2;
+
+                               if (*pos != ' ' && *pos != '\t') {
+                                       /* +2 means move over \r\n */
+                                       g_string_erase(string, (st_pos+2)-(string->str), pos-(st_pos +2));
+                                       pos = st_pos;
+                                       matched = FALSE;
+                               }
+                               continue;
+                       }
+               }
+
+               pos++;
+       }
+}
+
+static gchar *__bluetooth_pb_vcard_filter_v30(const gchar *vcard,
+                                       guint64 filter)
+{
+       GString *string = NULL;
+
+       if (vcard == NULL)
+               return NULL;
+
+       string = g_string_new(vcard);
+
+       if ((filter & VCARD_PHOTO) == 0)
+               __bluetooth_pb_vcard_remove_v30(string, "PHOTO");
+
+       if ((filter & VCARD_BDAY) == 0)
+               __bluetooth_pb_vcard_remove_v30(string, "BDAY");
+
+       if ((filter & VCARD_ADR) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "ADR");
+
+       if ((filter & VCARD_EMAIL) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "EMAIL");
+
+       if ((filter & VCARD_TITLE) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "TITLE");
+
+       if ((filter & VCARD_ROLE) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "ROLE");
+
+       if ((filter & VCARD_ORG) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "ORG");
+
+       if ((filter & VCARD_NOTE) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "NOTE");
+
+       if ((filter & VCARD_REV) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "REV");
+
+       if ((filter & VCARD_URL) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "URL");
+
+       if ((filter & VCARD_UID) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "UID");
+
+       if ((filter & VCARD_NICKNAME) == 0 )
+               __bluetooth_pb_vcard_remove_v30(string, "NICKNAME");
+
+       return g_string_free(string, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v21(gint contact_id,
+                                                       gint phonelog_id,
+                                                       guint64 filter,
+                                                       const gchar *first_name,
+                                                       va_list args)
+{
+       CTSstruct *contact = NULL;
+       gint ret = 0;
+       guint64 f = filter;
+
+       const gchar *name = first_name;
+
+       GString *str = NULL;
+
+       ret = contacts_svc_get_person(contact_id, &contact);
+       if (ret < 0)
+               return NULL;
+
+       if (f == 0)
+               f = ~f;
+
+       str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
+
+       /* N, TEL is default */
+       __bluetooth_pb_vcard_append_n_v21(str, contact);
+
+       if (phonelog_id > 0) {
+               gchar *number;
+
+               number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+               __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0", number);
+               g_free(number);
+
+
+       } else {
+               __bluetooth_pb_vcard_append_tel_v21(str, contact);
+       }
+
+       if (f & VCARD_FN)
+               __bluetooth_pb_vcard_append_fn_v21(str, contact);
+       if (f & VCARD_PHOTO)
+               __bluetooth_pb_vcard_append_photo_v21(str, contact);
+       if (f & VCARD_BDAY)
+               __bluetooth_pb_vcard_append_bday_v21(str, contact);
+       if (f & VCARD_ADR)
+               __bluetooth_pb_vcard_append_adr_v21(str, contact);
+       if (f & VCARD_EMAIL)
+               __bluetooth_pb_vcard_append_email_v21(str, contact);
+       if (f & VCARD_TITLE)
+               __bluetooth_pb_vcard_append_title_v21(str, contact);
+       if (f & VCARD_ROLE)
+               __bluetooth_pb_vcard_append_role_v21(str, contact);
+       if (f & VCARD_ORG)
+               __bluetooth_pb_vcard_append_org_v21(str, contact);
+       if (f & VCARD_NOTE)
+               __bluetooth_pb_vcard_append_note_v21(str, contact);
+       if (f & VCARD_REV)
+               __bluetooth_pb_vcard_append_rev_v21(str, contact);
+       if (f & VCARD_URL)
+               __bluetooth_pb_vcard_append_url_v21(str, contact);
+       if (f & VCARD_UID)
+               __bluetooth_pb_vcard_append_uid_v21(str, contact);
+
+       while (name) {
+               const gchar *param = va_arg(args, const gchar *);
+               const gchar *value = va_arg(args, const gchar *);
+
+               if (value) {
+                       gchar *escaped = NULL;
+
+                       escaped = __bluetooth_pb_vcard_escape(value);
+                       __bluetooth_pb_vcard_append_qp_encode_v21(str, name, param, escaped);
+
+                       g_free(escaped);
+               }
+
+               name = va_arg(args, const gchar *);
+       }
+
+       g_string_append(str, "END:VCARD\r\n");
+
+       return g_string_free(str, FALSE);
+}
+
+
+static gchar *__bluetooth_pb_vcard_real_contact_valist_v30(gint contact_id,
+                                                       gint phonelog_id,
+                                                       guint64 filter,
+                                                       const gchar *first_name,
+                                                       va_list args)
+{
+       CTSstruct *contact = NULL;
+
+       gint ret = 0;
+
+       const gchar *name = first_name;
+       gchar *vcard = NULL;
+
+       ret = contacts_svc_get_person(contact_id, &contact);
+       if (ret < 0)
+               return NULL;
+
+       ret = contacts_svc_get_vcard_from_contact(contact, &vcard);
+
+       if(vcard == NULL)
+               return NULL;
+
+       /* append contents on vcard */
+       while (name) {
+               const gchar *param = va_arg(args, const gchar *);
+               const gchar *value = va_arg(args, const gchar *);
+               const gchar *local_value = NULL;
+
+               gchar *new_vcard = NULL;
+
+               GString *content = g_string_new(name);
+
+               if (param)
+                       g_string_append_printf(content, ";%s", param);
+
+               if (value)
+                       local_value = value;
+               else
+                       local_value = "";
+
+               new_vcard = contacts_svc_vcard_put_content(vcard, content->str, local_value);
+
+               if(new_vcard) {
+                       g_free(vcard);
+                       vcard = new_vcard;
+               }
+
+               g_string_free(content, TRUE);
+
+               name = va_arg(args, const gchar *);
+       }
+
+       /* temporary fixed for some application crash */
+       if (filter == 0)
+               filter = ~VCARD_NOTE;
+
+       if (filter) {
+               gchar *new_vcard = NULL;
+
+               new_vcard = __bluetooth_pb_vcard_filter_v30(vcard, filter);
+
+               if (new_vcard) {
+                       g_free(vcard);
+                       vcard = new_vcard;
+               }
+       }
+
+       /* if phonelog_id exist, we shall show only the phone number that was used for that call */
+       if (phonelog_id > 0) {
+               GString *string = g_string_new(vcard);
+
+               gchar *new_vcard ;
+               gchar *number;
+
+               __bluetooth_pb_vcard_remove_v30(string , "TEL");
+
+               number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+               new_vcard = contacts_svc_vcard_put_content(string->str, "TEL", number);
+               g_free(number);
+
+               if (new_vcard) {
+                       g_free(vcard);
+                       vcard = new_vcard;
+               }
+
+               g_string_free(string, TRUE);
+       }
+
+       return vcard;
+}
+
+
+static gchar *__bluetooth_pb_vcard_real_contact_with_properties(gint contact_id,
+                                                               gint phonelog_id,
+                                                               guint64 filter,
+                                                               guint8 format,
+                                                               const gchar *first_name,
+                                                               ...)
+{
+       DBG("\n");
+       gchar *vcard = NULL;
+       va_list args;
+
+       va_start(args, first_name);
+
+       switch(format) {
+       case VCARD_FORMAT_3_0:
+               vcard = __bluetooth_pb_vcard_real_contact_valist_v30(contact_id,
+                               phonelog_id, filter,
+                               first_name, args);
+               break;
+       case VCARD_FORMAT_2_1:
+       default:
+               vcard = __bluetooth_pb_vcard_real_contact_valist_v21(contact_id,
+                               phonelog_id, filter,
+                               first_name, args);
+               break;
+       }
+
+       va_end(args);
+
+       return vcard;
+}
+
+static gchar *__bluetooth_pb_vcard_real_call_v21(gint phonelog_id,
+                                               guint filter,
+                                               const char *attr)
+{
+       GString *str;
+       gchar *number;
+
+       str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
+
+       __bluetooth_pb_vcard_append_qp_encode_v21(str, "N", NULL, NULL);
+
+       number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+       __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0", number);
+       g_free(number);
+
+       if (((filter == 0) || (filter | VCARD_X_IRMC_CALL_DATETIME))
+                       && attr) {
+               gchar *datetime = NULL;
+
+               datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
+               __bluetooth_pb_vcard_append_qp_encode_v21(str, "X-IRMC-CALL-DATETIME",
+                               attr, datetime);
+               g_free(datetime);
+       }
+
+       g_string_append(str, "END:VCARD\r\n");
+
+       return g_string_free(str, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_real_call_v30(gint phonelog_id,
+                                               guint filter,
+                                               const gchar *attr)
+{
+       GString *str;
+       gchar *number;
+
+       str = g_string_new("BEGIN:VCARD\r\nVERSION:3.0\r\n");
+
+       __bluetooth_pb_vcard_append_v30(str, "N", NULL, NULL);
+       __bluetooth_pb_vcard_append_v30(str, "FN", NULL, NULL);
+
+       number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+       __bluetooth_pb_vcard_append_v30(str, "TEL", NULL, number);
+       g_free(number);
+
+       if (((filter == 0) || (filter | VCARD_X_IRMC_CALL_DATETIME))
+                       && attr) {
+               gchar *datetime = NULL;
+
+               datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
+               __bluetooth_pb_vcard_append_v30(str,
+                               "X-IRMC-CALL-DATETIME", attr, datetime);
+               g_free(datetime);
+       }
+
+       g_string_append(str, "END:VCARD\r\n");
+
+       return g_string_free(str, FALSE);
+}
+
+static gchar *__bluetooth_pb_vcard_real_call(gint phonelog_id,
+                                       guint filter,
+                                       guint8 format,
+                                       const gchar *attr)
+{
+       DBG("\n");
+       gchar *vcard = NULL;
+
+       switch(format) {
+       case VCARD_FORMAT_3_0:
+               vcard = __bluetooth_pb_vcard_real_call_v30(phonelog_id,
+                               filter, attr);
+               break;
+       case VCARD_FORMAT_2_1:
+       default:
+               vcard = __bluetooth_pb_vcard_real_call_v21(phonelog_id,
+                               filter, attr);
+               break;
+       }
+
+       return vcard;
+}
+
+static gchar **__bluetooth_pb_contact_add_field_str(CTSvalue *value,
+                                               int *field,
+                                               gint field_size)
+{
+       gchar **strv;
+       gint i;
+
+       gboolean valid = FALSE;
+
+       /* check empty field */
+       for (i = 0; i < field_size; i++) {
+               const gchar *tmp;
+               tmp = contacts_svc_value_get_str(value, field[i]);
+               if (tmp) {
+                       valid = TRUE;
+                       break;
+               }
+
+       }
+
+       if (valid == FALSE)
+               return NULL;
+
+       strv = g_new0(gchar *, field_size + 1);
+
+       for (i = 0; i < field_size; i++) {
+               const gchar *tmp;
+
+               tmp = contacts_svc_value_get_str(value, field[i]);
+               if (tmp == NULL)
+                       strv[i] = g_strdup("");
+               else
+                       strv[i] = __bluetooth_pb_vcard_escape(tmp);
+       }
+
+       return strv;
+}
+
+static gchar **__bluetooth_pb_contact_tel_param(CTSvalue *value)
+{
+       const gint TEL_PARAM_LEN = 13;
+       gchar **strv = NULL;
+       enum NUMBERTYPE type;
+
+       gint i = 0;
+
+       strv = g_new0(char *, TEL_PARAM_LEN + 1);       /* tel param max size is 13 */
+
+       if (contacts_svc_value_get_bool(value, CTS_NUM_VAL_DEFAULT_BOOL)) {
+               strv[i] = g_strdup("PREF");
+               i++;
+       }
+
+       type = contacts_svc_value_get_int(value, CTS_NUM_VAL_TYPE_INT);
+
+       if (type & CTS_NUM_TYPE_HOME) {
+               strv[i] = g_strdup("HOME");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_WORK) {
+               strv[i] = g_strdup("WORK");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_VOICE) {
+               strv[i] = g_strdup("VOICE");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_FAX) {
+               strv[i] = g_strdup("FAX");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_MSG) {
+               strv[i] = g_strdup("MSG");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_CELL) {
+               strv[i] = g_strdup("CELL");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_PAGER) {
+               strv[i] = g_strdup("PAGER");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_BBS) {
+               strv[i] = g_strdup("BBS");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_MODEM) {
+               strv[i] = g_strdup("MODEM");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_CAR) {
+               strv[i] = g_strdup("CAR");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_ISDN) {
+               strv[i] = g_strdup("ISDN");
+               i++;
+       }
+
+       if (type & CTS_NUM_TYPE_VIDEO) {
+               strv[i] = g_strdup("VIDEO");
+               i++;
+       }
+
+       /* CTS_NUM_TYPE_PCS is not part of vcard2.1 */
+
+       return strv;
+}
+
+
+static gchar *__bluetooth_pb_contact_photo_type(const gchar *filename)
+{
+       gchar *filetype = NULL;
+       gchar *ext = NULL;
+
+       if (g_file_test(filename, G_FILE_TEST_IS_REGULAR) == FALSE) {
+               ERR("file does not regular:%s\n", filename);
+               return NULL;
+       }
+
+       ext = strrchr(filename, '.');
+       if (ext == NULL) {
+               ERR("file doesn't have extension\n");
+               return NULL;
+       }
+
+       ext++;
+
+       if (g_ascii_strcasecmp(ext, "gif") == 0)
+               filetype = "GIF";
+       else if (g_ascii_strcasecmp(ext, "cgm") == 0)
+               filetype = "CGM";
+       else if (g_ascii_strcasecmp(ext, "wmf") == 0)
+               filetype = "WMF";
+       else if (g_ascii_strcasecmp(ext, "bmp") == 0)
+               filetype = "BMP";
+       else if (g_ascii_strcasecmp(ext, "met") == 0)
+               filetype = "MET";
+       else if (g_ascii_strcasecmp(ext, "dib") == 0)
+               filetype = "DIB";
+       else if (g_ascii_strcasecmp(ext, "pict") == 0 || g_ascii_strcasecmp(ext, "pct") == 0 ||
+                       g_ascii_strcasecmp(ext, "pic") == 0)
+               filetype = "PICT";
+       else if (g_ascii_strcasecmp(ext, "tiff") == 0 || g_ascii_strcasecmp(ext, "tif") == 0)
+               filetype = "TIFF";
+       else if (g_ascii_strcasecmp(ext, "ps") == 0)
+               filetype = "PS";
+       else if (g_ascii_strcasecmp(ext, "pdf") == 0)
+               filetype = "PDF";
+       else if (g_ascii_strcasecmp(ext, "jpeg") == 0 || g_ascii_strcasecmp(ext, "jpg") == 0 ||
+                       g_ascii_strcasecmp(ext, "jpe") == 0)
+               filetype = "JPEG";
+       else if (g_ascii_strcasecmp(ext, "mpeg") == 0 || g_ascii_strcasecmp(ext, "mpg") == 0)
+               filetype = "MPEG";
+       else if (g_ascii_strcasecmp(ext, "m2v") == 0)
+               filetype = "MPEG2";
+       else if (g_ascii_strcasecmp(ext, "avi") == 0)
+               filetype = "AVI";
+       else if (g_ascii_strcasecmp(ext, "mov") == 0)
+               filetype = "QTIME";
+       else if (g_ascii_strcasecmp(ext, "png") == 0)
+               filetype = "PNG";
+
+       return g_strdup(filetype);
+}
+
+static gchar **__bluetooth_pb_contact_addr(CTSvalue *value)
+{
+       const gint ADDR_LEN = 7;
+
+       gchar **strv = NULL;
+
+       gint addr[] = { CTS_POSTAL_VAL_POBOX_STR,
+                       CTS_POSTAL_VAL_EXTENDED_STR,
+                       CTS_POSTAL_VAL_STREET_STR,
+                       CTS_POSTAL_VAL_LOCALITY_STR,
+                       CTS_POSTAL_VAL_REGION_STR,
+                       CTS_POSTAL_VAL_POSTALCODE_STR,
+                       CTS_POSTAL_VAL_COUNTRY_STR };
+
+       strv = __bluetooth_pb_contact_add_field_str(value, addr, ADDR_LEN);
+       return strv;
+}
+
+static gchar **__bluetooth_pb_contact_addr_param(CTSvalue *value)
+{
+       gchar **strv = NULL;
+       enum ADDRESSTYPE type;
+
+       gint i = 0;
+
+       strv = g_new0(gchar *, 7);      /* ADDR param max size is 6 */
+
+       type = contacts_svc_value_get_int(value, CTS_POSTAL_VAL_TYPE_INT);
+
+       if (type & CTS_ADDR_TYPE_HOME) {
+               strv[i] = g_strdup("HOME");
+               i++;
+       }
+       if (type & CTS_ADDR_TYPE_WORK) {
+               strv[i] = g_strdup("WORK");
+               i++;
+       }
+       if (type & CTS_ADDR_TYPE_DOM) {
+               strv[i] = g_strdup("DOM");
+               i++;
+       }
+       if (type & CTS_ADDR_TYPE_INTL) {
+               strv[i] = g_strdup("INTL");
+               i++;
+       }
+       if (type & CTS_ADDR_TYPE_POSTAL) {
+               strv[i] = g_strdup("POSTAL");
+               i++;
+       }
+       if (type & CTS_ADDR_TYPE_PARCEL) {
+               strv[i] = g_strdup("PARCEL");
+               i++;
+       }
+       return strv;
+}
+
+static gchar *__bluetooth_pb_phonelog_datetime(gint phonelog_id)
+{
+       CTSvalue *value = NULL;
+       char time_str[32] = {0,};
+
+       time_t log_time;
+       struct tm time_info;
+
+       gint status = 0;
+
+       status = contacts_svc_get_phonelog(phonelog_id, &value);
+       if (status != CTS_SUCCESS) {
+               DBG("can not get phonelog from id\n");
+               return NULL;
+       }
+
+       log_time = contacts_svc_value_get_int(value, CTS_PLOG_VAL_LOG_TIME_INT);
+       localtime_r(&log_time, &time_info);
+
+       strftime(time_str, sizeof(time_str),
+                       "%Y%m%dT%H%M%S", &time_info);
+
+       contacts_svc_value_free(value);
+
+       return g_strdup(time_str);
+}
+
+static gchar *__bluetooth_pb_fn_from_contact(CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+
+       GString *string = NULL;
+       const gchar *str = NULL;
+
+       gint name_size = 5;
+       gint name[] = { CTS_NAME_VAL_PREFIX_STR,
+               CTS_NAME_VAL_FIRST_STR,
+               CTS_NAME_VAL_ADDITION_STR,
+               CTS_NAME_VAL_LAST_STR,
+               CTS_NAME_VAL_SUFFIX_STR };
+
+       gint i = 0;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_NAME_VALUE, &value);
+
+       str = contacts_svc_value_get_str(value, CTS_NAME_VAL_DISPLAY_STR);
+       if (str)
+               return g_strdup(str);
+
+       string = g_string_new(NULL);
+
+       for (i = 0; i < name_size; i++) {
+               const gchar *tmp = NULL;
+
+               tmp = contacts_svc_value_get_str(value, name[i]);
+               if (tmp) {
+                       if (string->len > 0) {
+                               if (name[i] == CTS_NAME_VAL_SUFFIX_STR)
+                                       g_string_append_c(string, ',');
+
+                               g_string_append_c(string, ' ');
+                       }
+                       g_string_append(string, tmp);
+               }
+       }
+
+       return g_string_free(string, FALSE);
+}
+
+static gchar *__bluetooth_pb_name_from_contact(CTSstruct *contact)
+{
+       CTSvalue *value = NULL;
+       GString *string = g_string_new(NULL);
+
+       gint name_size = 5;
+       gint name[] = { CTS_NAME_VAL_LAST_STR,
+               CTS_NAME_VAL_FIRST_STR,
+               CTS_NAME_VAL_ADDITION_STR,
+               CTS_NAME_VAL_PREFIX_STR,
+               CTS_NAME_VAL_SUFFIX_STR };
+
+       gint i = 0;
+
+       contacts_svc_struct_get_value(contact, CTS_CF_NAME_VALUE, &value);
+
+       for (i = 0; i < name_size; i++) {
+               const gchar *tmp = NULL;
+
+               if (i > 0)
+                       g_string_append_c(string, ';');
+
+               tmp = contacts_svc_value_get_str(value, name[i]);
+               if (tmp) {
+                       gchar *escape = NULL;
+
+                       escape = __bluetooth_pb_vcard_escape(tmp);
+                       g_string_append(string, escape);
+
+                       g_free(escape);
+               }
+       }
+
+       return g_string_free(string, FALSE);
+}
+
+static gchar *__bluetooth_pb_number_from_contact(CTSstruct *contact)
+{
+       GSList *list = NULL;
+       GSList *pos = NULL;
+
+       gboolean has_default = FALSE;
+
+       contacts_svc_struct_get_list(contact, CTS_CF_NUMBER_LIST, &list);
+
+       for (pos = list;pos != NULL;pos = pos->next) {
+               has_default = contacts_svc_value_get_bool((CTSvalue *)(pos->data),
+                                                       CTS_NUM_VAL_DEFAULT_BOOL);
+
+               if (has_default)
+                       break;
+       }
+
+       if (has_default == FALSE)
+               pos = list;
+
+       return g_strdup(contacts_svc_value_get_str((CTSvalue *)(pos->data),
+                                               CTS_NUM_VAL_NUMBER_STR));
+}
+
+static gint __bluetooth_pb_contact_id_from_phonelog_id(gint phonelog_id)
+{
+       CTSvalue *value = NULL;
+
+       gint contact_id = 0;
+       gint status = 0;
+
+       status = contacts_svc_get_phonelog(phonelog_id, &value);
+       if (status != CTS_SUCCESS) {
+               DBG("can not get phonelog from id\n");
+               return 0;
+       }
+
+       contact_id = contacts_svc_value_get_int(value,
+                       CTS_PLOG_VAL_RELATED_ID_INT);
+
+       if (contact_id == 0) {
+               /* CTS_PLOG_VAL_RELATEED_ID_INT can be 0,
+                  when phonelog is added on existing contacts,
+                  with this case, trying to contact by phone number */
+               const gchar *number = NULL;
+
+               number = contacts_svc_value_get_str(value, CTS_PLOG_VAL_NUMBER_STR);
+               if (number) {
+                       gint ret = 0;
+
+                       ret = contacts_svc_find_contact_by(CTS_FIND_BY_NUMBER,
+                                       number);
+                       if (ret > 0)
+                               contact_id = ret;
+               }
+       }
+
+       return contact_id;
+}
+
+/* API for vcard */
+gboolean _bluetooth_pb_is_incoming_call(gint phonelog_id)
+{
+       CTSvalue *value = NULL;
+
+       gint status;
+       gint type = 0;
+
+       gboolean retval = FALSE;
+
+       status = contacts_svc_get_phonelog(phonelog_id, &value);
+       if (status != CTS_SUCCESS) {
+               DBG("can not get phonelog from id\n");
+               return FALSE;
+       }
+
+       type = contacts_svc_value_get_int(value, CTS_PLOG_VAL_LOG_TYPE_INT);
+       if (CTS_PLOG_TYPE_VOICE_INCOMMING == type ||
+                       CTS_PLOG_TYPE_VIDEO_INCOMMING == type) {
+               retval = TRUE;
+       }
+       contacts_svc_value_free(value);
+
+       return retval;
+}
+
+gboolean _bluetooth_pb_is_outgoing_call(gint phonelog_id)
+{
+       CTSvalue *value = NULL;
+
+       gint status;
+       gint type = 0;
+
+       gboolean retval = FALSE;
+
+       status = contacts_svc_get_phonelog(phonelog_id, &value);
+       if (status != CTS_SUCCESS) {
+               DBG("can not get phonelog from id\n");
+               return FALSE;
+       }
+
+       type = contacts_svc_value_get_int(value, CTS_PLOG_VAL_LOG_TYPE_INT);
+       if (CTS_PLOG_TYPE_VOICE_OUTGOING == type ||
+                       CTS_PLOG_TYPE_VIDEO_OUTGOING == type) {
+               retval = TRUE;
+       }
+       contacts_svc_value_free(value);
+
+       return retval;
+}
+
+gboolean _bluetooth_pb_is_missed_call(gint phonelog_id)
+{
+       CTSvalue *value = NULL;
+
+       gint status;
+       gint type = 0;
+
+       gboolean retval = FALSE;
+
+       status = contacts_svc_get_phonelog(phonelog_id, &value);
+       if (status != CTS_SUCCESS) {
+               DBG("can not get phonelog from id\n");
+               return FALSE;
+       }
+
+       type = contacts_svc_value_get_int(value, CTS_PLOG_VAL_LOG_TYPE_INT);
+       if (CTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN == type ||
+                       CTS_PLOG_TYPE_VOICE_INCOMMING_SEEN == type ||
+                       CTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN == type ||
+                       CTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN == type) {
+               retval = TRUE;
+       }
+       contacts_svc_value_free(value);
+
+       return retval;
+}
+
+gchar *_bluetooth_pb_vcard_contact(gint contact_id,
+                               guint64 filter,
+                               guint8 format)
+{
+       gchar *str = NULL;
+
+       if (contact_id < 0)
+               return NULL;
+
+       /* owner */
+       if (contact_id == 0) {
+               str = __bluetooth_pb_vcard_owner(filter, format);
+               return str;
+       }
+
+       str = __bluetooth_pb_vcard_real_contact_with_properties(contact_id, 0,
+                       filter, format,
+                       NULL);
+       return str;
+}
+
+gchar *_bluetooth_pb_vcard_call(gint phonelog_id,
+                               guint64 filter,
+                               guint8 format,
+                               const gchar *attr)
+{
+       gint contact_id = 0;
+
+       gchar *str = NULL;
+
+       if (attr == NULL) {
+               DBG("Unknown attribute type ignored\n");
+               return NULL;
+       }
+
+       contact_id = __bluetooth_pb_contact_id_from_phonelog_id(phonelog_id);
+
+       if (contact_id) {
+               if (filter == 0 || (filter & VCARD_X_IRMC_CALL_DATETIME)) {
+                       gchar *datetime = NULL;
+
+                       datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
+
+                       str = __bluetooth_pb_vcard_real_contact_with_properties(contact_id,
+                                       phonelog_id,
+                                       filter, format,
+                                       "X-IRMC-CALL-DATETIME", attr, datetime,
+                                       NULL);
+
+                       if(datetime)
+                               g_free(datetime);
+               }
+               else {
+                       str = __bluetooth_pb_vcard_real_contact_with_properties(contact_id,
+                                       phonelog_id,
+                                       filter, format,
+                                       NULL);
+               }
+       }
+       else
+               str = __bluetooth_pb_vcard_real_call(phonelog_id, filter, format, attr);
+
+       return str;
+}
+
+gchar *_bluetooth_pb_fn_from_contact_id(gint contact_id)
+{
+       CTSstruct *contact = NULL;
+       gchar *str = NULL;
+
+       contacts_svc_get_person(contact_id, &contact);
+
+       str = __bluetooth_pb_fn_from_contact(contact);
+
+       contacts_svc_struct_free(contact);
+
+       return str;
+}
+
+gchar *_bluetooth_pb_name_from_contact_id(gint contact_id)
+{
+       CTSstruct *contact = NULL;
+       gchar *str = NULL;
+
+       contacts_svc_get_person(contact_id, &contact);
+
+       str = __bluetooth_pb_name_from_contact(contact);
+
+       contacts_svc_struct_free(contact);
+
+       return str;
+}
+
+gchar *_bluetooth_pb_number_from_contact_id(gint contact_id)
+{
+       CTSstruct *contact = NULL;
+       gchar *str = NULL;
+
+       contacts_svc_get_person(contact_id, &contact);
+
+       str = __bluetooth_pb_number_from_contact(contact);
+
+       contacts_svc_struct_free(contact);
+
+       return str;
+}
+
+gchar *_bluetooth_pb_fn_from_phonelog_id(gint phonelog_id)
+{
+       gint contact_id = 0;
+       gchar *str = NULL;
+
+       contact_id = __bluetooth_pb_contact_id_from_phonelog_id(phonelog_id);
+
+       if (contact_id > 0)
+               str = _bluetooth_pb_fn_from_contact_id(contact_id);
+       else
+               str = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+
+       return str;
+}
+
+gchar *_bluetooth_pb_name_from_phonelog_id(gint phonelog_id)
+{
+       gint contact_id = 0;
+       gchar *str = NULL;
+
+       contact_id = __bluetooth_pb_contact_id_from_phonelog_id(phonelog_id);
+
+       if (contact_id > 0)
+               str = _bluetooth_pb_name_from_contact_id(contact_id);
+       else {
+               gchar *tmp;
+
+               tmp = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
+               str = g_strdup_printf("%s;;;;", tmp);
+
+               g_free(tmp);
+       }
+
+       return str;
+}
+
+gchar *_bluetooth_pb_number_from_phonelog_id(gint phonelog_id)
+{
+       CTSvalue *value = NULL;
+       gint status;
+       gchar *str;
+
+       status = contacts_svc_get_phonelog(phonelog_id, &value);
+       if (status != CTS_SUCCESS) {
+               return NULL;
+       }
+
+       str = g_strdup(contacts_svc_value_get_str(value,
+                               CTS_PLOG_VAL_NUMBER_STR));
+
+       contacts_svc_value_free(value);
+
+       return str;
+}
+
+gchar *_bluetooth_pb_fn_owner(void)
+{
+       return _bluetooth_pb_number_owner();
+}
+
+gchar *_bluetooth_pb_name_owner(void)
+{
+       gchar *name;
+       gchar *number;
+
+       number = _bluetooth_pb_number_owner();
+       name = g_strdup_printf("%s;;;;", number);
+
+       g_free(number);
+
+       return name;
+}
+
+gchar *_bluetooth_pb_number_owner(void)
+{
+       return vconf_get_str(VCONFKEY_TELEPHONY_SUBSCRIBER_NUMBER);
+}
diff --git a/bluetooth-pb-agent/bluetooth_pb_vcard.h b/bluetooth-pb-agent/bluetooth_pb_vcard.h
new file mode 100644 (file)
index 0000000..0ea1605
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
+ *              Girishashok Joshi <girish.joshi@samsung.com>
+ *              Chanyeol Park <chanyeol.park@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 __DEF_BT_PB_VCARD_H_
+#define __DEF_BT_PB_VCARD_H_
+
+#include <glib.h>
+#include <contacts-svc.h>
+
+gboolean _bluetooth_pb_is_incoming_call(gint phonelog_id);
+
+gboolean _bluetooth_pb_is_outgoing_call(gint phonelog_id);
+
+gboolean _bluetooth_pb_is_missed_call(gint phonelog_id);
+
+/* vcard */
+gchar *_bluetooth_pb_vcard_contact(gint contact_id,
+                               guint64 filter,
+                               guint8 format);
+
+gchar *_bluetooth_pb_vcard_call(gint phonelog_id,
+                               guint64 filter,
+                               guint8 format,
+                               const gchar *attr);
+
+/* get list entry*/
+GPtrArray *_bluetooth_pb_list_new(void);
+
+void _bluetooth_pb_list_contact_append(GPtrArray *ptr_array,
+                               gint handle,
+                               gint contact_id);
+
+void _bluetooth_pb_list_call_append(GPtrArray *ptr_array,
+                               gint handle,
+                               gint phonelog_id);
+
+gint _bluetooth_pb_list_get_id(gint handle);
+
+void _bluetooth_pb_list_free(GPtrArray *ptr_array,
+                       gboolean hash_table);
+
+gchar *_bluetooth_pb_fn_from_contact_id(gint contact_id);
+
+gchar *_bluetooth_pb_name_from_contact_id(gint contact_id);
+
+gchar *_bluetooth_pb_number_from_contact_id(gint contact_id);
+
+gchar *_bluetooth_pb_fn_from_phonelog_id(gint phonelog_id);
+
+gchar *_bluetooth_pb_name_from_phonelog_id(gint phonelog_id);
+
+gchar *_bluetooth_pb_number_from_phonelog_id(gint phonelog_id);
+
+gchar *_bluetooth_pb_fn_owner(void);
+
+gchar *_bluetooth_pb_name_owner(void);
+
+gchar *_bluetooth_pb_number_owner(void);
+
+#endif
diff --git a/bluetooth-telephony/CMakeLists.txt b/bluetooth-telephony/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b1cdc49
--- /dev/null
@@ -0,0 +1,54 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bluetooth-telephony C)
+
+SET(SRCS bluetooth-telephony-api.c)
+SET(HEADERS bluetooth-telephony-api.h)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include")
+SET(VERSION_MAJOR 1)
+SET(VERSION ${VERSION_MAJOR}.0.0)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(packages REQUIRED dlog dbus-glib-1 gobject-2.0 gmodule-2.0 vconf)
+
+FOREACH(flag ${packages_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g ")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+IF("${ARCH}" STREQUAL "arm")
+       ADD_DEFINITIONS("-DTARGET")
+       MESSAGE("add -DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+FIND_PROGRAM(MARSHALTOOL NAMES glib-genmarshal)
+EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR}/marshal.list --header > ${CMAKE_CURRENT_SOURCE_DIR}/marshal.h")
+EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR}/marshal.list --body > ${CMAKE_CURRENT_SOURCE_DIR}/marshal.c")
+
+FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool)
+EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bluetooth_telephony_method ${CMAKE_CURRENT_SOURCE_DIR}/bt_telephony_frwk.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-telephony-glue.h")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${packages_LDFLAGS})
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc @ONLY)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig)
+
+FOREACH(hfile ${HEADERS})
+       INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} DESTINATION include/bluetooth-telephony)
+ENDFOREACH(hfile)
diff --git a/bluetooth-telephony/bluetooth-telephony-api.c b/bluetooth-telephony/bluetooth-telephony-api.c
new file mode 100644 (file)
index 0000000..4baca2d
--- /dev/null
@@ -0,0 +1,1604 @@
+/*
+ * Bluetooth-telephony
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             GirishAshok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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 <string.h>
+#include <stdlib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <unistd.h>
+
+#include "vconf.h"
+#include "vconf-keys.h"
+
+#include "bluetooth-telephony-internal.h"
+#include "bluetooth-telephony-glue.h"
+#include "bluetooth-telephony-api.h"
+#include "marshal.h"
+
+typedef struct {
+       DBusGConnection *conn;
+       DBusGProxy *proxy;
+       DBusGProxy *dbus_proxy;
+       DBusGProxy *manager_proxy;
+} telephony_dbus_info_t;
+
+static GObject *object;
+static bt_telephony_info_t telephony_info;
+static telephony_dbus_info_t telephony_dbus_info;
+static gboolean is_active = FALSE;
+
+#define BT_EXPORT_API __attribute__((visibility("default")))
+
+#define BT_TELEPHONY "BT_TELEPHONY"
+#define DBG(fmt, args...) SLOG(LOG_DEBUG, BT_TELEPHONY, \
+                               "%s():%d "fmt, __func__, __LINE__, ##args)
+#define ERR(fmt, args...) SLOG(LOG_ERROR, BT_TELEPHONY, \
+                               "%s():%d "fmt, __func__, __LINE__, ##args)
+
+#define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark())
+
+#define BLUEZ_SERVICE_NAME "org.bluez"
+#define BLUEZ_HEADSET_INTERFACE "org.bluez.Headset"
+#define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager"
+#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter"
+#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device"
+
+#define HFP_AGENT_SERVICE "org.bluez.hfp_agent"
+#define HFP_AGENT_PATH "/org/bluez/hfp_agent"
+#define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
+
+#define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
+
+#define BT_TELEPHONY_CHECK_BT_STATUS() \
+       if (!is_active) { \
+               DBG("Bluetooth is inactive \n"); \
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
+       }
+
+/*Function Declaration*/
+static int __bt_telephony_get_error(const char *error_message);
+static int __bt_telephony_event_cb(int event, int result, void *param_data);
+static GQuark __bluetooth_telephony_error_quark(void);
+static int __bluetooth_telephony_dbus_method_send(const char *path,
+               const char *interface, const char *method, int type, ...);
+static int __bluetooth_telephony_send_call_status(
+                       bt_telephony_call_status_t call_status,
+                       unsigned int call_id);
+static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
+                                       const char *err_msg);
+
+static DBusHandlerResult __bluetooth_telephony_event_filter(
+                                               DBusConnection *conn,
+                                               DBusMessage *msg, void *data);
+
+static void __bluetooth_telephony_name_owner_changed(DBusGProxy *dbus_proxy,
+                                       const char *name, const char *prev,
+                                       const char *new, gpointer user_data);
+static void __bluetooth_telephony_adapter_added_cb(DBusGProxy *manager_proxy,
+                               const char *adapter_path, gpointer user_data);
+static int __bluetooth_telephony_proxy_init(void);
+static void __bluetooth_telephony_proxy_deinit(void);
+static int __bluetooth_telephony_register(bt_telephony_func_ptr cb,
+                                                       void  *user_data);
+static int __bluetooth_telephony_unregister(void);
+static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
+                                                       char *path);
+static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
+static int __bluetooth_telephony_get_connected_device(void);
+static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void);
+
+/*Function Definition*/
+static int __bt_telephony_get_error(const char *error_message)
+{
+       if (error_message == NULL) {
+               DBG("Error message NULL\n");
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       DBG("Error message = %s \n", error_message);
+       if (g_strcmp0(error_message, "NotAvailable") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
+       else if (g_strcmp0(error_message, "NotConnected") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
+       else if (g_strcmp0(error_message, "InProgress") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_BUSY;
+       else if (g_strcmp0(error_message, "InvalidArguments") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
+       else if (g_strcmp0(error_message, "AlreadyExists") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
+       else if (g_strcmp0(error_message, "Already Connected") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
+       else if (g_strcmp0(error_message, "No memory") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
+       else if (g_strcmp0(error_message, "I/O error") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
+       else if (g_strcmp0(error_message, "Operation currently not available") == 0)
+               return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
+       else
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+}
+
+static int __bt_telephony_event_cb(int event, int result, void *param_data)
+{
+       telephony_event_param_t bt_event = { 0, };
+
+       bt_event.event = event;
+       bt_event.result = result;
+       bt_event.param_data = param_data;
+
+       return telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
+}
+
+static GQuark __bluetooth_telephony_error_quark(void)
+{
+       static GQuark quark = 0;
+
+       quark = g_quark_from_static_string("telephony");
+
+       return quark;
+}
+
+static int __bluetooth_telephony_dbus_method_send(const char *path,
+                       const char *interface, const char *method, int type, ...)
+{
+       DBusMessage *msg;
+       DBusMessage *reply;
+       DBusError err;
+       va_list args;
+
+       DBG("__bluetooth_telephony_dbus_method_send +\n");
+
+       msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
+                       path, interface, method);
+       if (!msg) {
+               DBG("Unable to allocate new D-Bus %s message \n", method);
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       va_start(args, type);
+
+       if (!dbus_message_append_args_valist(msg, type, args)) {
+               dbus_message_unref(msg);
+               va_end(args);
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       va_end(args);
+
+       dbus_error_init(&err);
+
+       reply = dbus_connection_send_with_reply_and_block(
+               dbus_g_connection_get_connection(telephony_dbus_info.conn),
+               msg, -1, &err);
+       dbus_message_unref(msg);
+
+       if (!reply) {
+               DBG("Error returned in method call\n");
+               if (dbus_error_is_set(&err)) {
+                       int ret = __bt_telephony_get_error(err.message);
+                       dbus_error_free(&err);
+                       return ret;
+               }
+       }
+
+       dbus_message_unref(reply);
+
+       DBG("__bluetooth_telephony_dbus_method_send -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+static int __bluetooth_telephony_send_call_status(
+                       bt_telephony_call_status_t call_status,
+                       unsigned int call_id)
+{
+       char *path = g_strdup(telephony_info.call_path);
+       int ret;
+
+       DBG("__bluetooth_telephony_send_call_status +\n");
+
+       ret = __bluetooth_telephony_dbus_method_send(
+                       HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
+                       "ChangeCallStatus", DBUS_TYPE_STRING, &path,
+                       DBUS_TYPE_INT32, &call_status,
+                       DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID);
+       g_free(path);
+       return ret;
+}
+
+static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
+                                       const char *err_msg)
+{
+       return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg);
+}
+
+static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object)
+{
+       DBG("bluetooth_telephony_method_init +\n");
+       DBG("agent %p\n", object);
+       DBG("bluetooth_telephony_method_init -\n");
+
+       return;
+}
+
+static void __bluetooth_telephony_method_finalize(
+                                       BluetoothTelephonyMethod *object)
+{
+       DBG("__bluetooth_telephony_method_finalize +\n");
+       G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize((
+                                                       GObject *)object);
+       DBG("__bluetooth_telephony_method_finalize -\n");
+
+       return;
+}
+
+static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void)
+{
+       BluetoothTelephonyMethod *obj;
+
+       DBG("__bluetooth_telephony_method_new +\n");
+       obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL);
+       DBG("__bluetooth_telephony_method_new -\n");
+
+       return obj;
+}
+
+static void bluetooth_telephony_method_class_init(
+                                       BluetoothTelephonyMethodClass *klass)
+{
+       GObjectClass *object_class = NULL;
+       DBG("bluetooth_telephony_method_class_init +\n");
+
+       object_class = G_OBJECT_CLASS(klass);
+       object_class->finalize = (void *)__bluetooth_telephony_method_finalize;
+
+       /*Registration of the Framework methods */
+       dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD,
+                       &dbus_glib_bluetooth_telephony_method_object_info);
+       DBG("bluetooth_telephony_method_class_init -\n");
+       return;
+}
+
+static gboolean bluetooth_telephony_method_answer(
+                               BluetoothTelephonyMethod *object,
+                               guint callid, DBusGMethodInvocation *context)
+{
+       telephony_event_callid_t call_data = { 0, };
+       GError *err;
+       int error;
+
+       DBG("bluetooth_telephony_method_answer +\n");
+       DBG("call_id = [%d]\n", callid);
+
+       call_data.callid = callid;
+
+       error = __bt_telephony_event_cb(BLUETOOTH_EVENT_AG_ANSWER,
+                                       BLUETOOTH_TELEPHONY_ERROR_NONE,
+                                       (void *)&call_data);
+
+       if (error != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               err = __bluetooth_telephony_error(
+                               BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
+                               "Application error");
+               dbus_g_method_return_error(context, err);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       DBG("bluetooth_telephony_method_answer -\n");
+       return TRUE;
+}
+
+static gboolean bluetooth_telephony_method_release(
+                               BluetoothTelephonyMethod *object,
+                               guint callid, DBusGMethodInvocation *context)
+{
+       telephony_event_callid_t call_data = { 0, };
+       GError *err;
+       int error;
+
+       DBG("bluetooth_telephony_method_release +\n");
+       DBG("call_id = [%d]\n", callid);
+
+       call_data.callid = callid;
+
+       error = __bt_telephony_event_cb(BLUETOOTH_EVENT_AG_RELEASE,
+                                       BLUETOOTH_TELEPHONY_ERROR_NONE,
+                                       (void *)&call_data);
+
+       if (error != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               err = __bluetooth_telephony_error(
+                               BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
+                               "Application error");
+               dbus_g_method_return_error(context, err);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       DBG("bluetooth_telephony_method_release-\n");
+       return TRUE;
+
+}
+
+static gboolean bluetooth_telephony_method_reject(
+                               BluetoothTelephonyMethod *object,
+                               guint callid, DBusGMethodInvocation *context)
+{
+       telephony_event_callid_t call_data = { 0, };
+       GError *err;
+       int error;
+
+       DBG("bluetooth_telephony_method_reject +\n");
+       DBG("call_id = [%d]\n", callid);
+
+       call_data.callid = callid;
+
+       error = __bt_telephony_event_cb(BLUETOOTH_EVENT_AG_REJECT,
+                                       BLUETOOTH_TELEPHONY_ERROR_NONE,
+                                       (void  *)&call_data);
+
+       if (error != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               err = __bluetooth_telephony_error(
+                               BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
+                               "Application error");
+               dbus_g_method_return_error(context, err);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       DBG("bluetooth_telephony_method_reject-\n");
+       return TRUE;
+}
+
+static gboolean bluetooth_telephony_method_threeway(
+                               BluetoothTelephonyMethod *object,
+                               guint value, DBusGMethodInvocation *context)
+{
+       int event = 0;
+       GError *err;
+       int error;
+
+       DBG("bluetooth_telephony_method_threeway \n");
+       DBG("chld value  = [%d]\n", value);
+
+       if (value >= 0) {
+               switch (value) {
+               case 0:
+                       event = BLUETOOTH_EVENT_AG_CALL_HOLD_RELEASE_ALL;
+                       break;
+               case 1:
+                       event = BLUETOOTH_EVENT_AG_CALL_HOLD_RELEASE_ACTIVE;
+                       break;
+               case 2:
+                       event = BLUETOOTH_EVENT_AG_CALL_HOLD_HOLD_ACTIVE;
+                       break;
+               case 3:
+                       event = BLUETOOTH_EVENT_AG_CALL_HOLD_ADD_NEW;
+                       break;
+               case 4:
+                       event = BLUETOOTH_EVENT_AG_CALL_HOLD_TRANSFER;
+                       break;
+               default:
+                       DBG("Invalid CHLD command\n");
+                       err = __bluetooth_telephony_error(
+                               BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX,
+                               "Invalid chld command");
+                       dbus_g_method_return_error(context, err);
+                       g_error_free(err);
+                       return FALSE;
+               }
+
+               DBG("event  = [%d]\n", event);
+
+               error = __bt_telephony_event_cb(event,
+                               BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
+
+               if (error != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+                       err = __bluetooth_telephony_error(
+                                       BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
+                                       "Application error");
+                       dbus_g_method_return_error(context, err);
+                       g_error_free(err);
+                       return FALSE;
+               }
+       } else {
+               err = __bluetooth_telephony_error(
+                       BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX,
+                       "Invalid chld command");
+               dbus_g_method_return_error(context, err);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       DBG("bluetooth_telephony_method_threeway -\n");
+       return TRUE;
+}
+
+static gboolean bluetooth_telephony_method_send_dtmf(
+                               BluetoothTelephonyMethod *object,
+                               gchar *dtmf, DBusGMethodInvocation *context)
+{
+       telephony_event_dtmf_t call_data = { 0, };
+       GError *err;
+       int error;
+
+       DBG("bluetooth_ag_method_send_dtmf +\n");
+
+       if (dtmf == NULL) {
+               DBG("Number dial failed\n");
+               err = __bluetooth_telephony_error(
+                               BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
+                               "Invalid dtmf");
+               dbus_g_method_return_error(context, err);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       DBG("Dtmf = %s \n", dtmf);
+
+       call_data.dtmf = g_strdup(dtmf);
+
+       error = __bt_telephony_event_cb(BLUETOOTH_EVENT_AG_DTMF,
+               BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data);
+
+       if (error != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("Number dial failed\n");
+               err = __bluetooth_telephony_error(
+                               BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
+                               "Application error");
+               dbus_g_method_return_error(context, err);
+               g_free(call_data.dtmf);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       dbus_g_method_return(context);
+       g_free(call_data.dtmf);
+       DBG("bluetooth_ag_method_send_dtmf -\n");
+       return TRUE;
+}
+
+static DBusHandlerResult __bluetooth_telephony_event_filter(
+                                               DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       const char *path = dbus_message_get_path(msg);
+       char *dev_addr = NULL;
+       DBusMessageIter item_iter;
+       DBusMessageIter value_iter;
+       const char *property;
+
+       if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       dbus_message_iter_init(msg, &item_iter);
+       if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       dbus_message_iter_get_basic(&item_iter, &property);
+
+       if (property == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       DBG("Property (%s)\n", property);
+
+       if (g_strcmp0(property, "State") == 0) {
+               char *state = NULL;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &state);
+               if (NULL == state) {
+                       DBG("State is null\n");
+                       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+               }
+               DBG("State %s\n", state);
+
+               if (g_strcmp0(state, "connected") == 0)
+                       telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
+               else if (g_strcmp0(state, "playing") == 0)
+                       telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
+               else if (g_strcmp0(state, "disconnected") == 0)
+                       telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+
+       if (g_strcmp0(property, "Connected") == 0) {
+               gboolean connected = FALSE;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &connected);
+               DBG("Connected %d\n", connected);
+
+               if (connected) {
+                       /*Get device address*/
+                       if (path != NULL)
+                               dev_addr = strstr(path, "dev_");
+
+                       if (dev_addr != NULL) {
+                               dev_addr += 4;
+                               g_strlcpy(telephony_info.address,
+                                       dev_addr,
+                                       sizeof(telephony_info.address));
+                               g_strdelimit(telephony_info.address, "_", ':');
+                               DBG("address is %s \n",
+                                       telephony_info.address);
+
+                               telephony_info.headset_state =
+                                               BLUETOOTH_STATE_CONNECTED;
+
+                               if (telephony_dbus_info.proxy == NULL)
+                                       telephony_dbus_info.proxy =
+                                                       __bluetooth_telephony_get_connected_device_proxy();
+
+                               DBG("Headset Connected\n");
+                       }
+               } else { /*Device disconnected*/
+                       memset(telephony_info.address, 0x00,
+                                       sizeof(telephony_info.address));
+                       telephony_info.headset_state =
+                                               BLUETOOTH_STATE_DISCONNETED;
+
+                       if (telephony_dbus_info.proxy != NULL) {
+                               g_object_unref(telephony_dbus_info.proxy);
+                               telephony_dbus_info.proxy = NULL;
+                       }
+                       DBG("Headset Disconnected\n");
+               }
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+
+       if (g_strcmp0(property, "Playing") == 0) {
+               gboolean audio_sink_playing = FALSE;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
+
+               if (audio_sink_playing) {
+                       if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, TRUE)) {
+                               DBG("SVCONFKEY_BT_HEADSET_SCO -"
+                                       "Set to TRUE\n");
+                       } else {
+                               DBG("vconf_set_bool - Failed\n");
+                       }
+                       telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
+                        __bt_telephony_event_cb(
+                               BLUETOOTH_EVENT_AUDIO_CONNECTED,
+                               BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
+               } else {
+                       if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
+                               DBG("SVCONFKEY_BT_HEADSET_SCO -"
+                                               "Set to FALSE\n");
+                       } else {
+                               DBG("vconf_set_bool - Failed\n");
+                       }
+                       telephony_info.headset_state =
+                                               BLUETOOTH_STATE_CONNECTED;
+                       __bt_telephony_event_cb(
+                               BLUETOOTH_EVENT_AUDIO_DISCONNECTED,
+                               BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
+               }
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void __bluetooth_telephony_name_owner_changed(DBusGProxy *dbus_proxy,
+                                       const char *name, const char *prev,
+                                       const char *new, gpointer user_data)
+{
+       DBG("Name str = %s \n", name);
+
+       if (g_strcmp0(name, BLUEZ_SERVICE_NAME) == 0 && *new == '\0') {
+               DBG("BlueZ is terminated and flag need to be reset");
+               is_active = FALSE;
+               DBG("Send disabled to application\n");
+               __bt_telephony_event_cb(BLUETOOTH_EVENT_BT_DISABLED,
+                       BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
+       }
+
+}
+
+static void __bluetooth_telephony_adapter_added_cb(DBusGProxy *manager_proxy,
+                               const char *adapter_path, gpointer user_data)
+{
+       DBG("Adapter added [%s] \n", adapter_path);
+
+       if (strstr(adapter_path, "hci0")) {
+               DBG("BlueZ is Activated and flag need to be reset");
+               is_active = TRUE;
+               DBG("Send enabled to application\n");
+               __bt_telephony_event_cb(BLUETOOTH_EVENT_BT_ENABLED,
+                       BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
+       }
+}
+
+static int __bluetooth_telephony_proxy_init(void)
+{
+       DBG("__bluetooth_audio_proxy_init +\n");
+
+       telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name(
+                       telephony_dbus_info.conn, DBUS_SERVICE_DBUS,
+                       DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+       if (NULL == telephony_dbus_info.dbus_proxy)
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+
+       /*Add Signal callback for BT disabled*/
+       dbus_g_proxy_add_signal(telephony_dbus_info.dbus_proxy,
+                                       "NameOwnerChanged",
+                                       G_TYPE_STRING, G_TYPE_STRING,
+                                       G_TYPE_STRING, G_TYPE_INVALID);
+
+       dbus_g_proxy_connect_signal(telephony_dbus_info.dbus_proxy,
+                                       "NameOwnerChanged",
+                                       G_CALLBACK(__bluetooth_telephony_name_owner_changed),
+                                       NULL, NULL);
+
+       /*Add Signal callback for BT enabled*/
+
+       dbus_g_proxy_add_signal(telephony_dbus_info.manager_proxy,
+                               "AdapterAdded",
+                               DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+       dbus_g_proxy_connect_signal(telephony_dbus_info.manager_proxy,
+                       "AdapterAdded",
+                       G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
+                       NULL, NULL);
+
+       object = (GObject *)__bluetooth_telephony_method_new();
+
+       if (NULL == object) {
+               g_object_unref(telephony_dbus_info.dbus_proxy);
+               telephony_dbus_info.dbus_proxy = NULL;
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       DBG("telephony_object = %d\n", object);
+
+       dbus_g_connection_register_g_object(telephony_dbus_info.conn,
+                       telephony_info.call_path, G_OBJECT(object));
+
+       DBG("__bluetooth_audio_proxy_init -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+static void __bluetooth_telephony_proxy_deinit(void)
+{
+       DBG("__bluetooth_telephony_proxy_deinit +\n");
+
+
+       /*Remove BT disabled signal*/
+       dbus_g_proxy_disconnect_signal(telephony_dbus_info.dbus_proxy ,
+               "NameOwnerChanged",
+               G_CALLBACK(__bluetooth_telephony_name_owner_changed),
+               NULL);
+
+       g_object_unref(telephony_dbus_info.dbus_proxy);
+
+       /*Remove BT enabled signal*/
+       dbus_g_proxy_disconnect_signal(
+               telephony_dbus_info.manager_proxy,
+               "AdapterAdded",
+               G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
+               NULL);
+
+       dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
+                               G_OBJECT(object));
+
+       g_object_unref(object);
+       object = NULL;
+
+       g_object_unref(telephony_dbus_info.proxy);
+       telephony_dbus_info.proxy = NULL;
+
+       DBG("__bluetooth_telephony_proxy_deinit -\n");
+       return;
+}
+
+static int __bluetooth_telephony_register(bt_telephony_func_ptr cb,
+                                                       void  *user_data)
+{
+       char *path = g_strdup(telephony_info.call_path);
+       int ret;
+
+       DBG("bluetooth_telephony_register +\n");
+
+       telephony_info.cb = cb;
+       telephony_info.user_data = user_data;
+
+       ret =  __bluetooth_telephony_dbus_method_send(
+                       HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
+                       "RegisterApplication", DBUS_TYPE_STRING, &path,
+                       DBUS_TYPE_INVALID);
+       g_free(path);
+       DBG("bluetooth_telephony_register -\n");
+       return ret;
+}
+
+static  int __bluetooth_telephony_unregister(void)
+{
+       char *path = g_strdup(telephony_info.call_path);
+       int ret;
+
+       DBG("bluetooth_telephony_unregister +\n");
+
+       telephony_info.cb = NULL;
+       telephony_info.user_data = NULL;
+       telephony_info.call_count = 0;
+
+       ret = __bluetooth_telephony_dbus_method_send(
+                       HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
+                       "UnregisterApplication", DBUS_TYPE_STRING, &path,
+                       DBUS_TYPE_INVALID);
+       g_free(path);
+       DBG("bluetooth_telephony_unregister +\n");
+       return ret;
+}
+
+static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
+                                                       char *path)
+{
+       GError *err = NULL;
+       char *adapter_path = NULL;
+
+       DBG("__bluetooth_get_default_adapter_path + \n");
+
+
+       if (!dbus_g_proxy_call(telephony_dbus_info.manager_proxy,
+                               "DefaultAdapter", &err, G_TYPE_INVALID,
+                               DBUS_TYPE_G_OBJECT_PATH, &adapter_path,
+                               G_TYPE_INVALID)) {
+               if (err != NULL) {
+                       DBG("Getting DefaultAdapter failed: [%s]\n",
+                                                       err->message);
+                       g_error_free(err);
+               }
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       if (adapter_path == NULL) {
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
+               DBG("Path too long.\n");
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       DBG("path = %s\n", adapter_path);
+       g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
+       DBG("__bluetooth_get_default_adapter_path -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
+{
+       gboolean flag = FALSE;
+       DBG("__bluetooth_telephony_is_headset + \n");
+
+       switch ((device_class & 0x1f00) >> 8) {
+       case 0x04:
+               switch ((device_class & 0xfc) >> 2) {
+               case 0x01:
+               case 0x02:
+                       flag = TRUE;
+                       break;
+               case 0x06:
+                       flag = TRUE;
+                       break;
+               case 0x0b:
+               case 0x0c:
+               case 0x0d:
+                       break;
+               default:
+                       flag = TRUE;
+                       break;
+               }
+               break;
+       }
+       DBG("__bluetooth_telephony_is_headset -\n");
+       return flag;
+}
+
+static int __bluetooth_telephony_get_connected_device(void)
+{
+       DBusGProxy *list_proxy = NULL;
+       DBusGProxy *device_proxy = NULL;
+       GPtrArray *gp_array = NULL;
+       GError *error = NULL;
+       gchar *gp_path = NULL;
+       GHashTable *list_hash = NULL;
+       GHashTable *device_hash = NULL;
+       GValue *value = {0};
+       uint32_t device_class;
+       gboolean playing = FALSE;
+       gboolean connected = FALSE;
+       const gchar *address;
+       char object_path[BT_ADAPTER_PATH_LEN] = {0};
+       int i = 0;
+       DBusGProxy *proxy = NULL;
+
+       DBG("__bluetooth_telephony_get_connected_device +\n");
+
+       /*Get default adapter path*/
+       if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
+                       object_path) < 0)
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       /*Get List of All devices*/
+       list_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
+                                               BLUEZ_SERVICE_NAME, object_path,
+                                               BLUEZ_ADAPTER_INTERFACE);
+
+       if (list_proxy == NULL)
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+
+       dbus_g_proxy_call(list_proxy, "ListDevices", &error, G_TYPE_INVALID,
+                               dbus_g_type_get_collection("GPtrArray",
+                               DBUS_TYPE_G_OBJECT_PATH),
+                               &gp_array, G_TYPE_INVALID);
+
+       if (error != NULL) {
+               g_error_free(error);
+               goto done;
+       }
+
+       if (gp_array == NULL)
+               goto done;
+
+       /*Check for headset devices*/
+       for (i = 0; i < gp_array->len; i++) {
+               gp_path = g_ptr_array_index(gp_array, i);
+
+               if (gp_path == NULL)
+                       goto done;
+
+               proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
+                                               BLUEZ_SERVICE_NAME, gp_path,
+                                               BLUEZ_DEVICE_INTERFACE);
+
+               if (proxy == NULL)
+                       goto done;
+
+               dbus_g_proxy_call(proxy, "GetProperties", NULL,
+                               G_TYPE_INVALID, dbus_g_type_get_map(
+                               "GHashTable", G_TYPE_STRING,
+                               G_TYPE_VALUE), &list_hash, G_TYPE_INVALID);
+
+               if (list_hash == NULL)
+                       goto done;
+
+               value = g_hash_table_lookup(list_hash, "Class");
+               device_class = value ? g_value_get_uint(value) : 0;
+
+               if (!__bluetooth_telephony_is_headset(device_class)) {
+                       g_object_unref(proxy);
+                       proxy = NULL;
+                       g_free(gp_path);
+                       gp_path = NULL;
+                       continue;
+               }
+
+               /*Check for Connection*/
+               device_proxy = dbus_g_proxy_new_for_name(
+                               telephony_dbus_info.conn,
+                               BLUEZ_SERVICE_NAME, gp_path,
+                               BLUEZ_HEADSET_INTERFACE);
+
+               if (device_proxy == NULL)
+                       goto done;
+
+               dbus_g_proxy_call(device_proxy, "GetProperties",
+                               &error, G_TYPE_INVALID,
+                               dbus_g_type_get_map("GHashTable",
+                               G_TYPE_STRING, G_TYPE_VALUE),
+                               &device_hash, G_TYPE_INVALID);
+
+               if (error == NULL) {
+                       value = g_hash_table_lookup(device_hash,
+                                       "Connected");
+                       connected = value ? g_value_get_boolean(
+                                       value) : FALSE;
+                       if (connected) {
+                               value = g_hash_table_lookup(list_hash,
+                                                               "Address");
+                               address = value ? g_value_get_string(
+                                                       value) : NULL;
+                               g_strlcpy(telephony_info.address, address,
+                                               sizeof(telephony_info.address));
+                               value = g_hash_table_lookup(device_hash,
+                                                               "Playing");
+                               playing = value ? g_value_get_boolean(
+                                                       value) : FALSE;
+                               if (playing)
+                                       telephony_info.headset_state =
+                                               BLUETOOTH_STATE_PLAYING;
+                               else
+                                       telephony_info.headset_state =
+                                               BLUETOOTH_STATE_CONNECTED;
+
+                               goto done;
+                       }
+               } else
+                       g_error_free(error);
+
+               g_object_unref(proxy);
+               proxy = NULL;
+               g_free(gp_path);
+               gp_path = NULL;
+       }
+done:
+       if (list_proxy)
+               g_object_unref(list_proxy);
+       if (device_proxy)
+               g_object_unref(device_proxy);
+       if (proxy)
+               g_object_unref(proxy);
+       g_free(gp_path);
+       g_ptr_array_free(gp_array, TRUE);
+       DBG("__bluetooth_telephony_get_connected_device -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+}
+
+static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
+{
+       DBusGProxy *proxy = NULL;
+       char object_path[BT_ADAPTER_PATH_LEN] = {0};
+       GError *error = NULL;
+       DBusGProxy *default_proxy;
+
+       DBG("__bluetooth_telephony_get_connected_device_proxy + \n");
+
+       /*Get default adapter path*/
+       if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
+                       object_path) < 0)
+               return NULL;
+
+       /*Get List of All devices*/
+       default_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
+                                               BLUEZ_SERVICE_NAME, object_path,
+                                               BLUEZ_ADAPTER_INTERFACE);
+
+       if (default_proxy == NULL)
+               return NULL;
+
+       if (strlen(telephony_info.address) == 0)
+               __bluetooth_telephony_get_connected_device();
+
+       if (strlen(telephony_info.address) == 0) {
+               g_object_unref(default_proxy);
+               return NULL;
+       }
+
+       if (NULL == telephony_info.obj_path) {
+               dbus_g_proxy_call(default_proxy, "FindDevice", &error,
+                               G_TYPE_STRING, telephony_info.address,
+                               G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
+                               &telephony_info.obj_path,
+                               G_TYPE_INVALID);
+               if (error != NULL) {
+                       DBG("dbus_g_proxy_call Failed!\n");
+                       g_error_free(error);
+                       g_object_unref(default_proxy);
+                       return NULL;
+               }
+       }
+
+       proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
+                       BLUEZ_SERVICE_NAME, telephony_info.obj_path,
+                       BLUEZ_HEADSET_INTERFACE);
+
+       g_object_unref(default_proxy);
+
+       return proxy;
+}
+
+BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
+                                                       void  *user_data)
+{
+       DBusError dbus_error;
+       DBusConnection *conn;
+       int ret;
+       GError *error = NULL;
+       char object_path[BT_ADAPTER_PATH_LEN] = {0};
+       DBG("bluetooth_telephony_init +\n");
+
+       if (NULL == cb)
+               return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
+
+       if (telephony_dbus_info.conn != NULL) {
+               DBG("Bluetooth telephony already initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
+       }
+
+       telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+       if (!telephony_dbus_info.conn) {
+               if (NULL != error) {
+                       DBG("dbus_g_bus_get() failed:[%d:%s]\n",
+                                       error->code, error->message);
+                       g_error_free(error);
+               }
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name(
+                                               telephony_dbus_info.conn,
+                                               BLUEZ_SERVICE_NAME,
+                                               "/", BLUEZ_MANAGER_INTERFACE);
+
+       if (telephony_dbus_info.manager_proxy == NULL) {
+               DBG("Could not create a manager proxy\n");
+               dbus_g_connection_unref(telephony_dbus_info.conn);
+               telephony_dbus_info.conn = NULL;
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+
+       /*Check for BT status*/
+       ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
+                                                               object_path);
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               dbus_g_connection_unref(telephony_dbus_info.conn);
+               telephony_dbus_info.conn = NULL;
+               g_object_unref(telephony_dbus_info.manager_proxy);
+               telephony_dbus_info.manager_proxy = NULL;
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED;
+       }
+       /*Bluetooth is active, therefore set the flag */
+       is_active = TRUE;
+
+       /* Call Path */
+       snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
+                                       CSD_CALL_APP_PATH, getpid());
+       DBG("Call Path = %s \n", telephony_info.call_path);
+       memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
+
+       if (__bluetooth_telephony_proxy_init()) {
+               DBG("__bluetooth_telephony_proxy_init failed\n");
+               dbus_g_connection_unref(telephony_dbus_info.conn);
+               telephony_dbus_info.conn = NULL;
+               g_object_unref(telephony_dbus_info.manager_proxy);
+               telephony_dbus_info.manager_proxy = NULL;
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       ret = __bluetooth_telephony_register(cb, user_data);
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("__bluetooth_telephony_register failed\n");
+               __bluetooth_telephony_proxy_deinit();
+               dbus_g_connection_unref(telephony_dbus_info.conn);
+               telephony_dbus_info.conn = NULL;
+               g_object_unref(telephony_dbus_info.manager_proxy);
+               telephony_dbus_info.manager_proxy = NULL;
+               return ret;
+       }
+
+       dbus_error_init(&dbus_error);
+       conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
+       dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
+                               NULL, NULL);
+
+       dbus_bus_add_match(conn,
+                       "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
+                       "',member='PropertyChanged'", &dbus_error);
+
+       if (dbus_error_is_set(&dbus_error)) {
+               DBG("Fail to add dbus filter signal\n");
+               dbus_error_free(&dbus_error);
+               __bluetooth_telephony_unregister();
+               __bluetooth_telephony_proxy_deinit();
+               dbus_connection_remove_filter(dbus_g_connection_get_connection(
+                               telephony_dbus_info.conn),
+                               __bluetooth_telephony_event_filter, NULL);
+               dbus_g_connection_unref(telephony_dbus_info.conn);
+               telephony_dbus_info.conn = NULL;
+               g_object_unref(telephony_dbus_info.manager_proxy);
+               telephony_dbus_info.manager_proxy = NULL;
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+
+       DBG("bluetooth_telephony_init -\n");
+       return ret;
+}
+
+BT_EXPORT_API int bluetooth_telephony_deinit(void)
+{
+       DBG("bluetooth_telephony_deinit +\n");
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       dbus_connection_remove_filter(dbus_g_connection_get_connection(
+                               telephony_dbus_info.conn),
+                               __bluetooth_telephony_event_filter, NULL);
+
+       __bluetooth_telephony_unregister();
+       __bluetooth_telephony_proxy_deinit();
+
+       g_object_unref(telephony_dbus_info.manager_proxy);
+       telephony_dbus_info.manager_proxy = NULL;
+
+       dbus_g_connection_unref(telephony_dbus_info.conn);
+       telephony_dbus_info.conn = NULL;
+
+       DBG("bluetooth_telephony_deinit -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
+{
+       DBG("+ \n");
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return FALSE;
+       }
+
+       if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
+               return TRUE;
+
+       DBG("- \n");
+       return FALSE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
+{
+       GError *error = NULL;
+       int ret;
+
+       DBG("+\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       if (telephony_dbus_info.proxy == NULL)
+               telephony_dbus_info.proxy =
+                       __bluetooth_telephony_get_connected_device_proxy();
+
+       if (telephony_dbus_info.proxy == NULL)
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+
+       if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
+                       &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
+                       G_TYPE_INVALID)) {
+               if (error != NULL) {
+                       ret = __bt_telephony_get_error(error->message);
+                       g_error_free(error);
+                       return ret;
+               }
+       }
+
+       DBG("-\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
+{
+       GError *error = NULL;
+       int ret;
+
+       DBG("+\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       if (telephony_dbus_info.proxy == NULL)
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+
+       if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
+                               &error, G_TYPE_BOOLEAN,
+                               FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
+               DBG("Dbus Call Failed!\n");
+               if (error != NULL) {
+                       ret = __bt_telephony_get_error(error->message);
+                       g_error_free(error);
+                       return ret;
+               }
+       }
+
+       DBG("-\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_audio_open(void)
+{
+       GError *error = NULL;
+       int ret;
+
+       DBG("bluetooth_telephony_audio_open +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
+               return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
+
+       if (telephony_dbus_info.proxy == NULL)
+               telephony_dbus_info.proxy =
+                       __bluetooth_telephony_get_connected_device_proxy();
+
+       if (telephony_dbus_info.proxy == NULL)
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+
+       if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
+                                       G_TYPE_INVALID, G_TYPE_INVALID)) {
+               DBG("Dbus Call Failed!\n");
+               if (error != NULL) {
+                       ret = __bt_telephony_get_error(error->message);
+                       g_error_free(error);
+                       return ret;
+               }
+       }
+       DBG("bluetooth_telephony_audio_open -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_audio_close(void)
+{
+       GError *error = NULL;
+       int ret;
+
+       DBG("bluetooth_telephony_audio_close +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
+       }
+
+       if (NULL == telephony_dbus_info.proxy)
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+
+       if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
+                       G_TYPE_INVALID, G_TYPE_INVALID)) {
+               DBG("Dbus Call Failed!\n");
+               if (error != NULL) {
+                       ret = __bt_telephony_get_error(error->message);
+                       g_error_free(error);
+                       return ret;
+               }
+       }
+
+       DBG("bluetooth_telephony_audio_close -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
+{
+       int ret;
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       DBG("bluetooth_telephony_call_remote_ringing +\n");
+       /*Make sure SCO is already connected */
+       ret = __bluetooth_telephony_send_call_status(
+                               CSD_CALL_STATUS_MO_ALERTING, call_id);
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("send call status Failed = [%d]\n", ret);
+               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+       }
+       DBG("bluetooth_telephony_call_remote_ringing -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
+                                                       unsigned int bt_audio)
+{
+       int ret;
+       DBG("bluetooth_telephony_call_answered +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
+                                                               call_id);
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("send call status Failed = [%d]\n", ret);
+               return ret;
+       }
+
+       if (bt_audio) {
+               if (!bluetooth_telephony_is_sco_connected()) {
+                       ret = bluetooth_telephony_audio_open();
+                       if (ret != 0) {
+                               DBG(" Audio connection call Failed = %d\n", ret);
+                               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+                       }
+               }
+       }
+
+       DBG("bluetooth_telephony_call_answered -\n");
+       return ret;
+}
+
+BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
+{
+       int ret;
+       DBG("bluetooth_telephony_call_end +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
+                                                               call_id);
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("send call status Failed = [%d]\n", ret);
+               return ret;
+       }
+       if (telephony_info.call_count > 0)
+               telephony_info.call_count = telephony_info.call_count - 1;
+
+       if (telephony_info.call_count  == 0) {
+               if (bluetooth_telephony_is_sco_connected()) {
+                       ret = bluetooth_telephony_audio_close();
+                       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+                               DBG(" Failed = [%d]\n", ret);
+                               return ret;
+                       }
+               }
+       }
+       DBG("bluetooth_telephony_call_end -\n");
+       return ret;
+}
+
+BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
+{
+       int ret;
+       DBG("bluetooth_telephony_call_held +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
+                                                               call_id);
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("send call status Failed = [%d]\n", ret);
+       }
+       DBG("bluetooth_telephony_call_held -\n");
+       return ret;
+}
+
+BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
+{
+       int ret;
+       DBG("bluetooth_telephony_call_retrieved +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
+                                                               call_id);
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("send call status Failed = [%d]\n", ret);
+       }
+       DBG("bluetooth_telephony_call_retrieved -\n");
+       return ret;
+}
+
+BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
+                               unsigned int call_count)
+{
+       int i;
+       int ret;
+       GList *list = call_list;
+       bt_telephony_call_status_info_t *call_status;
+
+       DBG("bluetooth_telephony_call_swapped +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       if (NULL == list) {
+               DBG("call_list is invalid \n");
+               return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
+       }
+
+       DBG(" call_count = [%d] \n", call_count);
+
+       for (i = 0; i < call_count; i++) {
+               call_status = g_list_nth_data(list, i);
+
+               if (NULL == call_status)
+                       continue;
+
+               DBG(" %d : Call id [%d] status[%d]\n", i,
+                                       call_status->call_id,
+                                       call_status->call_status);
+
+               switch (call_status->call_status) {
+               case BLUETOOTH_CALL_STATE_HELD:
+                       ret = __bluetooth_telephony_send_call_status(
+                                               CSD_CALL_STATUS_HOLD,
+                                               call_status->call_id);
+                       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+                               DBG("Failed = %d\n", ret);
+                               return ret;
+                       }
+               break;
+
+               case BLUETOOTH_CALL_STATE_CONNECTED:
+                       ret = __bluetooth_telephony_send_call_status(
+                                       CSD_CALL_STATUS_ACTIVE,
+                                       call_status->call_id);
+                       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+                               DBG("Failed = [%d]\n", ret);
+                               return ret;
+                       }
+               break;
+
+               default:
+                       DBG(" Unknown Call state\n");
+                       return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
+               }
+       }
+
+       DBG("bluetooth_telephony_call_swapped -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
+                               unsigned int call_count)
+{
+       int ret;
+
+       DBG("bluetooth_telephony_set_call_status +\n");
+
+       ret = bluetooth_telephony_call_swapped(call_list, call_count);
+
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
+               DBG("bluetooth_telephony_call_swapped Failed = [%d]\n", ret);
+               return ret;
+       }
+
+       telephony_info.call_count = call_count;
+
+       DBG("bluetooth_telephony_set_call_status -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
+                       const char *ph_number, unsigned int call_id,
+                       unsigned int bt_audio)
+{
+       const char *path = telephony_info.call_path;
+       int ret;
+
+       DBG("bluetooth_telephony_indicate_outgoing_call +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       if (NULL == ph_number)
+               return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
+
+       ret = __bluetooth_telephony_dbus_method_send(
+                       HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
+                       "OutgoingCall", DBUS_TYPE_STRING, &path,
+                       DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
+                       &call_id, DBUS_TYPE_INVALID);
+
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
+               return ret;
+
+
+       telephony_info.call_count++;
+       DBG(" ag_info.ag_call_count = [%d]\n", telephony_info.call_count);
+
+       if (bt_audio) {
+               if (!bluetooth_telephony_is_sco_connected()) {
+                       ret = bluetooth_telephony_audio_open();
+                       if (ret != 0) {
+                               DBG(" Audio connection call Failed = %d\n", ret);
+                               return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
+                       }
+               }
+       }
+
+       DBG("bluetooth_telephony_indicate_outgoing_call -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
+               const char *ph_number, unsigned int call_id)
+{
+       const char *path = telephony_info.call_path;
+       int ret;
+
+       DBG("bluetooth_telephony_indicate_incoming_call +\n");
+
+       BT_TELEPHONY_CHECK_BT_STATUS();
+
+       if (telephony_dbus_info.conn == NULL) {
+               DBG("Bluetooth telephony not initilized \n");
+               return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED;
+       }
+
+       if (NULL == ph_number)
+               return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
+
+       ret = __bluetooth_telephony_dbus_method_send(
+                       HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
+                       "IncomingCall", DBUS_TYPE_STRING, &path,
+                       DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
+                       &call_id, DBUS_TYPE_INVALID);
+
+       if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
+               return ret;
+
+       telephony_info.call_count++;
+       DBG(" telephony_info.call_count = [%d]\n", telephony_info.call_count);
+       DBG("bluetooth_telephony_indicate_incoming_call -\n");
+       return BLUETOOTH_TELEPHONY_ERROR_NONE;
+}
diff --git a/bluetooth-telephony/bluetooth-telephony-api.h b/bluetooth-telephony/bluetooth-telephony-api.h
new file mode 100644 (file)
index 0000000..30c1bec
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Bluetooth-telephony
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             GirishAshok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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 _BLUETOOTH_TELEPHONY_API_H_
+#define _BLUETOOTH_TELEPHONY_API_H_
+
+#include <stdint.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dlog.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+typedef int (*bt_telephony_func_ptr)(int, void *, void *);
+
+#define BLUETOOTH_TELEPHONY_ERROR_NONE ((int)0)
+#define BLUETOOTH_TELEPHONY_ERROR_INTERNAL \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x01)
+#define BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x02)
+#define BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x03)
+#define BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x04)
+#define BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x05)
+#define BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x06)
+#define BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x07)
+#define BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x08)
+#define BLUETOOTH_TELEPHONY_ERROR_BUSY \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x09)
+#define BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0A)
+#define BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0B)
+#define BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0C)
+#define BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0D)
+#define BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE \
+                               ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0E)
+
+#define BT_ADDRESS_STR_LEN 18
+#define BT_ADAPTER_PATH_LEN 50
+#define BT_AUDIO_CALL_PATH_LEN 50
+
+typedef struct {
+       int event;
+       int result;
+       void *param_data;
+} telephony_event_param_t;
+
+typedef struct {
+        int callid;
+} telephony_event_callid_t;
+
+typedef struct {
+       gchar *dtmf;
+} telephony_event_dtmf_t;
+
+typedef enum {
+       BLUETOOTH_STATE_CONNECTED,
+       BLUETOOTH_STATE_PLAYING,
+       BLUETOOTH_STATE_DISCONNETED,
+} bluetooth_headset_state_t;
+
+typedef struct {
+       bt_telephony_func_ptr cb;
+       unsigned int call_count;
+       char *obj_path;
+       char address[BT_ADDRESS_STR_LEN];
+       char call_path[BT_AUDIO_CALL_PATH_LEN];
+       bluetooth_headset_state_t headset_state;
+       void *user_data;
+} bt_telephony_info_t;
+
+typedef enum {
+       BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX,
+       BLUETOOTH_TELEPHONY_ERROR_BATTERY_STATUS,
+       BLUETOOTH_TELEPHONY_ERROR_SIGNAL_STATUS,
+       BLUETOOTH_TELEPHONY_ERROR_NOT_SUPPORTED,
+       BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
+       BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
+} bluetooth_telephony_error_t;
+
+typedef enum {
+       CSD_CALL_STATUS_IDLE,
+       CSD_CALL_STATUS_CREATE,
+       CSD_CALL_STATUS_COMING,
+       CSD_CALL_STATUS_PROCEEDING,
+       CSD_CALL_STATUS_MO_ALERTING,
+       CSD_CALL_STATUS_MT_ALERTING,
+       CSD_CALL_STATUS_WAITING,
+       CSD_CALL_STATUS_ANSWERED,
+       CSD_CALL_STATUS_ACTIVE,
+       CSD_CALL_STATUS_MO_RELEASE,
+       CSD_CALL_STATUS_MT_RELEASE,
+       CSD_CALL_STATUS_HOLD_INITIATED,
+       CSD_CALL_STATUS_HOLD,
+       CSD_CALL_STATUS_RETRIEVE_INITIATED,
+       CSD_CALL_STATUS_RECONNECT_PENDING,
+       CSD_CALL_STATUS_TERMINATED,
+       CSD_CALL_STATUS_SWAP_INITIATED,
+} bt_telephony_call_status_t;
+
+#define BLUETOOTH_EVENT_TYPE_TELEPHONY_BASE    (unsigned int)(0x00100)
+
+typedef enum {
+       BLUETOOTH_EVENT_AG_ANSWER = BLUETOOTH_EVENT_TYPE_TELEPHONY_BASE,
+       BLUETOOTH_EVENT_AG_RELEASE,
+       BLUETOOTH_EVENT_AG_REJECT,
+       BLUETOOTH_EVENT_AG_CALL_HOLD_RELEASE_ALL,
+       BLUETOOTH_EVENT_AG_CALL_HOLD_RELEASE_ACTIVE,
+       BLUETOOTH_EVENT_AG_CALL_HOLD_HOLD_ACTIVE,
+       BLUETOOTH_EVENT_AG_CALL_HOLD_ADD_NEW,
+       BLUETOOTH_EVENT_AG_CALL_HOLD_TRANSFER,
+       BLUETOOTH_EVENT_AG_DTMF,
+       BLUETOOTH_EVENT_BT_ENABLED,
+       BLUETOOTH_EVENT_BT_DISABLED,
+       BLUETOOTH_EVENT_AUDIO_CONNECTED,
+       BLUETOOTH_EVENT_AUDIO_DISCONNECTED,
+} bluetooth_telephony_event_type;
+
+typedef enum {
+       BLUETOOTH_CALL_STATE_NONE,
+       BLUETOOTH_CALL_STATE_DIALLING,
+       BLUETOOTH_CALL_STATE_INCOMING,
+       BLUETOOTH_CALL_STATE_INCOMING_HELD,
+       BLUETOOTH_CALL_STATE_CONNECTED,
+       BLUETOOTH_CALL_STATE_HELD,
+       BLUETOOTH_CALL_STATE_RETRIEVED,
+       BLUETOOTH_CALL_STATE_RETRIVING,
+       BLUETOOTH_CALL_STATE_WAITING,
+       BLUETOOTH_CALL_STATE_ALERTING,
+       BLUETOOTH_CALL_STATE_CANDIDATE
+} bt_telephony_call_state_t;
+
+typedef struct {
+       unsigned int call_id;
+       bt_telephony_call_state_t call_status;
+} bt_telephony_call_status_info_t;
+
+/**
+ * @brief      The function bluetooth_telephony_init is initialize telephony calls.
+ *
+ * @param[in]  cb      Callback function
+ * @param[in]  user_data       Data sent by application, which will be
+ *                             returned in event handler.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_init(bt_telephony_func_ptr cb, void  *user_data);
+
+/**
+ * @brief      The function bluetooth_telephony_deinit is deinitialize telephony calls.
+ *
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_deinit(void);
+
+/**
+ * @brief      The function bluetooth_telephony_audio_open is to open SCO channel
+ *
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_audio_open(void);
+
+/**
+ * @brief      The function bluetooth_telephony_audio_close is to close SCO channel.
+ *     that the Volume on AG is changed.
+ *
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_audio_close(void);
+
+/**
+  * @brief     The function bluetooth_telephony_call_remote_ringing is send
+  *    call status.
+ *
+ * @param[in]  call_id Call Id.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_call_remote_ringing(unsigned int call_id);
+
+/**
+ * @brief      The function bluetooth_telephony_call_answered is called to
+ *     answer calls.
+ *
+ * @param[in]  call_id Call Id.
+  * @param[in] bt_audio        flag
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_call_answered(unsigned int call_id,
+                                               unsigned int bt_audio);
+
+/**
+ * @brief      The function bluetooth_telephony_call_end to end call
+ *
+ * @param[in]  call_id Call Id.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_call_end(unsigned int call_id);
+
+/**
+ * @brief      The function bluetooth_telephony_call_held to hold call
+ *
+ * @param[in]  call_id Call Id.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_call_held(unsigned int call_id);
+
+/**
+ * @brief      The function bluetooth_telephony_call_retrieved to retrieve call
+ *
+ * @param[in]  call_id Call Id.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_call_retrieved(unsigned int call_id);
+
+/**
+ * @brief      The function bluetooth_telephony_call_swapped to swap call
+ *
+ * @param[in]  call_list       Call info such as id and status.
+ * @param[in]  call_count      Call count.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_call_swapped(void *call_list,
+                               unsigned int call_count);
+
+/**
+ * @brief      The function bluetooth_telephony_set_call_status to set call status
+ *
+ * @param[in]  call_list       Call info such as id and status.
+ * @param[in]  call_count      Call count.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_set_call_status(void *call_list,
+                               unsigned int call_count);
+
+/**
+ * @brief      The function bluetooth_telephony_indicate_outgoing_call toindicate
+ *     outgoing call.
+ *
+ * @param[in]  ph_number       Phone number of the outgoing call.
+ * @param[in]  call_id         Call ID.
+ * @param[in]  bt_audio                Flag.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_indicate_outgoing_call(
+               const char *ph_number, unsigned int call_id,
+               unsigned int bt_audio);
+
+/**
+ * @brief      The function bluetooth_telephony_indicate_incoming_call  to indicate
+ *     incoming call.
+ *
+ * @param[in]  call_info       Call info such as id and status.
+ * @param[in]  call_count      Call count.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_telephony_indicate_incoming_call(
+               const char *ph_number, unsigned int call_id);
+
+/**
+ * @brief      The function bluetooth_telephony_is_sco_connected  to check
+ *             if SCO channel is connected.
+ *
+ * @return     gboolean        TRUE if headset playing else FALSE.
+ *
+ */
+gboolean bluetooth_telephony_is_sco_connected(void);
+
+/**
+ * @brief This function sends request to enable voice recognition feature
+ *
+ * @return     int     Zero on Success or reason for error if any.
+ */
+ int bluetooth_telephony_start_voice_recognition(void);
+
+/**
+ * @brief This function sends request to disable voice recognition feature
+ *
+ * @return     int     Zero on Success or reason for error if any.
+ */
+ int bluetooth_telephony_stop_voice_recognition(void);
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+#endif/*_BLUETOOTH_TELEPHONY_API_H_*/
diff --git a/bluetooth-telephony/bluetooth-telephony-internal.h b/bluetooth-telephony/bluetooth-telephony-internal.h
new file mode 100644 (file)
index 0000000..47f646f
--- /dev/null
@@ -0,0 +1,95 @@
+/*\r
+ * bluetooth-telephony\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>\r
+ *             GirishAshok Joshi <girish.joshi@samsung.com>\r
+ *             DoHyun Pyun <dh79.pyun@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+#ifndef _BLUETOOTH_TELEPHONY_INTERNAL_H_\r
+#define _BLUETOOTH_TELEPHONY_INTERNAL_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C"{\r
+#endif /*__cplusplus*/\r
+\r
+#define BLUETOOTH_TELEPHONY_METHOD (bluetooth_telephony_method_get_type())\r
+#define BLUETOOTH_TELEPHONY_METHOD_GET_OBJECT(obj) \\r
+               (G_TYPE_CHECK_INSTANCE_CAST((obj), \\r
+               BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethod))\r
+\r
+#define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \\r
+               (G_TYPE_CHECK_INSTANCE_TYPE((obj), \\r
+               BLUETOOTH_TELEPHONY_METHOD))\r
+\r
+#define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \\r
+               (G_TYPE_CHECK_CLASS_CAST((class), \\r
+               BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))\r
+\r
+#define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \\r
+               (G_TYPE_INSTANCE_GET_CLASS((obj), \\r
+               BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))\r
+\r
+#define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \\r
+               (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD))\r
+\r
+#define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \\r
+               (G_TYPE_INSTANCE_GET_PRIVATE((obj), \\r
+               BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate))\r
+\r
+typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod;\r
+typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass;\r
+\r
+struct _BluetoothTelephonyMethod {\r
+       GObject parent;\r
+};\r
+\r
+struct _BluetoothTelephonyMethodClass {\r
+       GObjectClass parent_class;\r
+};\r
+\r
+BluetoothTelephonyMethod *bluetooth_telephony_method_new(void);\r
+GType bluetooth_telephony_method_get_type(void);\r
+\r
+G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT)\r
+\r
+\r
+static gboolean bluetooth_telephony_method_answer(BluetoothTelephonyMethod *object,\r
+                               guint callid,\r
+                               DBusGMethodInvocation *context);\r
+\r
+static gboolean bluetooth_telephony_method_release(\r
+                               BluetoothTelephonyMethod *object, guint callid,\r
+                               DBusGMethodInvocation *context);\r
+\r
+static gboolean bluetooth_telephony_method_reject(BluetoothTelephonyMethod  *object,\r
+                               guint callid, DBusGMethodInvocation *context);\r
+\r
+static gboolean bluetooth_telephony_method_threeway(\r
+                               BluetoothTelephonyMethod *object, guint value,\r
+                               DBusGMethodInvocation *context);\r
+\r
+static gboolean bluetooth_telephony_method_send_dtmf(\r
+                               BluetoothTelephonyMethod *object,\r
+                               gchar *dtmf, DBusGMethodInvocation *context);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif /*__cplusplus*/\r
+\r
+#endif /*_BLUETOOTH_TELEPHONY_INTERNAL_H_*/\r
diff --git a/bluetooth-telephony/bluetooth-telephony.pc.in b/bluetooth-telephony/bluetooth-telephony.pc.in
new file mode 100644 (file)
index 0000000..ae974bd
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: bluetooth-telephony
+Description: Tizen Linux platform Bluetooth Telephony API
+Version: @VERSION@
+Requires: dlog dbus-glib-1 vconf
+Libs: -L${libdir} -lbluetooth-telephony
+Cflags: -I${includedir} -I${includedir}/bluetooth-telephony
diff --git a/bluetooth-telephony/bt_telephony_frwk.xml b/bluetooth-telephony/bt_telephony_frwk.xml
new file mode 100644 (file)
index 0000000..8cb4f63
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node>
+  <interface name="org.tizen.csd.Call.Instance">
+    <method name="Answer">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+       <arg type="u" name="callid"/>
+    </method>
+
+    <method name="Release">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="callid"/>
+    </method>
+
+    <method name="Reject">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="callid"/>
+    </method>
+
+    <method name="Threeway">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="value"/>
+    </method>
+
+    <method name="SendDtmf">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="dtmf"/>
+    </method>
+
+  </interface>
+  </node>
diff --git a/bluetooth-telephony/marshal.list b/bluetooth-telephony/marshal.list
new file mode 100644 (file)
index 0000000..3116498
--- /dev/null
@@ -0,0 +1,5 @@
+# DBUS Signal argument converting list for bluetooth telephony  lib
+VOID:UINT
+VOID:INT
+VOID:STRING,UINT
+VOID:STRING
diff --git a/debian/libbluetooth-frwk-0.postinst b/debian/libbluetooth-frwk-0.postinst
new file mode 100644 (file)
index 0000000..25c2099
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# root case
+if [ ${USER} == "root" ]
+then
+       # Set vconf values with -g/-u options
+
+       # 6520 is vconf_bt
+       vconftool set -t int db/bluetooth/status "0" -g 6520
+       vconftool set -t int memory/private/libbluetooth-frwk-0/obex_no_agent "0" -g 6520 -i
+       vconftool set -t string memory/private/libbluetooth-frwk-0/uuid "" -g 6520 -i
+       vconftool set -t string memory/bluetooth/sco_headset_name "" -g 6520 -i
+fi
\ No newline at end of file
diff --git a/lib/bluetooth-audio-api.c b/lib/bluetooth-audio-api.c
new file mode 100644 (file)
index 0000000..092c13a
--- /dev/null
@@ -0,0 +1,1288 @@
+/*
+ * Bluetooth-audio-api
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             GirishAshok Joshi <girish.joshi@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 <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include "vconf.h"
+#include "vconf-keys.h"
+
+#include "bluetooth-audio-api.h"
+#include "bluetooth-api-common.h"
+
+#define AUDIO_DBUS_SERVICE     "org.bluez"
+#define AUDIO_AG_DBUS_INTERFACE        "org.bluez.Headset"
+#define AUDIO_SINK_DBUS_INTERFACE      "org.bluez.AudioSink"
+#define AUDIO_DBUS_INTERFACE   "org.bluez.Audio"
+
+#define BLUETOOTH_PHONE_STATUS_HEADSET_STATE   VCONFKEY_BT_DEVICE
+
+#ifndef VCONFKEY_BT_HEADSET_NAME
+#define VCONFKEY_BT_HEADSET_NAME       "memory/bluetooth/sco_headset_name"
+#endif
+#define BLUETOOTH_SCO_HEADSET_NAME     VCONFKEY_BT_HEADSET_NAME
+#define BLUETOOTH_AG_ADAPTER_PATH_LENGTH       50
+
+typedef enum {
+       BT_AUDIO_HSP = 0x00,
+       BT_AUDIO_A2DP,
+       BT_AUDIO_ALL,
+} bt_audio_type_t;
+
+typedef struct {
+       DBusGConnection *audio_conn;
+       DBusGProxy *manager_proxy;
+       char *audio_obj_path;
+} audio_dbus_info_t;
+
+static bt_audio_info_t audio_info;
+static audio_dbus_info_t audio_dbus_info;
+static DBusConnection *audio_connection = NULL;
+
+#define BT_AUDIO "BT_AUDIO"
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(fmt, args...) SLOG(LOG_DEBUG, BT_AUDIO,\
+                               "%s():%d "fmt, __func__, __LINE__, ##args)
+
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(fmt, args...) SLOG(LOG_ERROR, BT_AUDIO, \
+                               "%s():%d "fmt, __func__, __LINE__, ##args)
+
+static DBusGProxy *current_proxy;
+static DBusGProxyCall *current_call;
+
+static void __bluetooth_audio_internal_event_cb(int event, int result,
+                                                       void *param_data)
+{
+       bt_audio_event_param_t bt_event = { 0, };
+
+       DBG("__bluetooth_audio_internal_event_cb +\n");
+
+       bt_event.event = event;
+       bt_event.result = result;
+       bt_event.param_data = param_data;
+
+       if (audio_info.audio_cb)
+               audio_info.audio_cb(bt_event.event, &bt_event,
+                                       audio_info.user_data);
+
+       DBG("__bluetooth_audio_internal_event_cb -\n");
+}
+
+static DBusGProxy *__bluetooth_get_adapter_proxy(void)
+{
+       DBusGProxy *proxy;
+       char *adapter_path = NULL;
+
+       if (audio_dbus_info.manager_proxy == NULL)
+               return NULL;
+
+       if (!dbus_g_proxy_call(audio_dbus_info.manager_proxy,
+                       "DefaultAdapter", NULL,
+                       G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
+                       &adapter_path, G_TYPE_INVALID)) {
+               ERR("Fait to get DefaultAdapter");
+               return NULL;
+       }
+
+       adapter_path = g_strdup(adapter_path);
+       if (adapter_path == NULL)
+               return NULL;
+
+       proxy = dbus_g_proxy_new_for_name(audio_dbus_info.audio_conn,
+                               AUDIO_DBUS_SERVICE,
+                               adapter_path,
+                               "org.bluez.Adapter");
+
+       g_free(adapter_path);
+
+       return proxy;
+}
+
+static char *__bluetooth_get_audio_path(bluetooth_device_address_t *address)
+{
+
+       char *object_path = NULL;
+       char addr_str[BT_ADDRESS_STRING_SIZE + 1] = { 0 };
+       DBusGProxy *proxy;
+       DBusGProxy *adapter;
+       GError *error = NULL;
+
+       if (audio_dbus_info.audio_conn == NULL)
+               return NULL;
+
+       if (address == NULL)
+               return NULL;
+
+       adapter = __bluetooth_get_adapter_proxy();
+
+       if (adapter == NULL)
+               return NULL;
+
+       _bluetooth_internal_addr_type_to_addr_string(addr_str, address);
+
+       dbus_g_proxy_call(adapter, "FindDevice",
+                         &error, G_TYPE_STRING, addr_str,
+                         G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
+                         &object_path, G_TYPE_INVALID);
+
+       g_object_unref(adapter);
+
+       if (error != NULL) {
+               DBG("Failed to Find device: %s\n", error->message);
+               g_error_free(error);
+               return NULL;
+       }
+
+       if (object_path == NULL)
+               return NULL;
+
+       proxy = dbus_g_proxy_new_for_name(audio_dbus_info.audio_conn,
+                                       AUDIO_DBUS_SERVICE,
+                                       object_path,
+                                       AUDIO_AG_DBUS_INTERFACE);
+
+       if (proxy == NULL)
+               return NULL;
+
+       g_object_unref(proxy);
+
+       return g_strdup(object_path);
+}
+
+static char *__bluetooth_get_connected_audio_path(void)
+{
+       int i;
+       char *audio_path = NULL;
+       GPtrArray *devinfo = NULL;
+       bluetooth_device_info_t *ptr;
+
+       /* allocate the g_pointer_array */
+       devinfo = g_ptr_array_new();
+
+       if (bluetooth_get_bonded_device_list(&devinfo)
+                                       != BLUETOOTH_ERROR_NONE) {
+               g_ptr_array_free(devinfo, TRUE);
+               return NULL;
+       }
+
+       DBG("g pointer arrary count : [%d]", devinfo->len);
+       for (i = 0; i < devinfo->len; i++) {
+               ptr = g_ptr_array_index(devinfo, i);
+               if(ptr != NULL) {
+                       if (ptr->connected == TRUE) {
+                               audio_path = __bluetooth_get_audio_path(&ptr->device_address);
+                               if (audio_path)
+                                       break;
+                       }
+               }
+       }
+
+       g_ptr_array_free(devinfo, TRUE);
+
+       return audio_path;
+}
+
+static void __bluetooth_ag_set_name(const char *address)
+{
+       DBusGProxy *device_proxy = NULL;
+       DBusGProxy *adapter_proxy;
+       GHashTable *hash = NULL;
+       GValue *property_value;
+       char *dev_name = NULL;
+       char *device_path = NULL;
+
+       DBG("__bluetooth_ag_get_name +\n");
+
+       if (NULL == audio_dbus_info.audio_conn)
+               return;
+
+       adapter_proxy = __bluetooth_get_adapter_proxy();
+       if (adapter_proxy == NULL)
+               return;
+
+       dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
+                         G_TYPE_STRING, address, G_TYPE_INVALID,
+                         DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
+
+       g_object_unref(adapter_proxy);
+
+       if (device_path == NULL)
+               return;
+
+       device_proxy = dbus_g_proxy_new_for_name(audio_dbus_info.audio_conn,
+                       AUDIO_DBUS_SERVICE, device_path,
+                       "org.bluez.Device");
+
+       if (NULL == device_proxy) {
+               DBG("Getting proxy Failed!\n");
+               return;
+       }
+
+       dbus_g_proxy_call(device_proxy, "GetProperties", NULL, G_TYPE_INVALID,
+                       dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
+                                       G_TYPE_VALUE), &hash, G_TYPE_INVALID);
+
+       if (hash == NULL) {
+               g_object_unref(device_proxy);
+               return;
+       }
+
+       property_value = g_hash_table_lookup(hash, "Name");
+       dev_name = (char *)(property_value ?
+                       g_value_get_string(property_value) : NULL);
+       if (NULL != dev_name) {
+               DBG("Name - [%s]\n", dev_name);
+               int ret = 0;
+               ret = vconf_set_str(BLUETOOTH_SCO_HEADSET_NAME,
+                               (char *)dev_name);
+               if (ret != 0) {
+                       DBG("vconf_set_str failed for [%s]\n",
+                               BLUETOOTH_SCO_HEADSET_NAME);
+               } else {
+                       DBG("Set device_name is  [%s]\n", dev_name);
+               }
+       }
+
+       g_object_unref(device_proxy);
+       DBG("__bluetooth_ag_get_name -\n");
+}
+
+static void __bluetooth_set_ag_state(bt_ag_conn_status_t state)
+{
+       DBG("__bluetooth_set_ag_state +\n");
+
+       switch (audio_info.ag_state) {
+       case BLUETOOTH_AG_STATE_NONE:
+               audio_info.ag_state = state;
+               break;
+       case BLUETOOTH_AG_STATE_CONNECTING:
+               if (BLUETOOTH_AG_STATE_CONNECTED == state) {
+                       DBG("Successfully connected\n");
+                       audio_info.ag_state = state;
+
+               } else if (BLUETOOTH_AG_STATE_DISCONNECTED == state) {
+                       DBG("Connection attempt failed\n");
+                       audio_info.ag_state = state;
+               }
+               break;
+       case BLUETOOTH_AG_STATE_CONNECTED:
+               if (BLUETOOTH_AG_STATE_PLAYING == state) {
+                       DBG("SCO audio connection successfully opened\n");
+                       audio_info.ag_state = state;
+                       audio_info.ag_audio_flag = TRUE;
+               } else if (BLUETOOTH_AG_STATE_DISCONNECTED == state) {
+                       DBG("Disconnected from the remote device");
+                       audio_info.ag_state = state;
+                       audio_info.ag_audio_flag = FALSE;
+                       audio_info.ag_spkr_gain = 0;
+               }
+               break;
+       case BLUETOOTH_AG_STATE_PLAYING:
+               if (BLUETOOTH_AG_STATE_CONNECTED == state) {
+                       DBG("SCO audio connection closed\n");
+                       audio_info.ag_state = state;
+                       audio_info.ag_audio_flag = FALSE;
+               } else if (BLUETOOTH_AG_STATE_DISCONNECTED == state) {
+                       DBG("Disconnected from the remote devicen");
+                       audio_info.ag_state = state;
+                       audio_info.ag_audio_flag = FALSE;
+               }
+               break;
+       case BLUETOOTH_AG_STATE_DISCONNECTED:
+               if (BLUETOOTH_AG_STATE_CONNECTING == state) {
+                       DBG("Either an incoming or outgoing connection"\
+                               "attempt ongoing.\n");
+                       audio_info.ag_state = state;
+               }
+               break;
+       default:
+               break;
+       }
+       DBG("__bluetooth_set_ag_state -\n");
+}
+
+static void __bluetooth_set_ag_remote_speaker_gain(unsigned int speaker_gain)
+{
+       DBG("__bluetooth_set_ag_remote_speaker_gain +\n");
+
+       DBG("speaker_gain = [%d]\n", speaker_gain);
+       audio_info.ag_spkr_gain = speaker_gain;
+
+       __bluetooth_audio_internal_event_cb(BLUETOOTH_EVENT_AG_SPEAKER_GAIN,
+                               BLUETOOTH_AUDIO_ERROR_NONE,
+                               (void *)&speaker_gain);
+
+       DBG("__bluetooth_set_ag_remote_speaker_gain -\n");
+}
+
+static void __bluetooth_set_ag_remote_mic_gain(unsigned int microphone_gain)
+{
+       DBG("__bluetooth_set_ag_remote_mic_gain +\n");
+
+       DBG("microphone_gain = [%d]\n", microphone_gain);
+
+       __bluetooth_audio_internal_event_cb(BLUETOOTH_EVENT_AG_MIC_GAIN,
+                               BLUETOOTH_AUDIO_ERROR_NONE,
+                               (void *)&microphone_gain);
+
+       DBG("__bluetooth_set_ag_remote_mic_gain -\n");
+}
+
+static int __bluetooth_audio_proxy_init(void)
+{
+       GError *error = NULL;
+       DBusGProxy *manager_proxy;
+
+       DBG("__bluetooth_audio_proxy_init +\n");
+       audio_dbus_info.audio_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+       if (!audio_dbus_info.audio_conn) {
+               if (NULL != error) {
+                       DBG("dbus_g_bus_get() failed:[%d:%s]\n",
+                                       error->code, error->message);
+                       g_error_free(error);
+               }
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       audio_connection = dbus_g_connection_get_connection(
+                                       audio_dbus_info.audio_conn);
+
+
+       manager_proxy = dbus_g_proxy_new_for_name(audio_dbus_info.audio_conn,
+                                               AUDIO_DBUS_SERVICE, "/",
+                                               "org.bluez.Manager");
+
+       if (manager_proxy == NULL) {
+               DBG("Could not create a dbus proxy\n");
+               goto error;
+       }
+
+       audio_dbus_info.manager_proxy = manager_proxy;
+
+       DBG("__bluetooth_audio_proxy_init -\n");
+       return BLUETOOTH_AUDIO_ERROR_NONE;
+
+error:
+       dbus_g_connection_unref(audio_dbus_info.audio_conn);
+       audio_dbus_info.audio_conn = NULL;
+       audio_connection = NULL;
+       return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+}
+
+static void __bluetooth_audio_proxy_deinit(void)
+{
+       DBG("__bluetooth_audio_proxy_deinit +\n");
+
+       /* To prevent the crash */
+       if (current_proxy && current_call) {
+               dbus_g_proxy_cancel_call(current_proxy, current_call);
+               current_proxy = NULL;
+               current_call = NULL;
+       }
+
+       if (audio_dbus_info.audio_conn) {
+               dbus_g_connection_unref(audio_dbus_info.audio_conn);
+               audio_dbus_info.audio_conn = NULL;
+       }
+
+       if (audio_dbus_info.manager_proxy) {
+               g_object_unref(audio_dbus_info.manager_proxy);
+               audio_dbus_info.manager_proxy = NULL;
+       }
+
+       audio_connection = NULL;
+
+       DBG("__bluetooth_audio_proxy_deinit -\n");
+}
+
+static void __bluetooth_ag_state_event_handler(char *state)
+{
+       DBG("__bluetooth_ag_state_event_handler +\n");
+
+       DBG("state[%s]\n", state);
+       if (g_strcmp0(state, "connecting") == 0)
+               __bluetooth_set_ag_state(BLUETOOTH_AG_STATE_CONNECTING);
+       else if (g_strcmp0(state, "connected") == 0)
+               __bluetooth_set_ag_state(BLUETOOTH_AG_STATE_CONNECTED);
+       else if (g_strcmp0(state, "playing") == 0)
+               __bluetooth_set_ag_state(BLUETOOTH_AG_STATE_PLAYING);
+       else if (g_strcmp0(state, "disconnected") == 0)
+               __bluetooth_set_ag_state(BLUETOOTH_AG_STATE_DISCONNECTED);
+
+       DBG("__bluetooth_ag_state_event_handler -\n");
+}
+
+static void __bluetooth_ag_handle_connect(const char *str_address)
+{
+       int ret = FALSE;
+       int bt_device_state = 0;
+
+       DBG("__bluetooth_ag_handle_connect +\n");
+
+       ret = vconf_get_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                                       &bt_device_state);
+       if (ret != 0) {
+               DBG("No value for [%s]\n",
+                               BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Read bt_device_state is  [%d]\n",
+                               bt_device_state);
+       }
+
+       bt_device_state |= BLUETOOTH_STATE_HEADSET_CONNECTED;
+       DBG("bt_device_state = [%d]\n", bt_device_state);
+
+       ret = vconf_set_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                                       bt_device_state);
+       if (ret != 0) {
+               DBG("vconf_set_int failed for [%s]\n",
+                               BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Set bt_device_state is  [%d]\n",
+                               bt_device_state);
+       }
+
+       __bluetooth_ag_set_name(str_address);
+
+       DBG("BT_STATE_HEADSET_CONNECTED\n");
+
+       __bluetooth_audio_internal_event_cb(BLUETOOTH_EVENT_AG_CONNECTED,
+                               BLUETOOTH_AUDIO_ERROR_NONE,
+                               (void *)str_address);
+
+       DBG("__bluetooth_ag_handle_connect -\n");
+       return;
+}
+
+static void __bluetooth_ag_handle_disconnect(const char *str_address)
+{
+       int ret = FALSE;
+       int bt_device_state = 0;
+
+       DBG("__bluetooth_ag_handle_disconnect +\n");
+
+       ret = vconf_get_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                               &bt_device_state);
+       if (ret != 0) {
+               DBG("No value for [%s]\n",
+                               BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Read bt_device_state is  [%d]\n",
+                               bt_device_state);
+       }
+       if (bt_device_state & BLUETOOTH_STATE_HEADSET_CONNECTED)
+               bt_device_state ^= BLUETOOTH_STATE_HEADSET_CONNECTED;
+
+       ret = vconf_set_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                               bt_device_state);
+       if (ret != 0) {
+               DBG("vconf_set_int failed for [%s]\n",
+                               BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Set bt_device_state is  [%d]\n",
+                               bt_device_state);
+       }
+
+       audio_info.ag_state = BLUETOOTH_AG_STATE_DISCONNECTED;
+       audio_info.ag_audio_flag = FALSE;
+       audio_info.ag_spkr_gain = 0;
+
+       DBG("BT_EVENT_AG_DISCONNECTED = 0\n");
+
+       vconf_set_str(BLUETOOTH_SCO_HEADSET_NAME, (char *) "");
+
+       __bluetooth_audio_internal_event_cb(BLUETOOTH_EVENT_AG_DISCONNECTED,
+                                               BLUETOOTH_AUDIO_ERROR_NONE,
+                                               (void *)str_address);
+
+       DBG("__bluetooth_ag_handle_disconnect -\n");
+       return;
+}
+
+static void __bluetooth_ag_connect_cb(DBusGProxy *proxy, DBusGProxyCall *call,
+               gpointer user_data)
+{
+       GError *err = NULL;
+       char *address = (char *)user_data;
+
+       DBG("__bluetooth_ag_connect_cb +\n");
+
+       dbus_g_proxy_end_call(proxy, call, &err, G_TYPE_INVALID);
+
+       if (err != NULL) {
+               DBG("Error occured in Proxy call [%s]\n",
+                               err->message);
+               g_error_free(err);
+
+               __bluetooth_audio_internal_event_cb(
+                                       BLUETOOTH_EVENT_AG_CONNECTED,
+                                       BLUETOOTH_AG_ERROR_CONNECTION_ERROR,
+                                       (void *)address);
+       }
+       g_object_unref(proxy);
+       g_free(user_data);
+
+       current_proxy = NULL;
+       current_call = NULL;
+
+       DBG("__bluetooth_ag_connect_cb -\n");
+       return;
+}
+
+static void __bluetooth_av_connect_cb(DBusGProxy *proxy,
+                               DBusGProxyCall *call,
+                               gpointer user_data)
+{
+       GError *err = NULL;
+       char *address = (char *)user_data;
+       DBG("__bluetooth_av_connect_cb +\n");
+
+       dbus_g_proxy_end_call(proxy, call, &err, G_TYPE_INVALID);
+
+       if (err != NULL) {
+               DBG("Error occured in Proxy call [%s]\n",
+                            err->message);
+               audio_info.av_state = BLUETOOTH_AV_STATE_NONE;
+               g_error_free(err);
+
+               __bluetooth_audio_internal_event_cb(
+                                       BLUETOOTH_EVENT_AV_CONNECTED,
+                                       BLUETOOTH_AV_ERROR_CONNECTION_ERROR,
+                                       (void *)address);
+       }
+       g_object_unref(proxy);
+       g_free(user_data);
+
+       current_proxy = NULL;
+       current_call = NULL;
+
+       DBG("__bluetooth_av_connect_cb -\n");
+       return;
+}
+
+static DBusHandlerResult __bluetooth_ag_event_filter(DBusConnection *conn,
+               DBusMessage *msg, void *data)
+{
+       const char *path = dbus_message_get_path(msg);
+       char address[BT_ADDRESS_STRING_SIZE] = {0,};
+       char *dev_addr = NULL;
+       DBusMessageIter item_iter;
+       DBusMessageIter value_iter;
+       const char *property;
+
+       if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       if (!dbus_message_is_signal(
+                       msg, AUDIO_AG_DBUS_INTERFACE, "PropertyChanged") &&
+                       !dbus_message_is_signal(msg, "org.bluez.Manager",
+                                       "AdapterRemoved")) {
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       if (path == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (strcmp(path, "/") == 0) {
+               if (audio_info.ag_state ==
+                       BLUETOOTH_AG_STATE_CONNECTED) {
+                       char str_deviceAddr[BT_ADDRESS_STRING_SIZE];
+
+                       _bluetooth_internal_addr_type_to_addr_string(
+                                       str_deviceAddr,
+                                       &audio_info.local_address);
+                       __bluetooth_ag_handle_disconnect(
+                                               str_deviceAddr);
+               }
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+       dev_addr = strstr(path, "dev_");
+
+       if (dev_addr != NULL) {
+               dev_addr += 4;
+               g_strlcpy(address, dev_addr, sizeof(address));
+               g_strdelimit(address, "_", ':');
+               DBG("address is %s \n", address);
+               _bluetooth_internal_convert_addr_string_to_addr_type(
+                                       &audio_info.remote_address, address);
+       }
+
+       dbus_message_iter_init(msg, &item_iter);
+
+       if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       dbus_message_iter_get_basic(&item_iter, &property);
+       DBG("Property (%s)\n", property);
+
+       if (property == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (!strcmp(property, "State")) {
+               char *state = NULL;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &state);
+               if (NULL == state) {
+                       DBG("State is null\n");
+                       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+               }
+               DBG("State %s\n", state);
+
+               __bluetooth_ag_state_event_handler(state);
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       if (!strcmp(property, "Connected")) {
+               gboolean connected;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &connected);
+               DBG("Connected %d\n", connected);
+
+               if (connected)
+                       __bluetooth_ag_handle_connect(address);
+               else
+                       __bluetooth_ag_handle_disconnect(address);
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+       if (!strcmp(property, "SpeakerGain")) {
+               guint16 spkr_gain;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &spkr_gain);
+
+               DBG("spk_gain[%d]\n", spkr_gain);
+               __bluetooth_set_ag_remote_speaker_gain(spkr_gain);
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+       if (!strcmp(property, "MicrophoneGain")) {
+               guint16 mic_gain;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &mic_gain);
+
+               DBG("mic_gain[%d]\n", mic_gain);
+               __bluetooth_set_ag_remote_mic_gain(mic_gain);
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void __bluetooth_av_handle_connect(const char *str_address)
+{
+       int ret = FALSE;
+       int bt_device_state = 0;
+
+       DBG("__bluetooth_av_handle_connect +\n");
+
+       audio_info.av_state = BLUETOOTH_AV_STATE_CONNECTED;
+
+       ret = vconf_get_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                               &bt_device_state);
+       if (ret != 0) {
+               DBG("No value for [%s]\n",
+                            BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Read bt_device_state is  [%d]\n",
+                            bt_device_state);
+       }
+
+       bt_device_state |= BLUETOOTH_STATE_A2DP_HEADSET_CONNECTED;
+       DBG("bt_device_state = [%d]\n", bt_device_state);
+
+       ret = vconf_set_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                               bt_device_state);
+       if (ret != 0) {
+               DBG("vconf_set_int failed for [%s]\n",
+                            BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Set bt_device_state is  [%d]\n",
+                            bt_device_state);
+       }
+
+       __bluetooth_audio_internal_event_cb(BLUETOOTH_EVENT_AV_CONNECTED,
+                       BLUETOOTH_AUDIO_ERROR_NONE, (void *)str_address);
+
+       DBG("__bluetooth_av_handle_connect -\n");
+       return;
+
+}
+
+static void __bluetooth_av_handle_disconnect(const char *str_address)
+{
+       int ret = FALSE;
+       int bt_device_state = 0;
+
+       DBG("__bluetooth_av_handle_disconnect +\n");
+
+       audio_info.av_state = BLUETOOTH_AV_STATE_DISCONNECTED;
+
+       ret = vconf_get_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                               &bt_device_state);
+       if (ret != 0) {
+               DBG("No value for [%s]\n",
+                            BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Read bt_device_state is  [%d]\n",
+                            bt_device_state);
+       }
+       if (bt_device_state & BLUETOOTH_STATE_A2DP_HEADSET_CONNECTED)
+               bt_device_state ^= BLUETOOTH_STATE_A2DP_HEADSET_CONNECTED;
+
+       ret = vconf_set_int(BLUETOOTH_PHONE_STATUS_HEADSET_STATE,
+                                       bt_device_state);
+       if (ret != 0) {
+               DBG("vconf_set_int failed for [%s]\n",
+                            BLUETOOTH_PHONE_STATUS_HEADSET_STATE);
+       } else {
+               DBG("Set bt_device_state is  [%d]\n",
+                            bt_device_state);
+       }
+
+       __bluetooth_audio_internal_event_cb(
+                       BLUETOOTH_EVENT_AV_DISCONNECTED,
+                       BLUETOOTH_AUDIO_ERROR_NONE, (void *)str_address);
+
+       DBG("__bluetooth_av_handle_disconnect -\n");
+       return;
+}
+
+static void __bluetooth_av_handle_play(const char *address)
+{
+       DBG("A2DP playing [%s]\n", address);
+}
+
+static void __bluetooth_av_handle_stop(const char *address)
+{
+
+       DBG("A2DP stopped [%s]\n", address);
+}
+
+static void __bluetooth_av_state_event_handler(const char *audio_sink_state)
+{
+       DBG("Audio Sink State is %s\n", audio_sink_state);
+}
+
+static DBusHandlerResult __bluetooth_audio_sink_event_filter(
+                                               DBusConnection *conn,
+                                               DBusMessage *msg,
+                                               void *data)
+{
+       const char *path = dbus_message_get_path(msg);
+       char address[BT_ADDRESS_STRING_SIZE] = {0,};
+       char *dev_addr = NULL;
+       DBusMessageIter item_iter, value_iter;
+       const char *property;
+       char *state;
+
+       if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       if (!dbus_message_is_signal
+           (msg, AUDIO_SINK_DBUS_INTERFACE, "PropertyChanged") &&
+               !dbus_message_is_signal(msg, "org.bluez.Manager",
+                                      "AdapterRemoved")) {
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       if (path == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (strcmp(path, "/") == 0) {
+               if (audio_info.av_state ==
+                   BLUETOOTH_AV_STATE_CONNECTED) {
+                       char str_deviceAddr
+                           [BT_ADDRESS_STRING_SIZE];
+
+                       _bluetooth_internal_addr_type_to_addr_string(
+                                       str_deviceAddr,
+                                       &audio_info.local_address);
+
+                       __bluetooth_av_handle_disconnect(
+                               str_deviceAddr);
+               }
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+       dev_addr = strstr(path, "dev_");
+
+       if (dev_addr != NULL) {
+               dev_addr += 4;
+               g_strlcpy(address, dev_addr, sizeof(address));
+               g_strdelimit(address, "_", ':');
+               DBG("address is %s \n", address);
+               _bluetooth_internal_convert_addr_string_to_addr_type(
+                                       &audio_info.remote_address, address);
+       }
+
+       dbus_message_iter_init(msg, &item_iter);
+
+       if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
+               DBG("This is bad format dbus\n");
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       dbus_message_iter_get_basic(&item_iter, &property);
+       DBG("Property (%s)\n", property);
+
+       if (property == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (!strcmp(property, "State")) {
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &state);
+
+               __bluetooth_av_state_event_handler(state);
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+
+       if (!strcmp(property, "Connected")) {
+               gboolean audio_sink_connected;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &audio_sink_connected);
+
+               if (audio_sink_connected)
+                       __bluetooth_av_handle_connect(address);
+               else
+                       __bluetooth_av_handle_disconnect(address);
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+
+       if (!strcmp(property, "Playing")) {
+               gboolean audio_sink_playing;
+               dbus_message_iter_next(&item_iter);
+               dbus_message_iter_recurse(&item_iter, &value_iter);
+               dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
+
+               if (audio_sink_playing)
+                       __bluetooth_av_handle_play(address);
+               else
+                       __bluetooth_av_handle_stop(address);
+
+               return DBUS_HANDLER_RESULT_HANDLED;
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+BT_EXPORT_API int bluetooth_audio_init(bt_audio_func_ptr cb, void  *user_data)
+{
+       DBusError dbus_error;
+       DBG("bluetooth_audio_init +\n");
+
+       if (NULL == cb)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       audio_info.audio_cb = cb;
+       audio_info.user_data = user_data;
+
+       if (__bluetooth_audio_proxy_init()) {
+               DBG("__bluetooth_audio_proxy_init failed\n");
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       dbus_error_init(&dbus_error);
+
+       dbus_connection_add_filter(audio_connection,
+                               __bluetooth_ag_event_filter,
+                               NULL, NULL);
+
+       dbus_connection_add_filter(audio_connection,
+                               __bluetooth_audio_sink_event_filter,
+                               NULL, NULL);
+
+       dbus_bus_add_match(audio_connection,
+                       "type='signal',interface='" AUDIO_AG_DBUS_INTERFACE
+                       "',member='PropertyChanged'", &dbus_error);
+
+       if (dbus_error_is_set(&dbus_error)) {
+               DBG("Fail to add dbus filter signal\n");
+               dbus_error_free(&dbus_error);
+               __bluetooth_audio_proxy_deinit();
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       dbus_bus_add_match(audio_connection,
+                          "type='signal',interface='"
+                          AUDIO_SINK_DBUS_INTERFACE
+                          "',member='PropertyChanged'", &dbus_error);
+
+       if (dbus_error_is_set(&dbus_error)) {
+               DBG("Fail to add dbus filter signal\n");
+               dbus_error_free(&dbus_error);
+               __bluetooth_audio_proxy_deinit();
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       DBG("bluetooth_audio_init -\n");
+       return BLUETOOTH_AUDIO_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_audio_deinit(void)
+{
+       DBG("bluetooth_audio_deinit +\n");
+
+       audio_info.audio_cb = NULL;
+
+       if (audio_connection) {
+               dbus_connection_remove_filter(audio_connection,
+                               __bluetooth_ag_event_filter, NULL);
+
+               dbus_connection_remove_filter(audio_connection,
+                                     __bluetooth_audio_sink_event_filter,
+                                     NULL);
+       }
+
+       if (NULL != audio_dbus_info.audio_obj_path) {
+               g_free(audio_dbus_info.audio_obj_path);
+               audio_dbus_info.audio_obj_path = NULL;
+       }
+
+       __bluetooth_audio_proxy_deinit();
+
+       DBG("bluetooth_audio_deinit -\n");
+       return BLUETOOTH_AUDIO_ERROR_NONE;
+}
+
+static int __bluetooth_audio_connect(int type, bluetooth_device_address_t *device_address, void *cb_func)
+{
+       const char *device_path = NULL;
+       char *interface;
+       char *address;
+       DBusGProxy *adapter_proxy;
+       DBusGProxy *profile_proxy;
+
+       DBG("+");
+
+       if (device_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       if (audio_dbus_info.audio_conn == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+       switch (type) {
+       case BT_AUDIO_HSP:
+               interface = AUDIO_AG_DBUS_INTERFACE;
+               break;
+       case BT_AUDIO_A2DP:
+               interface = AUDIO_SINK_DBUS_INTERFACE;
+               break;
+       case BT_AUDIO_ALL:
+               interface = AUDIO_DBUS_INTERFACE;
+               break;
+       default:
+               ERR("Unknown role");
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       adapter_proxy = __bluetooth_get_adapter_proxy();
+       if (adapter_proxy == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+
+       address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+
+       _bluetooth_internal_addr_type_to_addr_string(address, device_address);
+
+       dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
+                         G_TYPE_STRING, address, G_TYPE_INVALID,
+                         DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
+
+       g_object_unref(adapter_proxy);
+
+       if (device_path == NULL) {
+               DBG("No paired device");
+               g_free(address);
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       profile_proxy = dbus_g_proxy_new_for_name(audio_dbus_info.audio_conn,
+                                       AUDIO_DBUS_SERVICE,
+                                     device_path, interface);
+
+       if (profile_proxy == NULL) {
+               g_free(address);
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       current_proxy = NULL;
+
+       current_call = dbus_g_proxy_begin_call(profile_proxy, "Connect",
+                       (DBusGProxyCallNotify)cb_func,
+                       address, NULL,
+                       G_TYPE_INVALID);
+
+       if (current_call == NULL) {
+               DBG("Audio connect Dbus Call Error");
+               g_object_unref(profile_proxy);
+               g_free(address);
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       current_proxy = profile_proxy;
+
+       DBG("-\n");
+
+       return BLUETOOTH_AUDIO_ERROR_NONE;
+}
+
+
+static int __bluetooth_audio_disconnect(int type, bluetooth_device_address_t *device_address)
+{
+       const char *device_path = NULL;
+       char *interface;
+       char *address;
+       DBusGProxy *adapter_proxy;
+       DBusGProxy *profile_proxy;
+
+       DBG("+");
+
+       if (device_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       if (audio_dbus_info.audio_conn == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+       switch (type) {
+       case BT_AUDIO_HSP:
+               interface = AUDIO_AG_DBUS_INTERFACE;
+               break;
+       case BT_AUDIO_A2DP:
+               interface = AUDIO_SINK_DBUS_INTERFACE;
+               break;
+       case BT_AUDIO_ALL:
+               interface = AUDIO_DBUS_INTERFACE;
+               break;
+       default:
+               ERR("Unknown role");
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       adapter_proxy = __bluetooth_get_adapter_proxy();
+       if (adapter_proxy == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+
+       address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+
+       _bluetooth_internal_addr_type_to_addr_string(address, device_address);
+
+       dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
+                         G_TYPE_STRING, address, G_TYPE_INVALID,
+                         DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
+
+       g_object_unref(adapter_proxy);
+       g_free(address);
+
+       if (device_path == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+       profile_proxy = dbus_g_proxy_new_for_name(audio_dbus_info.audio_conn,
+                                       AUDIO_DBUS_SERVICE,
+                                     device_path, interface);
+
+       if (profile_proxy == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+       if (!dbus_g_proxy_call(profile_proxy, "Disconnect",
+                               NULL, G_TYPE_INVALID,
+                               G_TYPE_INVALID)) {
+               DBG("Audio disconnect Dbus Call Error");
+               g_object_unref(profile_proxy);
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+       }
+
+       g_object_unref(profile_proxy);
+
+       DBG("-\n");
+
+       return BLUETOOTH_AUDIO_ERROR_NONE;
+}
+
+
+BT_EXPORT_API int bluetooth_audio_connect(
+                               bluetooth_device_address_t *remote_address)
+{
+       DBG("bluetooth_ag_connect +\n");
+
+       if (remote_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       return __bluetooth_audio_connect(BT_AUDIO_ALL,
+                                       remote_address,
+                                       __bluetooth_ag_connect_cb);
+}
+
+BT_EXPORT_API int bluetooth_audio_disconnect(
+                               bluetooth_device_address_t *remote_address)
+{
+       DBG("bluetooth_ag_disconnect +\n");
+
+       if (remote_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       return __bluetooth_audio_disconnect(BT_AUDIO_ALL,
+                                       remote_address);
+}
+
+BT_EXPORT_API int bluetooth_ag_connect(
+                               bluetooth_device_address_t *remote_address)
+{
+       DBG("bluetooth_ag_connect +\n");
+
+       if (remote_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       return __bluetooth_audio_connect(BT_AUDIO_HSP,
+                                       remote_address,
+                                       __bluetooth_ag_connect_cb);
+}
+
+BT_EXPORT_API int bluetooth_ag_disconnect(
+                               bluetooth_device_address_t *remote_address)
+{
+       DBG("bluetooth_ag_disconnect +\n");
+
+       if (remote_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       return __bluetooth_audio_disconnect(BT_AUDIO_HSP,
+                                       remote_address);
+}
+
+BT_EXPORT_API int bluetooth_ag_set_speaker_gain(unsigned short speaker_gain)
+{
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       DBusMessageIter value;
+       char *audio_path;
+       char *spkr_gain_str = "SpeakerGain";
+       int ret = BLUETOOTH_AUDIO_ERROR_NONE;
+
+       DBG("bluetooth_ag_set_speaker_gain +\n");
+       DBG(" speaker_gain= [%d]\n", speaker_gain);
+
+       audio_path = __bluetooth_get_connected_audio_path();
+
+       if (audio_path == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+       DBG("audio_path: %s", audio_path);
+
+       msg = dbus_message_new_method_call(AUDIO_DBUS_SERVICE,
+                       audio_path, AUDIO_AG_DBUS_INTERFACE,
+                       "SetProperty");
+       if (NULL != msg) {
+               char sig[2] = {DBUS_TYPE_UINT16, '\0'};
+
+               dbus_message_iter_init_append(msg, &iter);
+               dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
+                               &spkr_gain_str);
+
+               dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig,
+                               &value);
+               dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
+                               &speaker_gain);
+
+               dbus_message_iter_close_container(&iter, &value);
+
+               if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
+                       dbus_message_set_no_reply(msg, TRUE);
+
+               if (!dbus_connection_send(audio_connection, msg, NULL)) {
+                       DBG(" bluetooth_ag_set_speaker_gain - \
+                               dbus_connection_send failed\n");
+                       ret = BLUETOOTH_AUDIO_ERROR_INTERNAL;
+               }
+               dbus_message_unref(msg);
+       } else
+               ret = BLUETOOTH_AUDIO_ERROR_INTERNAL;
+
+       DBG("bluetooth_ag_set_speaker_gain -\n");
+       return ret;
+}
+
+BT_EXPORT_API int bluetooth_ag_get_headset_volume(unsigned int *speaker_gain)
+{
+       DBG("bluetooth_ag_get_headset_volume +\n");
+
+       if (NULL == speaker_gain)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       DBG(" Current Speaker gain audio_info.ag_spkr_gain= [%d]\n",
+                       audio_info.ag_spkr_gain);
+
+       *speaker_gain = audio_info.ag_spkr_gain;
+
+       DBG(" *speaker_gain = [%d]\n", *speaker_gain);
+       DBG("bluetooth_ag_get_headset_volume -\n");
+
+       return BLUETOOTH_AUDIO_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_av_connect(
+                               bluetooth_device_address_t *remote_address)
+{
+       DBG("bluetooth_av_connect +\n");
+
+       if (remote_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       return __bluetooth_audio_connect(BT_AUDIO_A2DP,
+                                       remote_address,
+                                       __bluetooth_av_connect_cb);
+}
+
+BT_EXPORT_API int bluetooth_av_disconnect(
+                               bluetooth_device_address_t *remote_address)
+{
+       DBG("bluetooth_av_disconnect +\n");
+
+       if (remote_address == NULL)
+               return BLUETOOTH_AUDIO_ERROR_INVALID_PARAM;
+
+       return __bluetooth_audio_disconnect(BT_AUDIO_A2DP,
+                                       remote_address);
+}
diff --git a/lib/bluetooth-audio-api.h b/lib/bluetooth-audio-api.h
new file mode 100644 (file)
index 0000000..547ef5c
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * bluetooth-audio-api
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             GirishAshok Joshi <girish.joshi@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 _BLUETOOTH_AUDIO_API_H_
+#define _BLUETOOTH_AUDIO_API_H_
+
+#include <stdint.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dlog.h>
+
+#include "bluetooth-api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+#ifndef BT_EXPORT_API
+#define BT_EXPORT_API __attribute__((visibility("default")))
+#endif
+
+#define BLUETOOTH_AUDIO_ERROR_BASE ((int)0)
+#define BLUETOOTH_AUDIO_ERROR_NONE ((int)0)
+#define BLUETOOTH_AUDIO_ERROR_INTERNAL \
+                               ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x01)
+#define BLUETOOTH_AUDIO_ERROR_INVALID_PARAM \
+                               ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x02)
+#define BLUETOOTH_AG_ERROR_CONNECTION_ERROR \
+                               ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x03)
+#define BLUETOOTH_AV_ERROR_CONNECTION_ERROR \
+                               ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x04)
+
+typedef struct {
+       int event;
+       int result;
+       void *param_data;
+} bt_audio_event_param_t;
+
+typedef enum {
+       BLUETOOTH_AG_STATE_NONE,
+       BLUETOOTH_AG_STATE_CONNECTING,
+       BLUETOOTH_AG_STATE_CONNECTED,
+       BLUETOOTH_AG_STATE_DISCONNECTED,
+       BLUETOOTH_AG_STATE_PLAYING,
+} bt_ag_conn_status_t;
+
+typedef enum {
+       BLUETOOTH_AV_STATE_NONE,
+       BLUETOOTH_AV_STATE_CONNECTING,
+       BLUETOOTH_AV_STATE_CONNECTED,
+       BLUETOOTH_AV_STATE_DISCONNECTED,
+} bt_av_conn_status_t;
+
+typedef void (*bt_audio_func_ptr) (int, bt_audio_event_param_t *, void *);
+
+typedef struct {
+       bt_ag_conn_status_t ag_state;
+       bt_av_conn_status_t av_state;
+       unsigned int ag_audio_flag;
+       unsigned int ag_spkr_gain;
+       bluetooth_device_address_t local_address;
+       bluetooth_device_address_t remote_address;
+       bt_audio_func_ptr audio_cb;
+       void *user_data;
+} bt_audio_info_t;
+
+typedef enum {
+                BLUETOOTH_STATE_NONE = 0x0000,
+                BLUETOOTH_STATE_HEADSET_CONNECTED = 0x0004,
+                BLUETOOTH_STATE_A2DP_HEADSET_CONNECTED = 0x0010,
+} bluetooth_device_state_t;
+
+/**
+ * @brief      The function bluetooth_audio_init called to initializes the Audio
+ *     service to bluetoothD and Global data related to audio.
+ * @param[in]  cb      Callback function
+ * @param[in]  user_data       Data sent by application, which will be
+ *                             returned in event handler.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_init(bt_audio_func_ptr cb, void  *user_data);
+
+/**
+ * @brief      The function bluetooth_audio_deinit is called to free the Audio
+ *     related Global data.
+ *
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_deinit(void);
+
+
+/**
+ * @brief      The function bluetooth_audio_connect is called to establish an
+ *     AG connection with  the specified device.
+ *
+ * @param[in]  remote_address  Bluetooth device address.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_connect(bluetooth_device_address_t *remote_address);
+
+/**
+ * @brief      The function bluetooth_audio_disconnect is called to disconnect
+ *     an existing AG connection with the specified device.
+ *
+ * @param[in]  remote_address  Bluetooth device address.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_disconnect(bluetooth_device_address_t *remote_address);
+
+/**
+ * @brief      The function bluetooth_ag_connect is called to establish an AG
+ *     connection with  the specified device.
+ *
+ * @param[in]  remote_address  Bluetooth device address.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_ag_connect(bluetooth_device_address_t *remote_address);
+
+/**
+ * @brief      The function bluetooth_ag_disconnect is called to disconnect an
+ *     existing AG connection with the specified device.
+ *
+ * @param[in]  remote_address  Bluetooth device address.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_ag_disconnect(bluetooth_device_address_t *remote_address);
+
+/**
+ * @brief      The function bluetooth_av_connect is called to establish an AV
+ *     connection with  the specified device.
+ *
+ * @param[in]  remote_address  Bluetooth device address.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_av_connect(bluetooth_device_address_t *remote_address);
+
+/**
+ * @brief      The function bluetooth_av_disconnect is called to disconnect an
+ *     existing AV connection with the specified device.
+ *
+ * @param[in]  remote_address  Bluetooth device address.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_av_disconnect(bluetooth_device_address_t *remote_address);
+
+/**
+ * @brief      The function bluetooth_ag_get_headset_volume is called to get
+ *     the changed Volume on AG.
+ *
+ * @param[in]  speaker_gain    Speaker gain/loss.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_ag_get_headset_volume(unsigned int *speaker_gain);
+
+/**
+ * @brief      The function bluetooth_ag_set_speaker_gain is called to indicate
+ *     that the Volume on AG is changed.
+ *
+ * @param[in]  speaker_gain    Speaker gain/loss.
+ * @return     int     Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_ag_set_speaker_gain(unsigned short speaker_gain);
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+#endif/*_BLUETOOTH_AUDIO_API_H_*/
diff --git a/lib/bluetooth-control-api.c b/lib/bluetooth-control-api.c
new file mode 100644 (file)
index 0000000..23ea7c7
--- /dev/null
@@ -0,0 +1,715 @@
+/*
+ *   bluetooth-media-control
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             Girishashok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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 <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <glib.h>
+#include <string.h>
+
+#include "bluetooth-control-api.h"
+
+#define BLUEZ_SERVICE  "org.bluez"
+#define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager"
+
+#define BLUEZ_MEDIA_INTERFACE  "org.bluez.Media"
+#define BLUEZ_MEDIA_PLAYER_OBJECT_PATH "/Musicplayer"
+
+
+#define BLUEZ_MEDIA_PLAYER_INTERFACE   "org.bluez.MediaPlayer"
+
+#ifndef BT_EXPORT_API
+#define BT_EXPORT_API __attribute__((visibility("default")))
+#endif
+
+#define BT_CONTROL "BT_CONTROL"
+#define DBG(fmt, args...) SLOG(LOG_DEBUG, BT_CONTROL, \
+                               "%s():%d "fmt, __func__, __LINE__, ##args)
+#define ERR(fmt, args...) SLOG(LOG_ERROR, BT_CONTROL, \
+                               "%s():%d "fmt, __func__, __LINE__, ##args)
+
+typedef struct {
+       DBusGConnection *avrcp_conn;
+       char avrcp_obj_path[MEDIA_OBJECT_PATH_LENGTH];
+} avrcp_dbus_info_t;
+
+static avrcp_dbus_info_t g_avrcp_dbus_info;
+static DBusConnection *g_avrcp_connection = NULL;
+
+struct player_settinngs_t {
+       int key;
+       const char *property;
+};
+
+static struct player_settinngs_t equilizer_settings[] = {
+       { EQUILIZER_OFF, "off" },
+       { EQUILIZER_ON, "on" },
+       { EQUILIZER_INVALID, "" }
+};
+
+static struct player_settinngs_t repeat_settings[] = {
+       { REPEAT_MODE_OFF, "off" },
+       { REPEAT_SINGLE_TRACK, "singletrack" },
+       { REPEAT_ALL_TRACK, "alltracks" },
+       { REPEAT_GROUP, "group" },
+       { REPEAT_INVALID, "" }
+};
+
+static struct player_settinngs_t shuffle_settings[] = {
+       { SHUFFLE_MODE_OFF, "off" },
+       { SHUFFLE_ALL_TRACK, "alltracks" },
+       { SHUFFLE_GROUP, "group" },
+       { SHUFFLE_INVALID, "" }
+};
+
+static struct player_settinngs_t scan_settings[] = {
+       { SCAN_MODE_OFF, "off" },
+       { SCAN_ALL_TRACK, "alltracks" },
+       { SCAN_GROUP, "group" },
+       { SCAN_INVALID, "" }
+};
+
+static struct player_settinngs_t player_status[] = {
+       { STATUS_PLAYING, "playing" },
+       { STATUS_STOPPED, "stopped" },
+       { STATUS_PAUSED, "paused" },
+       { STATUS_FORWARD_SEEK, "forward-seek" },
+       { STATUS_REVERSE_SEEK, "reverse-seek" },
+       { STATUS_ERROR, "error" },
+       { STATUS_INVALID, "" }
+};
+
+static int __bluetooth_media_get_avrcp_adapter_path(
+               DBusGConnection *gconn, char *path)
+{
+       GError *err = NULL;
+       DBusGProxy *manager_proxy = NULL;
+       char *adapter_path = NULL;
+       int ret = 0;
+
+       DBG("__bluetooth_media_get_avrcp_adapter_path +\n");
+
+       manager_proxy = dbus_g_proxy_new_for_name(gconn, BLUEZ_SERVICE, "/",
+                                       BLUEZ_MANAGER_INTERFACE);
+
+       if (manager_proxy == NULL) {
+               DBG("Could not create a dbus proxy\n");
+               return BLUETOOTH_CONTROL_ERROR;
+       }
+
+       if (!dbus_g_proxy_call(manager_proxy, "DefaultAdapter", &err,
+                              G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
+                              &adapter_path, G_TYPE_INVALID)) {
+               DBG("Getting DefaultAdapter failed: [%s]\n", err->message);
+               g_error_free(err);
+               ret = BLUETOOTH_CONTROL_ERROR;
+               goto done;
+       }
+
+       if (strlen(adapter_path) >= MEDIA_OBJECT_PATH_LENGTH) {
+               DBG("Path too long.\n");
+               ret = BLUETOOTH_CONTROL_ERROR;
+               goto done;
+       }
+       DBG("path = %s\n", adapter_path);
+       g_strlcpy(path, adapter_path, MEDIA_OBJECT_PATH_LENGTH);
+
+done:
+       g_object_unref(manager_proxy);
+
+       DBG("Adapter [%s]\n", path);
+
+       DBG("__bluetooth_media_get_avrcp_adapter_path -\n");
+       return ret;
+}
+
+static void __bluetooth_media_append_variant(DBusMessageIter *iter,
+                       int type, void *val)
+{
+       DBusMessageIter value_iter;
+       const char *contained_signature;
+
+       switch (type) {
+       case DBUS_TYPE_BYTE:
+               contained_signature = DBUS_TYPE_BYTE_AS_STRING;
+               break;
+       case DBUS_TYPE_STRING:
+               contained_signature = DBUS_TYPE_STRING_AS_STRING;
+               break;
+       case DBUS_TYPE_BOOLEAN:
+               contained_signature = DBUS_TYPE_BOOLEAN_AS_STRING;
+               break;
+       case DBUS_TYPE_INT16:
+               contained_signature = DBUS_TYPE_INT16_AS_STRING;
+               break;
+       case DBUS_TYPE_UINT16:
+               contained_signature = DBUS_TYPE_UINT16_AS_STRING;
+               break;
+       case DBUS_TYPE_INT32:
+               contained_signature = DBUS_TYPE_INT32_AS_STRING;
+               break;
+       case DBUS_TYPE_UINT32:
+               contained_signature = DBUS_TYPE_UINT32_AS_STRING;
+               break;
+       case DBUS_TYPE_OBJECT_PATH:
+               contained_signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
+               break;
+       default:
+               contained_signature = DBUS_TYPE_VARIANT_AS_STRING;
+               break;
+       }
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+                       contained_signature, &value_iter);
+       dbus_message_iter_append_basic(&value_iter, type, val);
+       dbus_message_iter_close_container(iter, &value_iter);
+}
+
+static void __bluetooth_media_append_dict_entry(DBusMessageIter *dict,
+                       const char *key, int type, void *property)
+{
+       DBusMessageIter iter;
+
+       if (type == DBUS_TYPE_STRING) {
+               const char *str_ptr = *((const char **)property);
+               if (!str_ptr)
+                       return;
+       }
+
+       dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                               NULL, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
+
+       __bluetooth_media_append_variant(&iter, type, property);
+
+       dbus_message_iter_close_container(dict, &iter);
+}
+
+static dbus_bool_t __bluetooth_media_emit_property_changed(
+                               DBusConnection *conn, const char *path,
+                               const char *interface, const char *name,
+                               int type, void *value)
+{
+       DBusMessage *message = NULL;
+       DBusMessageIter iter;
+       dbus_bool_t result;
+
+       message = dbus_message_new_signal(path, interface, "PropertyChanged");
+
+       if (!message)
+               return FALSE;
+
+       dbus_message_iter_init_append(message, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+       __bluetooth_media_append_variant(&iter, type, value);
+
+       result = dbus_connection_send(conn, message, NULL);
+       dbus_message_unref(message);
+
+       return result;
+}
+
+static void __bluetooth_handle_trackchanged(
+                                       DBusMessage *msg)
+{
+       const char *path = dbus_message_get_path(msg);
+       media_metadata_attributes_t metadata = {0,};
+       DBusMessage *signal = NULL;
+       DBusMessageIter iter;
+       DBusMessageIter metadata_dict;
+
+       DBG("Path = %s\n", path);
+
+       if (!dbus_message_get_args(msg, NULL,
+               DBUS_TYPE_STRING, &metadata.title,
+               DBUS_TYPE_STRING, &metadata.artist,
+               DBUS_TYPE_STRING, &metadata.album,
+               DBUS_TYPE_STRING, &metadata.genre,
+               DBUS_TYPE_UINT32, &metadata.total_tracks,
+               DBUS_TYPE_UINT32, &metadata.number,
+               DBUS_TYPE_UINT32, &metadata.duration,
+               DBUS_TYPE_INVALID)) {
+               DBG("Unexpected parameters in signal");
+               return;
+       }
+
+       signal = dbus_message_new_signal(BLUEZ_MEDIA_PLAYER_OBJECT_PATH,
+                       BLUEZ_MEDIA_PLAYER_INTERFACE, "TrackChanged");
+       if (!signal) {
+               DBG("Unable to allocate TrackChanged signal\n");
+               return;
+       }
+
+       dbus_message_iter_init_append(signal, &iter);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata_dict);
+
+       if (NULL != metadata.title) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Title",
+                       DBUS_TYPE_STRING, &metadata.title);
+       }
+
+       if (NULL != metadata.artist) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Artist",
+                       DBUS_TYPE_STRING, &metadata.artist);
+       }
+
+       if (NULL != metadata.album) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Album",
+                       DBUS_TYPE_STRING, &metadata.album);
+       }
+
+       if (NULL != metadata.genre) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Genre",
+                       DBUS_TYPE_STRING, &metadata.genre);
+       }
+
+       if (0 != metadata.total_tracks)
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "NumberOfTracks",
+                       DBUS_TYPE_UINT32, &metadata.total_tracks);
+
+       if (0 != metadata.number)
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Number",
+                       DBUS_TYPE_UINT32, &metadata.number);
+
+       if (0 != metadata.duration)
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Duration",
+                       DBUS_TYPE_UINT32, &metadata.duration);
+
+       dbus_message_iter_close_container(&iter, &metadata_dict);
+
+       if (!dbus_connection_send(g_avrcp_connection, signal, NULL))
+               DBG("Unable to send TrackChanged signal\n");
+       dbus_message_unref(signal);
+
+}
+
+static void __bluetooth_handle_property_changed(
+                                       DBusMessage *msg)
+{
+       const char *path = dbus_message_get_path(msg);
+       unsigned int type;
+       unsigned int value;
+       DBG("Path = %s\n", path);
+
+       if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_UINT32, &type,
+                               DBUS_TYPE_UINT32, &value,
+                               DBUS_TYPE_INVALID)) {
+               DBG("Unexpected parameters in signal");
+               return;
+       }
+
+       DBG("type = [%d] and value = [%d]\n", type, value);
+
+       switch (type) {
+       case EQUILIZER:
+               if (!__bluetooth_media_emit_property_changed(
+                       g_avrcp_connection,
+                       BLUEZ_MEDIA_PLAYER_OBJECT_PATH,
+                       BLUEZ_MEDIA_PLAYER_INTERFACE,
+                       "Equalizer",
+                       DBUS_TYPE_STRING,
+                       &equilizer_settings[value].property)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+               break;
+       case REPEAT:
+               if (!__bluetooth_media_emit_property_changed(
+                       g_avrcp_connection,
+                       BLUEZ_MEDIA_PLAYER_OBJECT_PATH,
+                       BLUEZ_MEDIA_PLAYER_INTERFACE,
+                       "Repeat",
+                       DBUS_TYPE_STRING,
+                       &repeat_settings[value].property)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+               break;
+       case SHUFFLE:
+               if (!__bluetooth_media_emit_property_changed(
+                       g_avrcp_connection,
+                       BLUEZ_MEDIA_PLAYER_OBJECT_PATH,
+                       BLUEZ_MEDIA_PLAYER_INTERFACE,
+                       "Shuffle",
+                       DBUS_TYPE_STRING,
+                       &shuffle_settings[value].property)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+               break;
+       case SCAN:
+               if (!__bluetooth_media_emit_property_changed(
+                       g_avrcp_connection,
+                       BLUEZ_MEDIA_PLAYER_OBJECT_PATH,
+                       BLUEZ_MEDIA_PLAYER_INTERFACE,
+                       "Scan",
+                       DBUS_TYPE_STRING,
+                       &scan_settings[value].property)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+               break;
+       case STATUS:
+               if (!__bluetooth_media_emit_property_changed(
+                       g_avrcp_connection,
+                       BLUEZ_MEDIA_PLAYER_OBJECT_PATH,
+                       BLUEZ_MEDIA_PLAYER_INTERFACE,
+                       "Status",
+                       DBUS_TYPE_STRING,
+                       &player_status[value].property)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+               break;
+       case POSITION:
+               if (!__bluetooth_media_emit_property_changed(
+                       g_avrcp_connection,
+                       BLUEZ_MEDIA_PLAYER_OBJECT_PATH,
+                       BLUEZ_MEDIA_PLAYER_INTERFACE,
+                       "Position",
+                       DBUS_TYPE_UINT32,
+                       &value)) {
+                       DBG("Error sending the PropertyChanged signal \n");
+               }
+               break;
+       default:
+               DBG("Invalid Type\n");
+               break;
+       }
+}
+
+static DBusHandlerResult __bluetooth_media_event_filter(
+                                       DBusConnection *sys_conn,
+                                       DBusMessage *msg, void *data)
+{
+       if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (dbus_message_is_signal(msg, BT_MEDIA_PLAYER_DBUS_INTERFACE,
+                                       "TrackChanged")) {
+               __bluetooth_handle_trackchanged(msg);
+       } else if (dbus_message_is_signal(msg, BT_MEDIA_PLAYER_DBUS_INTERFACE,
+                                       "PropertyChanged")) {
+               __bluetooth_handle_property_changed(msg);
+       }
+
+       return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+BT_EXPORT_API int bluetooth_media_init(void)
+{
+       GError *err = NULL;
+       char default_obj_path[MEDIA_OBJECT_PATH_LENGTH] = {0,};
+       DBusError dbus_error;
+
+       DBG("bluetooth_media_init +\n");
+
+       g_avrcp_dbus_info.avrcp_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
+
+       if (!g_avrcp_dbus_info.avrcp_conn) {
+               DBG("Can not get DBUS Gconnection [%s]\n", err->message);
+               g_error_free(err);
+               return BLUETOOTH_CONTROL_ERROR;
+       }
+
+       DBG("bluetooth_media_init\n");
+
+       g_avrcp_connection = dbus_g_connection_get_connection(
+                                               g_avrcp_dbus_info.avrcp_conn);
+
+       dbus_error_init(&dbus_error);
+
+       dbus_connection_add_filter(g_avrcp_connection,
+                               __bluetooth_media_event_filter, NULL, NULL);
+
+       dbus_bus_add_match(g_avrcp_connection,
+                       "type='signal',interface="  \
+                       BT_MEDIA_PLAYER_DBUS_INTERFACE,
+                       &dbus_error);
+
+       if (dbus_error_is_set(&dbus_error)) {
+               DBG("Fail to add dbus filter signal\n");
+               dbus_error_free(&dbus_error);
+               return BLUETOOTH_CONTROL_ERROR;
+       }
+
+       if (__bluetooth_media_get_avrcp_adapter_path(
+               g_avrcp_dbus_info.avrcp_conn,
+                default_obj_path) < 0) {
+               DBG("Could not get adapter path\n");
+               goto error;
+       }
+
+       DBG("bluetooth_media_init\n");
+
+       if (default_obj_path != NULL)
+               g_strlcpy(g_avrcp_dbus_info.avrcp_obj_path, default_obj_path,
+                       MEDIA_OBJECT_PATH_LENGTH);
+       else
+               goto error;
+
+       DBG("bluetooth_media_init -\n");
+       return BLUETOOTH_CONTROL_SUCCESS;
+
+error:
+       dbus_g_connection_unref(g_avrcp_dbus_info.avrcp_conn);
+       g_avrcp_dbus_info.avrcp_conn = NULL;
+       g_avrcp_connection = NULL;
+       return BLUETOOTH_CONTROL_ERROR;
+}
+
+BT_EXPORT_API int bluetooth_media_register_player(void)
+{
+       DBusMessage *msg = NULL;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       DBusMessageIter property_dict;
+       DBusMessageIter metadata_dict;
+       DBusError err;
+
+
+       media_player_settings_t player_settings = {0,};
+       media_metadata_attributes_t metadata = {0,};
+
+       player_settings.equilizer = EQUILIZER_OFF;
+       player_settings.repeat  = REPEAT_MODE_OFF;
+       player_settings.shuffle = SHUFFLE_MODE_OFF;
+       player_settings.scan = SCAN_MODE_OFF;
+       player_settings.status = STATUS_STOPPED;
+       player_settings.position = 0;
+
+       metadata.title = "\0";
+       metadata.artist = "\0";
+       metadata.album = "\0";
+       metadata.genre = "\0";
+
+       if (strlen(g_avrcp_dbus_info.avrcp_obj_path) <= 0)
+               return BLUETOOTH_CONTROL_ERROR;
+
+       const char *object = g_strdup(BLUEZ_MEDIA_PLAYER_OBJECT_PATH);
+
+       DBG("bluetooth_media_register_player +\n");
+
+       msg = dbus_message_new_method_call(
+                               BLUEZ_SERVICE,
+                               g_avrcp_dbus_info.avrcp_obj_path,
+                               BLUEZ_MEDIA_INTERFACE,
+                               "RegisterPlayer");
+       if (!msg) {
+               DBG("dbus_message_new_method_call failed\n");
+               g_free((void *)object);
+               return BLUETOOTH_CONTROL_ERROR;
+       }
+
+       DBG("object = [%s] \n", object);
+
+       dbus_message_iter_init_append(msg, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &object);
+       g_free((void *)object);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict);
+
+       if (player_settings.equilizer < EQUILIZER_INVALID) {
+               __bluetooth_media_append_dict_entry(&property_dict,
+                       "Equalizer",
+                       DBUS_TYPE_STRING,
+                       &equilizer_settings[
+                               player_settings.equilizer].property);
+       }
+
+       if (player_settings.repeat < REPEAT_INVALID) {
+               __bluetooth_media_append_dict_entry(&property_dict,
+                       "Repeat",
+                       DBUS_TYPE_STRING,
+                       &repeat_settings[player_settings.repeat].property);
+       }
+
+       if (player_settings.shuffle < SHUFFLE_INVALID) {
+               __bluetooth_media_append_dict_entry(&property_dict,
+                       "Shuffle",
+                       DBUS_TYPE_STRING,
+                       &shuffle_settings[player_settings.shuffle].property);
+       }
+
+       if (player_settings.scan < SCAN_INVALID) {
+               __bluetooth_media_append_dict_entry(&property_dict,
+                       "Scan",
+                       DBUS_TYPE_STRING,
+                       &scan_settings[player_settings.scan].property);
+       }
+
+       if (player_settings.status < STATUS_INVALID) {
+               __bluetooth_media_append_dict_entry(&property_dict,
+                       "Status",
+                       DBUS_TYPE_STRING,
+                       &player_status[player_settings.status].property);
+       }
+
+       if (0 != player_settings.position)
+               __bluetooth_media_append_dict_entry(&property_dict,
+                       "Position",
+                       DBUS_TYPE_UINT32, &player_settings.position);
+
+       dbus_message_iter_close_container(&iter, &property_dict);
+
+       dbus_message_iter_init_append(msg, &iter);
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata_dict);
+
+       if (NULL != metadata.title) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Title",
+                       DBUS_TYPE_STRING, &metadata.title);
+       }
+
+       if (NULL != metadata.artist) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Artist",
+                       DBUS_TYPE_STRING, &metadata.artist);
+       }
+
+       if (NULL != metadata.album) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Album",
+                       DBUS_TYPE_STRING, &metadata.album);
+       }
+
+       if (NULL != metadata.genre) {
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Genre",
+                       DBUS_TYPE_STRING, &metadata.genre);
+       }
+
+       if (0 != metadata.total_tracks)
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "NumberOfTracks",
+                       DBUS_TYPE_UINT32, &metadata.total_tracks);
+
+       if (0 != metadata.number)
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Number",
+                       DBUS_TYPE_UINT32, &metadata.number);
+
+       if (0 != metadata.duration)
+               __bluetooth_media_append_dict_entry(&metadata_dict,
+                       "Duration",
+                       DBUS_TYPE_UINT32, &metadata.duration);
+
+       dbus_message_iter_close_container(&iter, &metadata_dict);
+
+       dbus_error_init(&err);
+       reply = dbus_connection_send_with_reply_and_block(g_avrcp_connection,
+                               msg, -1, &err);
+       dbus_message_unref(msg);
+
+       if (!reply) {
+               DBG("Error in registering the Music Player \n");
+
+               if (dbus_error_is_set(&err)) {
+                       DBG("%s", err.message);
+                       dbus_error_free(&err);
+                       return BLUETOOTH_CONTROL_ERROR;
+               }
+       }
+
+       if (reply)
+               dbus_message_unref(reply);
+
+       DBG("bluetooth_media_register_player -\n");
+
+       return BLUETOOTH_CONTROL_SUCCESS;
+}
+
+BT_EXPORT_API int bluetooth_media_unregister_player(void)
+{
+       DBusMessage *msg = NULL;
+       DBusMessage *reply = NULL;
+       DBusError err;
+       const char *object = g_strdup(BLUEZ_MEDIA_PLAYER_OBJECT_PATH);
+
+       DBG("bluetooth_media_unregister_player +\n");
+
+       msg = dbus_message_new_method_call(BLUEZ_SERVICE,
+                                       g_avrcp_dbus_info.avrcp_obj_path,
+                                       BLUEZ_MEDIA_INTERFACE,
+                                       "UnregisterPlayer");
+
+       if (NULL == msg) {
+               g_free((void *)object);
+               return BLUETOOTH_CONTROL_ERROR;
+       }
+
+       dbus_message_append_args(msg,
+                               DBUS_TYPE_OBJECT_PATH, &object,
+                               DBUS_TYPE_INVALID);
+
+       dbus_error_init(&err);
+       reply = dbus_connection_send_with_reply_and_block(g_avrcp_connection,
+                               msg, -1, &err);
+       dbus_message_unref(msg);
+       g_free((void *)object);
+
+       if (!reply) {
+               DBG("Error in unregistering the Music Player \n");
+
+               if (dbus_error_is_set(&err)) {
+                       DBG("%s", err.message);
+                       dbus_error_free(&err);
+                       return BLUETOOTH_CONTROL_ERROR;
+               }
+       } else
+               dbus_message_unref(reply);
+
+       DBG("bluetooth_media_unregister_player -\n");
+       return BLUETOOTH_CONTROL_SUCCESS;
+}
+
+BT_EXPORT_API int bluetooth_media_deinit(void)
+{
+       DBG("bluetooth_media_deinit +\n");
+
+       if (g_avrcp_dbus_info.avrcp_conn) {
+               dbus_g_connection_unref(g_avrcp_dbus_info.avrcp_conn);
+               g_avrcp_dbus_info.avrcp_conn = NULL;
+       }
+
+       DBG("bluetooth_media_deinit -\n");
+       return BLUETOOTH_CONTROL_SUCCESS;
+}
diff --git a/lib/bluetooth-control-api.h b/lib/bluetooth-control-api.h
new file mode 100644 (file)
index 0000000..ef198cd
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ *   bluetooth-media-control
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:    Hocheol Seo <hocheol.seo@samsung.com>
+ *             Girishashok Joshi <girish.joshi@samsung.com>
+ *             Chanyeol Park <chanyeol.park@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 _BLUETOOTH_CONTROL_API_H_
+#define _BLUETOOTH_CONTROL_API_H_
+
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <glib.h>
+#include <dlog.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+#define BT_MEDIA_PLAYER_DBUS_INTERFACE "org.tizen.player"
+#define BT_MEDIA_PLAYER_OBJECT_PATH    "/Tizen/Control"
+
+
+/* defines*/
+#define MEDIA_OBJECT_PATH_LENGTH       50
+
+#define BLUETOOTH_CONTROL_ERROR        -1
+#define BLUETOOTH_CONTROL_SUCCESS      0
+
+typedef enum {
+       EQUILIZER = 0x00,
+       REPEAT,
+       SHUFFLE,
+       SCAN,
+       STATUS,
+       POSITION
+} media_player_property_type;
+
+typedef enum {
+       EQUILIZER_OFF = 0x00,
+       EQUILIZER_ON,
+       EQUILIZER_INVALID,
+} media_player_equilizer_status;
+
+typedef enum {
+       REPEAT_MODE_OFF = 0x00,
+       REPEAT_SINGLE_TRACK,
+       REPEAT_ALL_TRACK,
+       REPEAT_GROUP,
+       REPEAT_INVALID,
+} media_player_repeat_status;
+
+typedef enum {
+       SHUFFLE_MODE_OFF = 0x00,
+       SHUFFLE_ALL_TRACK,
+       SHUFFLE_GROUP,
+       SHUFFLE_INVALID,
+} media_player_shuffle_status;
+
+typedef enum {
+       SCAN_MODE_OFF = 0x00,
+       SCAN_ALL_TRACK,
+       SCAN_GROUP,
+       SCAN_INVALID,
+} media_player_scan_status;
+
+typedef enum {
+       STATUS_PLAYING  = 0x00,
+       STATUS_STOPPED,
+       STATUS_PAUSED,
+       STATUS_FORWARD_SEEK,
+       STATUS_REVERSE_SEEK,
+       STATUS_ERROR,
+       STATUS_INVALID
+} media_player_status;
+
+typedef struct {
+       media_player_equilizer_status equilizer;
+       media_player_repeat_status  repeat;
+       media_player_shuffle_status  shuffle;
+       media_player_scan_status scan;
+       media_player_status status;
+       unsigned int position;
+} media_player_settings_t;
+
+typedef struct {
+       const char *title;
+       const char *artist;
+       const char *album;
+       const char *genre;
+       unsigned int total_tracks;
+       unsigned int number;
+       unsigned int duration;
+} media_metadata_attributes_t;
+
+/**
+ * @fn int bluetooth_media_init(void)
+ * @brief Initializes the Media interface to media service
+ *
+ * This function is a asynchronous call.
+ * No event for this api..
+ *
+ * @return   0  - Success \n
+ *          -1 - On Failure\n
+ *
+ * @exception   None
+ * @param[in]  None.
+ *
+ * @remark       None
+ * @see         None
+ */
+int bluetooth_media_init(void);
+
+/**
+ * @fn int bluetooth_media_register_player(media_player_settings_t player_settings,
+ *                                     media_metadata_attributes_t metadata )
+ * @brief Registers the Music player with its player settings and media attributes
+ *
+ * This function is a asynchronous call.
+ * No event for this api..
+ *
+ * @return   0  - Success \n
+ *          -1 - On Failure\n
+ *
+ * @exception   None
+ * @param[in]   player_settings - Music player application settings,
+ *                      metadata -Meida attributes
+ *
+ * @remark       None
+ * @see         None
+ */
+int bluetooth_media_register_player(void);
+
+/**
+ * @fn int bluetooth_media_unregister_player(void )
+ * @brief Un-registers the Music player
+ *
+ * This function is a asynchronous call.
+ * No event for this api..
+ *
+ * @return   0  - Success \n
+ *          -1 - On Failure\n
+ *
+ * @exception   None
+ * @param[in]   None
+ *
+ * @remark       None
+ * @see         None
+ */
+int bluetooth_media_unregister_player(void);
+
+/**
+ * @fn int bluetooth_media_deinit(void)
+ * @brief deinitializes the Media interface to media service
+ *
+ * This function is a asynchronous call.
+ * No event for this api..
+ *
+ * @return   0  - Success \n
+ *          -1 - On Failure\n
+ *
+ * @exception   None
+ * @param[in]  None.
+ *
+ * @remark       None
+ * @see         None
+ */
+int bluetooth_media_deinit(void);
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+
+#endif /*_BLUETOOTH_CONTROL_API_H_*/
diff --git a/lib/bluetooth-le/bluetooth-gatt-api.c b/lib/bluetooth-le/bluetooth-gatt-api.c
new file mode 100644 (file)
index 0000000..f0657a7
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * Bluetooth-frwk low energy
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hocheol Seo <hocheol.seo@samsung.com>
+ *         Girishashok Joshi <girish.joshi@samsung.com>
+ *         Chanyeol Park <chanyeol.park@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 "bluetooth-api-common.h"
+#include "bluetooth-api.h"
+
+#define BLUEZ_CHAR_INTERFACE "org.bluez.Characteristic"
+
+#define GATT_OBJECT_PATH  "/org/bluez/gatt_attrib"
+
+typedef struct {
+       GObject parent;
+} BluetoothGattService;
+
+typedef struct {
+       GObjectClass parent;
+} BluetoothGattServiceClass;
+
+GType bluetooth_gatt_service_get_type(void);
+
+#define BLUETOOTH_GATT_TYPE_SERVICE (bluetooth_gatt_service_get_type())
+
+#define BLUETOOTH_GATT_SERVICE(object) \
+               (G_TYPE_CHECK_INSTANCE_CAST((object), \
+               BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattService))
+
+#define BLUETOOTH_GATT_SERVICE_CLASS(klass)    \
+               (G_TYPE_CHECK_CLASS_CAST((klass), \
+               BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
+
+#define BLUETOOTH_GATT_IS_SERVICE(object)      \
+               (G_TYPE_CHECK_INSTANCE_TYPE((object), BLUETOOTH_GATT_TYPE_SERVICE))
+
+#define BLUETOOTH_GATT_IS_SERVICE_CLASS(klass) \
+               (G_TYPE_CHECK_CLASS_TYPE((klass), BLUETOOTH_GATT_TYPE_SERVICE))
+
+#define BLUETOOTH_GATT_SERVICE_GET_CLASS(obj)  \
+               (G_TYPE_INSTANCE_GET_CLASS((obj), \
+               BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass))
+
+G_DEFINE_TYPE(BluetoothGattService, bluetooth_gatt_service, G_TYPE_OBJECT)
+
+static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
+                                       gchar *obj_path,
+                                       gpointer byte_array,
+                                       DBusGMethodInvocation *context);
+
+#include "bluetooth-gatt-glue.h"
+
+static void bluetooth_gatt_service_init(BluetoothGattService *obj)
+{
+       g_assert(obj != NULL);
+}
+
+static void bluetooth_gatt_service_finalize(GObject *obj)
+{
+       G_OBJECT_CLASS(bluetooth_gatt_service_parent_class)->finalize(obj);
+}
+
+static void bluetooth_gatt_service_class_init(BluetoothGattServiceClass *klass)
+{
+       GObjectClass *object_class = (GObjectClass *)klass;
+
+       g_assert(klass != NULL);
+
+       object_class->finalize = bluetooth_gatt_service_finalize;
+
+       dbus_g_object_type_install_info(BLUETOOTH_GATT_TYPE_SERVICE,
+                                       &dbus_glib_bluetooth_gatt_object_info);
+}
+
+static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent,
+                                       gchar *obj_path,
+                                       gpointer byte_array,
+                                       DBusGMethodInvocation *context)
+{
+       DBG("+ \n");
+       bt_gatt_char_value_t char_val;
+
+       char_val.char_handle = obj_path;
+       char_val.char_value = byte_array;
+
+       _bluetooth_internal_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED,
+                       BLUETOOTH_ERROR_NONE, &char_val);
+
+       DBG("- \n");
+
+       return TRUE;
+}
+
+static void __add_value_changed_method(DBusGConnection *conn)
+{
+       static gboolean method_added = FALSE;
+       BluetoothGattService *bluetooth_gatt_obj = NULL;
+
+       if (method_added) {
+               DBG("Method already added. \n");
+               return;
+       }
+
+       method_added = TRUE;
+
+       bluetooth_gatt_obj = g_object_new(BLUETOOTH_GATT_TYPE_SERVICE, NULL);
+
+       dbus_g_connection_register_g_object(conn, GATT_OBJECT_PATH,
+                       G_OBJECT(bluetooth_gatt_obj));
+
+       return;
+}
+
+static char **__get_string_array_from_gptr_array(GPtrArray *gp)
+{
+       gchar *gp_path = NULL;
+       char **path = NULL;
+       int i;
+
+       path = g_malloc0(gp->len * sizeof(char *));
+
+       for (i = 0; i < gp->len; i++) {
+               gp_path = g_ptr_array_index(gp, i);
+               path[i] = g_strdup(gp_path);
+               DBG("path[%d] : [%s]", i, path[i]);
+       }
+       return path;
+}
+
+static void __bluetooth_internal_get_char_cb(DBusGProxy *proxy,
+                                       DBusGProxyCall *call,
+                                       gpointer user_data)
+{
+       GError *error = NULL;
+       GPtrArray *gp_array = NULL;
+       bt_gatt_discovered_char_t svc_char = { 0, };
+
+       svc_char.service_handle = user_data;
+
+       if (!dbus_g_proxy_end_call(proxy, call, &error,
+               dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+               &gp_array, G_TYPE_INVALID)) {
+               ERR("Error : %s \n", error->message);
+               g_error_free(error);
+               _bluetooth_internal_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
+                       BLUETOOTH_ERROR_INTERNAL, &svc_char);
+               g_free(svc_char.service_handle);
+               g_object_unref(proxy);
+               return;
+       }
+
+       if (NULL != gp_array) {
+               svc_char.handle_info.count = gp_array->len;
+               svc_char.handle_info.handle = __get_string_array_from_gptr_array(gp_array);
+       }
+
+       _bluetooth_internal_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED,
+                       BLUETOOTH_ERROR_NONE, &svc_char);
+
+       g_ptr_array_free(gp_array, TRUE);
+       g_free(svc_char.service_handle);
+       g_free(svc_char.handle_info.handle);
+       g_object_unref(proxy);
+       return;
+}
+
+BT_EXPORT_API int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc)
+{
+       DBG("+\n");
+       if (prim_svc == NULL)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       g_strfreev(prim_svc->handle);
+
+       DBG("-\n");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty)
+{
+       DBG("+\n");
+       if (svc_pty == NULL)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       g_free(svc_pty->uuid);
+       g_strfreev(svc_pty->handle_info.handle);
+
+       DBG("-\n");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty)
+{
+       DBG("+\n");
+       if (char_pty == NULL)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       g_free(char_pty->uuid);
+       g_free(char_pty->name);
+       g_free(char_pty->description);
+       g_free(char_pty->val);
+
+       DBG("-\n");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_get_primary_services(const bluetooth_device_address_t *address,
+                                                               bt_gatt_handle_info_t *prim_svc)
+{
+       DBG("+\n");
+       bt_info_t *bt_internal_info = NULL;
+       char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+       const char *device_path = NULL;
+       GError *error = NULL;
+       DBusGProxy *device_proxy = NULL;
+       GHashTable *hash = NULL;
+       GValue *value = NULL;
+       GPtrArray *gp_array  = NULL;
+
+       if (address == NULL || prim_svc == NULL)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       _bluetooth_internal_session_init();
+
+       if (_bluetooth_internal_is_adapter_enabled() == FALSE)
+               return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
+
+       bt_internal_info = _bluetooth_internal_get_information();
+
+       _bluetooth_internal_addr_type_to_addr_string(device_address, address);
+       DBG("bluetooth address [%s]\n", device_address);
+
+       if (!bt_internal_info->adapter_proxy)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       dbus_g_proxy_call(bt_internal_info->adapter_proxy, "FindDevice", &error,
+               G_TYPE_STRING, device_address, G_TYPE_INVALID,
+               DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
+       if (error) {
+               ERR("FindDevice Call Error %s[%s]", error->message, device_address);
+               g_error_free(error);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       if (!device_path)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       device_proxy = _bluetooth_internal_find_device_by_path(device_path);
+       if (!device_proxy)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       dbus_g_proxy_call(device_proxy, "GetProperties", &error, G_TYPE_INVALID,
+                               dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+                               &hash, G_TYPE_INVALID);
+       if (error) {
+               ERR("GetProperties Call Error %s[%s]", error->message, device_address);
+               g_error_free(error);
+               g_object_unref(device_proxy);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       g_object_unref(device_proxy);
+
+       if (!hash)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       value = g_hash_table_lookup(hash, "Services");
+       if (!value)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       gp_array = g_value_get_boxed(value);
+       if (!gp_array)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       prim_svc->count = gp_array->len;
+       prim_svc->handle = __get_string_array_from_gptr_array(gp_array);
+       g_ptr_array_free(gp_array, TRUE);
+
+       DBG("-\n");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(const char *service_handle)
+{
+       DBusGProxy *service_proxy = NULL;
+       bt_info_t *bt_internal_info = NULL;
+       char *handle;
+
+       if (service_handle == NULL)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       _bluetooth_internal_session_init();
+
+       if (_bluetooth_internal_is_adapter_enabled() == FALSE)
+               return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
+
+       bt_internal_info = _bluetooth_internal_get_information();
+
+       service_proxy = dbus_g_proxy_new_for_name(bt_internal_info->conn,
+                                               BLUEZ_SERVICE_NAME, service_handle,
+                                               BLUEZ_CHAR_INTERFACE);
+       if (service_proxy == NULL) {
+               ERR("ERROR: Can't make dbus proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       handle = g_strdup(service_handle);
+       DBG("Requested characteristic handle:%s \n ", handle);
+
+       if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics",
+                       (DBusGProxyCallNotify)__bluetooth_internal_get_char_cb,
+                       handle, NULL, G_TYPE_INVALID)) {
+               g_free(handle);
+               g_object_unref(service_proxy);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle,
+                                               bt_gatt_service_property_t *service)
+{
+       DBusGProxy *service_proxy = NULL;
+       bt_info_t *bt_internal_info = NULL;
+       GHashTable *hash = NULL;
+       GError *error = NULL;
+       GValue *value = NULL;
+       GPtrArray *gp_array  = NULL ;
+
+       _bluetooth_internal_session_init();
+
+       if (_bluetooth_internal_is_adapter_enabled() == FALSE)
+               return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
+
+       bt_internal_info = _bluetooth_internal_get_information();
+
+       service_proxy = dbus_g_proxy_new_for_name(bt_internal_info->conn,
+                                               BLUEZ_SERVICE_NAME, service_handle,
+                                               BLUEZ_CHAR_INTERFACE);
+       if (service_proxy == NULL) {
+               ERR("ERROR: Can't make dbus proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       dbus_g_proxy_call(service_proxy, "GetProperties", &error, G_TYPE_INVALID,
+                               dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+                               &hash, G_TYPE_INVALID);
+       if (error != NULL) {
+               ERR("GetProperties Call Error %s\n", error->message);
+               g_error_free(error);
+               g_object_unref(service_proxy);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       g_object_unref(service_proxy);
+
+       if (!hash)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       value = g_hash_table_lookup(hash, "UUID");
+       service->uuid = value ? g_value_dup_string(value) : NULL;
+       if (service->uuid) {
+               DBG("svc_pty.uuid = [%s] \n", service->uuid);
+       }
+
+       value = g_hash_table_lookup(hash, "Characteristics");
+       gp_array = value ? g_value_get_boxed(value) : NULL;
+       if (NULL != gp_array) {
+               service->handle_info.count = gp_array->len;
+               service->handle_info.handle = __get_string_array_from_gptr_array(gp_array);
+               g_ptr_array_free(gp_array, TRUE);
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *service_handle)
+{
+       DBusGProxy *watch_proxy = NULL;
+       bt_info_t *bt_internal_info = NULL;
+       GError *error = NULL;
+
+       if (NULL == service_handle)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       DBG("Entered service handle:%s \n ", service_handle);
+
+       _bluetooth_internal_session_init();
+
+       if (_bluetooth_internal_is_adapter_enabled() == FALSE)
+               return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
+
+       bt_internal_info = _bluetooth_internal_get_information();
+
+       watch_proxy = dbus_g_proxy_new_for_name(bt_internal_info->conn,
+                               BLUEZ_SERVICE_NAME, service_handle,
+                               BLUEZ_CHAR_INTERFACE);
+       if (watch_proxy == NULL) {
+               ERR("ERROR: Can't make dbus proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       __add_value_changed_method(bt_internal_info->conn);
+
+       dbus_g_proxy_call(watch_proxy, "RegisterCharacteristicsWatcher", &error,
+                               DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
+                               G_TYPE_INVALID, G_TYPE_INVALID);
+       if (error) {
+               ERR("Method call  Fail: %s", error->message);
+               g_error_free(error);
+               g_object_unref(watch_proxy);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       g_object_unref(watch_proxy);
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *service_handle)
+{
+       DBusGProxy *watch_proxy = NULL;
+       bt_info_t *bt_internal_info = NULL;
+       GError *error = NULL;
+
+       if (NULL == service_handle)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       DBG("Entered service handle:%s \n ", service_handle);
+
+       _bluetooth_internal_session_init();
+
+       if (_bluetooth_internal_is_adapter_enabled() == FALSE)
+               return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
+
+       bt_internal_info = _bluetooth_internal_get_information();
+
+       watch_proxy = dbus_g_proxy_new_for_name(bt_internal_info->conn,
+                               BLUEZ_SERVICE_NAME, service_handle,
+                               BLUEZ_CHAR_INTERFACE);
+       if (watch_proxy == NULL) {
+               ERR("ERROR: Can't make dbus proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       dbus_g_proxy_call(watch_proxy, "UnregisterCharacteristicsWatcher", &error,
+                               DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH,
+                               G_TYPE_INVALID, G_TYPE_INVALID);
+       if (error) {
+               ERR("Method call  Fail: %s", error->message);
+               g_error_free(error);
+               g_object_unref(watch_proxy);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       g_object_unref(watch_proxy);
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(const char *char_handle,
+                                               bt_gatt_char_property_t *characteristic)
+{
+       bt_info_t *bt_internal_info = NULL;
+       DBusGProxy *characteristic_proxy = NULL;
+       GHashTable *hash = NULL;
+       GError *error = NULL;
+       GValue *value = NULL;
+       GByteArray *gb_array = NULL;
+
+       if (char_handle == NULL || characteristic == NULL)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       _bluetooth_internal_session_init();
+
+       if (_bluetooth_internal_is_adapter_enabled() == FALSE)
+               return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
+
+       bt_internal_info = _bluetooth_internal_get_information();
+
+       characteristic_proxy = dbus_g_proxy_new_for_name(bt_internal_info->conn,
+                                                       BLUEZ_SERVICE_NAME, char_handle,
+                                                       BLUEZ_CHAR_INTERFACE);
+       if (characteristic_proxy == NULL) {
+               ERR("ERROR: Can't make dbus proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       dbus_g_proxy_call(characteristic_proxy, "GetProperties", &error, G_TYPE_INVALID,
+                               dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+                               &hash, G_TYPE_INVALID);
+       if (error != NULL) {
+               ERR("GetProperties Call Error %s\n", error->message);
+               g_error_free(error);
+               g_object_unref(characteristic_proxy);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+       g_object_unref(characteristic_proxy);
+
+       if (!hash)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       value = g_hash_table_lookup(hash, "UUID");
+       characteristic->uuid = value ? g_value_dup_string(value) : NULL;
+       if (characteristic->uuid) {
+               DBG("characteristic->uuid = [%s] \n", characteristic->uuid);
+       }
+
+       value = g_hash_table_lookup(hash, "Name");
+       characteristic->name = value ? g_value_dup_string(value) : NULL;
+       if (characteristic->name) {
+               DBG("characteristic->name = [%s] \n", characteristic->name);
+       }
+
+       value = g_hash_table_lookup(hash, "Description");
+       characteristic->description = value ? g_value_dup_string(value) : NULL;
+       if (characteristic->description) {
+               DBG("characteristic->description = [%s] \n", characteristic->description);
+       }
+
+       value = g_hash_table_lookup(hash, "Value");
+
+       gb_array = value ? g_value_get_boxed(value) : NULL;
+       if (gb_array) {
+               if (gb_array->len) {
+                       DBG("gb_array->len  = %d \n", gb_array->len);
+                       characteristic->val_len = gb_array->len;
+
+                       characteristic->val = g_malloc0(gb_array->len * sizeof(unsigned char));
+                       memcpy(characteristic->val, gb_array->data, gb_array->len);
+               } else {
+                       characteristic->val = NULL;
+               }
+
+               g_byte_array_free(gb_array, TRUE);
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(const char *char_handle,
+                                               const guint8 *value, int length)
+{
+       bt_info_t *bt_internal_info = NULL;
+       DBusGProxy *characteristic_proxy = NULL;
+       GValue *val;
+       GByteArray *gbarray;
+       GError *error = NULL;
+
+       if (char_handle == NULL || value == NULL || length == 0)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       DBG("Requested characteristic handle:%s \n ", char_handle);
+
+       _bluetooth_internal_session_init();
+
+       if (_bluetooth_internal_is_adapter_enabled() == FALSE)
+               return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
+
+       bt_internal_info = _bluetooth_internal_get_information();
+
+       characteristic_proxy = dbus_g_proxy_new_for_name(bt_internal_info->conn,
+                                                       BLUEZ_SERVICE_NAME, char_handle,
+                                                       BLUEZ_CHAR_INTERFACE);
+       if (characteristic_proxy == NULL) {
+               ERR("ERROR: Can't make dbus proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       gbarray = g_byte_array_new();
+       g_byte_array_append(gbarray, (guint8 *)value, length);
+
+       val = g_new0(GValue, 1);
+       g_value_init(val, DBUS_TYPE_G_UCHAR_ARRAY);
+       g_value_take_boxed(val, gbarray);
+
+       dbus_g_proxy_call(characteristic_proxy, "SetProperty",
+               &error, G_TYPE_STRING, "Value",
+               G_TYPE_VALUE, val, G_TYPE_INVALID, G_TYPE_INVALID);
+
+       g_object_unref(characteristic_proxy);
+       g_free(val);
+
+       if (error) {
+               ERR("Set value Fail: %s", error->message);
+               g_error_free(error);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
diff --git a/lib/bluetooth-le/bluetooth-gatt-glue.h b/lib/bluetooth-le/bluetooth-gatt-glue.h
new file mode 100644 (file)
index 0000000..5cece6f
--- /dev/null
@@ -0,0 +1,120 @@
+/* Generated by dbus-binding-tool; do not edit! */
+
+
+#ifndef __dbus_glib_marshal_bluetooth_gatt_MARSHAL_H__
+#define __dbus_glib_marshal_bluetooth_gatt_MARSHAL_H__
+
+#include       <glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* NONE:BOXED,BOXED,POINTER */
+extern void dbus_glib_marshal_bluetooth_gatt_VOID__BOXED_BOXED_POINTER (GClosure     *closure,
+                                                                        GValue       *return_value,
+                                                                        guint         n_param_values,
+                                                                        const GValue *param_values,
+                                                                        gpointer      invocation_hint,
+                                                                        gpointer      marshal_data);
+void
+dbus_glib_marshal_bluetooth_gatt_VOID__BOXED_BOXED_POINTER (GClosure     *closure,
+                                                            GValue       *return_value G_GNUC_UNUSED,
+                                                            guint         n_param_values,
+                                                            const GValue *param_values,
+                                                            gpointer      invocation_hint G_GNUC_UNUSED,
+                                                            gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__BOXED_BOXED_POINTER) (gpointer     data1,
+                                                          gpointer     arg_1,
+                                                          gpointer     arg_2,
+                                                          gpointer     arg_3,
+                                                          gpointer     data2);
+  register GMarshalFunc_VOID__BOXED_BOXED_POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 4);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__BOXED_BOXED_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_boxed (param_values + 1),
+            g_marshal_value_peek_boxed (param_values + 2),
+            g_marshal_value_peek_pointer (param_values + 3),
+            data2);
+}
+#define dbus_glib_marshal_bluetooth_gatt_NONE__BOXED_BOXED_POINTER     dbus_glib_marshal_bluetooth_gatt_VOID__BOXED_BOXED_POINTER
+
+G_END_DECLS
+
+#endif /* __dbus_glib_marshal_bluetooth_gatt_MARSHAL_H__ */
+
+#include <dbus/dbus-glib.h>
+static const DBusGMethodInfo dbus_glib_bluetooth_gatt_methods[] = {
+  { (GCallback) bluetooth_gatt_value_changed, dbus_glib_marshal_bluetooth_gatt_NONE__BOXED_BOXED_POINTER, 0 },
+};
+
+const DBusGObjectInfo dbus_glib_bluetooth_gatt_object_info = {  1,
+  dbus_glib_bluetooth_gatt_methods,
+  1,
+"org.bluez.Watcher\0ValueChanged\0A\0objpath\0I\0o\0value\0I\0ay\0\0\0",
+"\0",
+"\0"
+};
+
diff --git a/lib/bluetooth-le/bluetooth-gatt.xml b/lib/bluetooth-le/bluetooth-gatt.xml
new file mode 100644 (file)
index 0000000..a2f7bd9
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+       <interface name="org.bluez.Watcher">
+
+               <method name="ValueChanged">
+                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+                       <arg type="o" name="objpath"/>
+                       <arg type="ay" name="value"/>
+               </method>
+
+       </interface>
+</node>
+