--- /dev/null
+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)
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+<?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>
--- /dev/null
+[D-BUS Service]
+Name=org.bluez.hfp_agent
+Exec=/usr/bin/bluetooth-hfp-agent
--- /dev/null
+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)
--- /dev/null
+/*
+ * 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_*/
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_*/
--- /dev/null
+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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+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)
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_*/
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+<?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>
--- /dev/null
+# DBUS Signal argument converting list for bluetooth telephony lib
+VOID:UINT
+VOID:INT
+VOID:STRING,UINT
+VOID:STRING
--- /dev/null
+#!/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
--- /dev/null
+/*
+ * 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 *)µphone_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);
+}
--- /dev/null
+/*
+ * 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_*/
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_*/
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/* 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"
+};
+
--- /dev/null
+<?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>
+