[Bluetooth][OTP] Add base code for OTP server role 57/121657/7
authorGowtham Anandha Babu <gowtham.ab@samsung.com>
Tue, 28 Mar 2017 10:34:42 +0000 (16:04 +0530)
committerPyun DoHyun <dh79.pyun@samsung.com>
Wed, 12 Apr 2017 06:57:40 +0000 (23:57 -0700)
Implement OTP server role:
-------------------------
1) Add logic for init / deinit the OTP server.
2) On init, OTP server will run as a process
   called bt-otp.
3) Add support to indicate OTP server state(enabled/disabled)
   to applicaton.

All TODOs will be handled in upcoming patch set.

Change-Id: I98aa0a8988884d612ac05e8b52e4c5ccf637a500
Signed-off-by: Gowtham Anandha Babu <gowtham.ab@samsung.com>
23 files changed:
CMakeLists.txt
bt-api/CMakeLists.txt
bt-api/bt-common.c
bt-api/bt-event-handler.c
bt-api/bt-otp.c [new file with mode: 0644]
bt-core/CMakeLists.txt
bt-core/bt-core-adapter.c
bt-core/bt-core-dbus-handler.c
bt-core/include/bt-core-dbus-handler.h
bt-otp/CMakeLists.txt [new file with mode: 0644]
bt-otp/bluetooth-frwk-otp.conf [new file with mode: 0644]
bt-otp/bt-otpserver.c [new file with mode: 0644]
bt-otp/bt-otpserver.h [new file with mode: 0755]
bt-otp/org.projectx.otp.service [new file with mode: 0644]
bt-service/CMakeLists.txt
bt-service/bt-request-handler.c
bt-service/bt-service-common.c
bt-service/bt-service-event-sender.c
bt-service/bt-service-otp.c [new file with mode: 0644]
bt-service/include/bt-service-otp.h [new file with mode: 0644]
include/bluetooth-api.h
include/bt-internal-types.h
packaging/bluetooth-frwk.spec

index f616072..ec41c20 100644 (file)
@@ -10,6 +10,8 @@ ENDIF()
 
 ADD_SUBDIRECTORY(bt-httpproxy)
 
+ADD_SUBDIRECTORY(bt-otp)
+
 ADD_SUBDIRECTORY(bt-core)
 
 ADD_SUBDIRECTORY(plugin)
index 32024cd..8ec4d16 100644 (file)
@@ -29,7 +29,8 @@ bt-gatt-client.c
 bt-ipsp.c
 bt-dpm.c
 bt-proximity.c
-bt-tds.c)
+bt-tds.c
+bt-otp.c)
 
 SET(HEADERS
 bluetooth-api.h
@@ -85,6 +86,7 @@ IF("${ARCH}" STREQUAL "arm")
 ENDIF("${ARCH}" STREQUAL "arm")
 
 #ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_HPS")
+ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_OTP")
 ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_DPM")
 
 FIND_PROGRAM(MARSHALTOOL NAMES glib-genmarshal)
index d46ec6d..3839810 100644 (file)
@@ -2107,6 +2107,9 @@ BT_EXPORT_API int bluetooth_register_callback(bluetooth_cb_func_ptr callback_ptr
                ret = _bt_register_event(BT_TDS_EVENT, (void *)callback_ptr, user_data);
                if (ret != BLUETOOTH_ERROR_NONE)
                        goto fail;
+               ret = _bt_register_event(BT_OTP_EVENT, (void *)callback_ptr, user_data);
+               if (ret != BLUETOOTH_ERROR_NONE)
+                       goto fail;
        }
 
        _bt_register_name_owner_changed();
index 8f7a64a..a354dce 100644 (file)
@@ -3018,6 +3018,45 @@ static void __bt_tds_event_filter(GDBusConnection *connection,
        BT_DBG("-");
 }
 
+static void __bt_otp_event_filter(GDBusConnection *connection,
+               const gchar *sender_name,
+               const gchar *object_path,
+               const gchar *interface_name,
+               const gchar *signal_name,
+               GVariant *parameters,
+               gpointer user_data)
+{
+       bt_event_info_t *event_info;
+       event_info = (bt_event_info_t *)user_data;
+       int result = BLUETOOTH_ERROR_NONE;
+
+       ret_if(event_info == NULL);
+
+       if (strcasecmp(object_path, BT_OTP_PATH) != 0)
+               return;
+       if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0)
+               return;
+
+       ret_if(signal_name == NULL);
+
+       BT_DBG("+");
+
+       if (strcasecmp(signal_name, BT_OTP_SERVER_STATE_CHANGED) == 0) {
+               BT_DBG("OTP Server State Changed Event");
+               bool status = FALSE;
+
+               /* Extract data from DBUS params */
+               g_variant_get(parameters, "(ib)", &result, &status);
+               BT_DBG("Result [%d]", result);
+               BT_DBG("Status  [%s]", status ? "enabled" : "disabled");
+
+               _bt_common_event_cb(BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED,
+                               result, &status, event_info->cb, event_info->user_data);
+       }
+
+       BT_DBG("-");
+}
+
 static void __bt_remove_all_events(void)
 {
        bt_event_info_t *info;
@@ -3244,6 +3283,11 @@ int _bt_register_event(int event_type, void *event_cb, void *user_data)
                event_func = __bt_tds_event_filter;
                path = BT_TDS_PATH;
                break;
+       case BT_OTP_EVENT:
+               BT_DBG("BT_OTP_EVENT");
+               event_func = __bt_otp_event_filter;
+               path = BT_OTP_PATH;
+               break;
        default:
                BT_ERR("Unknown event");
                return BLUETOOTH_ERROR_INTERNAL;
diff --git a/bt-api/bt-otp.c b/bt-api/bt-otp.c
new file mode 100644 (file)
index 0000000..f10d0d7
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.h"
+#include "bt-internal-types.h"
+
+#include "bt-common.h"
+#include "bt-request-sender.h"
+#include "bt-event-handler.h"
+
+BT_EXPORT_API int bluetooth_otp_server_init(const char *directory)
+{
+       int result = BLUETOOTH_ERROR_INTERNAL;
+       bt_user_info_t *user_info;
+       char dir_name[BLUETOOTH_MAX_OTP_SERVER_DIR_NAME];
+       BT_DBG("+");
+
+       BT_CHECK_ENABLED(return);
+
+       user_info = _bt_get_user_data(BT_COMMON);
+       retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       if (directory)
+               g_strlcpy(dir_name, directory, sizeof(dir_name));
+       else
+               dir_name[0] = '\0';
+
+       g_array_append_vals(in_param1, dir_name, BLUETOOTH_MAX_OTP_SERVER_DIR_NAME);
+
+       result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_SERVER_INIT,
+               in_param1, in_param2, in_param3, in_param4,
+               user_info->cb, user_info->user_data);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       BT_DBG("-");
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_otp_server_deinit()
+{
+       int result = BLUETOOTH_ERROR_INTERNAL;
+       bt_user_info_t *user_info;
+       BT_DBG("+");
+
+       BT_CHECK_ENABLED(return);
+
+       user_info = _bt_get_user_data(BT_COMMON);
+       retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+       BT_DBG("");
+
+       result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_SERVER_DEINIT,
+               in_param1, in_param2, in_param3, in_param4,
+               user_info->cb, user_info->user_data);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       BT_DBG("-");
+       return result;
+}
\ No newline at end of file
index 1bbf1cc..acaddb4 100644 (file)
@@ -46,6 +46,7 @@ ADD_DEFINITIONS("-DAPPNAME=\"${APP_NAME}\"")
 ADD_DEFINITIONS("-DAPP_DIR=\"${APP_DIR}\"")
 ADD_DEFINITIONS("-DAPP_SYSCONFDIR=\"${APP_SYSCONFDIR}\"")
 #ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_HPS")
+ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_OTP")
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
 
index 1860931..f42caa9 100644 (file)
@@ -356,6 +356,10 @@ int _bt_disable_adapter_le(void)
        _bt_core_stop_httpproxy();
 #endif
 
+#ifdef TIZEN_FEATURE_BT_OTP
+       _bt_core_stop_otp();
+#endif
+
        status = _bt_core_get_status();
        BT_DBG("status : %d", status);
 
index 34c34c7..41f15b0 100644 (file)
 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
 #endif
 
+#ifdef TIZEN_FEATURE_BT_OTP
+#define BT_OTP_SERVICE_NAME    "org.projectx.otp"
+#define BT_OTP_OBJECT_PATH     "/org/projectx/otp"
+#define BT_OTP_INTERFACE_NAME  "org.projectx.otp_service"
+#endif
+
 static GDBusConnection *service_gconn;
 static GDBusProxy *service_gproxy;
 #ifdef TIZEN_FEATURE_BT_HPS
 static GDBusProxy *hps_gproxy;
 #endif
 
+#ifdef TIZEN_FEATURE_BT_OTP
+static GDBusProxy *otp_gproxy;
+#endif
+
 void _bt_core_fill_garray_from_variant(GVariant *var, GArray *param)
 {
        char *data;
@@ -198,6 +208,69 @@ GDBusProxy *_bt_core_gdbus_get_hps_proxy(void)
 }
 #endif
 
+#ifdef TIZEN_FEATURE_BT_OTP
+static GDBusProxy *_bt_core_gdbus_init_otp_proxy(void)
+{
+       GDBusProxy *proxy;
+       GError *err = NULL;
+       GDBusConnection *conn;
+
+       BT_DBG(" ");
+
+       conn = _bt_core_get_gdbus_connection();
+       if (!conn)
+               return NULL;
+
+       proxy =  g_dbus_proxy_new_sync(conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       BT_OTP_SERVICE_NAME,
+                       BT_OTP_OBJECT_PATH,
+                       BT_OTP_INTERFACE_NAME,
+                       NULL, &err);
+       if (proxy == NULL) {
+               if (err) {
+                        BT_ERR("Unable to create proxy: %s", err->message);
+                        g_clear_error(&err);
+               }
+               return NULL;
+       }
+
+       otp_gproxy = proxy;
+
+       return proxy;
+}
+
+GDBusProxy *_bt_core_gdbus_get_otp_proxy(void)
+{
+       return (otp_gproxy) ? otp_gproxy : _bt_core_gdbus_init_otp_proxy();
+}
+
+int _bt_core_stop_otp(void)
+{
+       GVariant *variant = NULL;
+       unsigned char enabled;
+       GError *err = NULL;
+       BT_DBG(" ");
+
+       otp_gproxy = _bt_core_gdbus_get_otp_proxy();
+       if (!otp_gproxy) {
+               BT_DBG("Couldn't get service proxy");
+               return -1;
+       }
+
+       variant = g_dbus_proxy_call_sync(otp_gproxy, "disable",
+                               NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+       if (err) {
+               BT_ERR("Error : %s" , err->message);
+               g_clear_error(&err);
+       }
+       if (variant) {
+               g_variant_get(variant, "(y)", &enabled);
+               BT_ERR("OTP disabled status 0x%x", enabled);
+       }
+       return 0;
+}
+#endif
 void _bt_core_gdbus_deinit_proxys(void)
 {
        BT_DBG("");
@@ -214,6 +287,13 @@ void _bt_core_gdbus_deinit_proxys(void)
        }
 #endif
 
+#ifdef TIZEN_FEATURE_BT_OTP
+       if (otp_gproxy) {
+               g_object_unref(otp_gproxy);
+               otp_gproxy = NULL;
+       }
+#endif
+
        if (service_gconn) {
                g_object_unref(service_gconn);
                service_gconn = NULL;
index dfaef71..25d0bed 100755 (executable)
@@ -53,6 +53,9 @@ GDBusProxy *_bt_core_gdbus_get_hps_proxy(void);
 int _bt_core_start_httpproxy(void);
 int _bt_core_stop_httpproxy(void);
 #endif
+#ifdef TIZEN_FEATURE_BT_OTP
+int _bt_core_stop_otp(void);
+#endif
 void _bt_core_gdbus_deinit_proxys(void);
 
 GDBusConnection * _bt_core_get_gdbus_connection(void);
diff --git a/bt-otp/CMakeLists.txt b/bt-otp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..eb3a814
--- /dev/null
@@ -0,0 +1,46 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(bt-otp C)
+
+SET(SRCS bt-otpserver.c)
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+       SET(CMAKE_BUILD_TYPE "Release")
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+SET(PKG_MODULES
+       dbus-glib-1
+       gio-2.0
+       pkgmgr
+       eventsystem
+       dbus-1
+)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(otp_pkgs REQUIRED ${PKG_MODULES})
+
+FOREACH(flag ${otp_pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag} -Wall")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+SET(APP_SYSCONFDIR /opt/var/lib/bluetooth)
+
+FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool)
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${otp_pkgs_LDFLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/../bt-api -lbluetooth-api)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.otp.service DESTINATION share/dbus-1/system-services)
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-otp.conf DESTINATION /etc/dbus-1/system.d)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
diff --git a/bt-otp/bluetooth-frwk-otp.conf b/bt-otp/bluetooth-frwk-otp.conf
new file mode 100644 (file)
index 0000000..537575f
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+    <policy user="root">
+        <allow own="org.projectx.otp"/>
+    </policy>
+    <policy at_console="true">
+        <allow send_destination="org.projectx.otp" />
+    </policy>
+    <policy context="default">
+        <allow send_destination="org.projectx.otp" />
+    </policy>
+</busconfig>
+
diff --git a/bt-otp/bt-otpserver.c b/bt-otp/bt-otpserver.c
new file mode 100644 (file)
index 0000000..b2c0f0d
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <dlog.h>
+#include <gio/gio.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <langinfo.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include "bt-otpserver.h"
+#include "bluetooth-api.h"
+
+
+#undef LOG_TAG
+#define LOG_TAG "BLUETOOTH_OTP"
+
+#define BT_INFO(fmt, arg...) SLOGI(fmt, ##arg)
+#define BT_ERR(fmt, arg...) SLOGE(fmt, ##arg)
+#define BT_DBG(fmt, arg...) SLOGD(fmt, ##arg)
+
+static GMainLoop *main_loop;
+GDBusNodeInfo *otp_node_info = NULL;
+static GDBusConnection *conn;
+static GDBusConnection *g_conn;
+
+static int property_sub_id = -1;
+static guint g_owner_id = 0;
+
+char *directory = NULL;
+
+static const gchar otp_introspection_xml[] =
+"<node name='/'>"
+"      <interface name='org.projectx.otp_service'>"
+"              <method name='enable'>"
+"                      <arg type='s' name='directory'/>"
+"                      <arg type='i' name='status' direction='out'/>"
+"              </method>"
+"              <method name='disable'>"
+"                      <arg type='i' name='status' direction='out'/>"
+"              </method>"
+"      </interface>"
+"</node>";
+
+void _bt_otp_deinit_event_receiver(void);
+void _bt_otp_unregister_interface(void);
+
+void _bt_otp_exit(void)
+{
+       int ret;
+       BT_DBG("");
+
+       ret = bluetooth_gatt_deinit();
+       if (ret != BLUETOOTH_ERROR_NONE)
+               BT_ERR("Failed to Deinit GATT %d", ret);
+
+       _bt_otp_deinit_event_receiver();
+
+       _bt_otp_unregister_interface();
+
+       if (main_loop != NULL) {
+               g_main_loop_quit(main_loop);
+       }
+}
+
+static void _bt_otp_method(GDBusConnection *connection,
+               const gchar *sender,
+               const gchar *object_path,
+               const gchar *interface_name,
+               const gchar *method_name,
+               GVariant *parameters,
+               GDBusMethodInvocation *invocation,
+               gpointer user_data)
+{
+       BT_DBG("+");
+       int status = BLUETOOTH_ERROR_NONE;
+
+       BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
+                       method_name, object_path, interface_name);
+
+       if (g_strcmp0(method_name, "enable") == 0) {
+               GDir *dir = NULL;
+               GError *error = NULL;
+               const gchar *filename = NULL;
+               GSList *list = NULL;
+
+               g_variant_get(parameters, "(s)", &directory);
+               BT_DBG("Directory = [%s]", directory);
+
+               dir = g_dir_open(directory, 0, &error);
+               if (!dir) {
+                       BT_ERR("Failed to open directory: %s", error->message);
+                       g_error_free(error);
+                       status = BLUETOOTH_ERROR_INVALID_DIRECTORY;
+                       goto fail;
+               }
+
+               while ((filename = g_dir_read_name(dir))) {
+                       list = g_slist_append(list, (gpointer) filename);
+               }
+
+               /* TODO: Extract metadata from these objects and cache it in internal structure */
+
+               /* TODO: Expose all OTS Characteristics via RegisterApplication */
+
+               /* TODO: Advertise with OTS_UUID */
+fail:
+               g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", status));
+
+       } else if (g_strcmp0(method_name, "disable") == 0) {
+               g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", status));
+               _bt_otp_exit();
+       }
+       BT_DBG("-");
+}
+
+static const GDBusInterfaceVTable otp_method_table = {
+       _bt_otp_method,
+       NULL,
+       NULL,
+};
+
+static void _bt_otp_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+       guint object_id;
+       GError *error = NULL;
+
+       BT_DBG("+");
+
+       g_conn = connection;
+
+       object_id = g_dbus_connection_register_object(connection, BT_OTP_OBJECT_PATH,
+                                               otp_node_info->interfaces[0],
+                                               &otp_method_table,
+                                               NULL, NULL, &error);
+       if (object_id == 0) {
+               BT_ERR("Failed to register method table: %s", error->message);
+               g_error_free(error);
+               g_dbus_node_info_unref(otp_node_info);
+       }
+
+       BT_DBG("-");
+}
+
+static void _bt_otp_on_name_acquired(GDBusConnection *connection,
+                                       const gchar     *name,
+                                       gpointer user_data)
+{
+       BT_DBG("");
+}
+
+static void _bt_otp_on_name_lost(GDBusConnection *connection,
+                               const gchar     *name,
+                               gpointer user_data)
+{
+       BT_DBG("");
+       g_object_unref(g_conn);
+       g_conn = NULL;
+       g_dbus_node_info_unref(otp_node_info);
+       g_bus_unown_name(g_owner_id);
+}
+
+int _bt_otp_register_interface(void)
+{
+       BT_DBG("+");
+       GError *error = NULL;
+       guint owner_id;
+
+       otp_node_info = g_dbus_node_info_new_for_xml(otp_introspection_xml, &error);
+       if (!otp_node_info) {
+               BT_ERR("Failed to install: %s", error->message);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+                               BT_OTP_SERVICE_NAME,
+                               G_BUS_NAME_OWNER_FLAGS_NONE,
+                               _bt_otp_on_bus_acquired, _bt_otp_on_name_acquired, _bt_otp_on_name_lost,
+                               NULL, NULL);
+       g_owner_id = owner_id;
+       BT_DBG("owner_id is [%d]\n", owner_id);
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+void _bt_otp_unregister_interface(void)
+{
+       BT_DBG("+");
+
+       g_object_unref(g_conn);
+       g_conn = NULL;
+       g_dbus_node_info_unref(otp_node_info);
+       g_bus_unown_name(g_owner_id);
+
+       BT_DBG("-");
+       return;
+}
+
+void _bt_otp_property_event_filter(GDBusConnection *connection,
+                                       const gchar *sender_name,
+                                       const gchar *object_path,
+                                       const gchar *interface_name,
+                                       const gchar *signal_name,
+                                       GVariant *parameters,
+                                       gpointer user_data)
+{
+       GVariant *value;
+
+       if (signal_name == NULL) {
+               BT_ERR("Wrong Signal");
+               return;
+       }
+
+       if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
+
+               g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
+               /* TODO: Handle READ/WRITE request from client */
+       }
+}
+
+int _bt_otp_init_event_receiver()
+{
+       BT_DBG("+");
+       GError *error = NULL;
+
+       if (conn == NULL) {
+               conn =  g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+               if (error != NULL) {
+                       BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
+                       g_clear_error(&error);
+               }
+       }
+
+       property_sub_id = g_dbus_connection_signal_subscribe(conn,
+               NULL, BT_OTP_INTERFACE_NAME,
+               PROPERTIES_CHANGED, BT_OTP_OBJECT_PATH, NULL, 0,
+               _bt_otp_property_event_filter,
+               NULL, NULL);
+       BT_DBG("property_sub_id = %d", property_sub_id);
+
+       BT_DBG("-");
+       return 0;
+}
+
+void _bt_otp_deinit_event_receiver(void)
+{
+       BT_DBG("+");
+
+       g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
+       conn = NULL;
+
+       BT_DBG("-");
+}
+
+static void _bt_otp_sig_handler(int sig)
+{
+       BT_DBG("+");
+       switch (sig) {
+       case SIGTERM:
+               BT_DBG("caught signal - sigterm\n");
+               break;
+       case SIGINT:
+               BT_DBG("caught signal - sigint\n");
+               break;
+       case SIGKILL:
+               BT_DBG("caught signal - sigkill\n");
+               break;
+       default:
+               BT_DBG("caught signal %d and ignored\n", sig);
+               break;
+       }
+       BT_DBG("-");
+}
+
+/* OTP Service Main loop */
+int main(void)
+{
+       struct sigaction sa;
+       BT_ERR("Starting the bt-otp daemon");
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = _bt_otp_sig_handler;
+       sa.sa_flags = SA_SIGINFO;
+       sigaction(SIGINT, &sa, NULL);
+       sigaction(SIGTERM, &sa, NULL);
+       sigaction(SIGKILL, &sa, NULL);
+
+       if (_bt_otp_register_interface() != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Fail to register otp service");
+               return -4;
+       }
+
+       if (_bt_otp_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Fail to init event reciever");
+               return -5;
+       }
+
+       main_loop = g_main_loop_new(NULL, FALSE);
+
+       g_main_loop_run(main_loop);
+
+       BT_DBG("g_main_loop_quit called!");
+
+       if (main_loop != NULL) {
+               g_main_loop_unref(main_loop);
+       }
+
+       return 0;
+}
diff --git a/bt-otp/bt-otpserver.h b/bt-otp/bt-otpserver.h
new file mode 100755 (executable)
index 0000000..046c808
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ *
+ */
+
+#define BT_OTP_SERVICE_NAME    "org.projectx.otp"
+#define BT_OTP_OBJECT_PATH     "/org/projectx/otp"
+#define BT_OTP_INTERFACE_NAME  "org.projectx.otp_service"
+
+#define PROPERTIES_CHANGED     "PropertiesChanged"
diff --git a/bt-otp/org.projectx.otp.service b/bt-otp/org.projectx.otp.service
new file mode 100644 (file)
index 0000000..0143eef
--- /dev/null
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.projectx.otp
+Exec=/usr/bin/bt-otp
+User=root
index a5007c3..a7290c6 100644 (file)
@@ -32,6 +32,7 @@ bt-service-pbap.c
 bt-service-dpm.c
 bt-service-proximity.c
 bt-service-tds.c
+bt-service-otp.c
 )
 
 IF(LIBNOTIFY_SUPPORT)
@@ -101,6 +102,7 @@ ADD_DEFINITIONS("-DAPP_LOCALEDIR=\"${APP_LOCALEDIR}\"")
 ADD_DEFINITIONS("-DAPP_SYSCONFDIR=\"${APP_SYSCONFDIR}\"")
 #ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_HPS")
 ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_DPM")
+ADD_DEFINITIONS("-DTIZEN_FEATURE_BT_OTP")
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
 
index 08cb882..2a3275f 100644 (file)
@@ -46,6 +46,7 @@
 #include "bt-service-agent.h"
 #include "bt-service-proximity.h"
 #include "bt-service-tds.h"
+#include "bt-service-otp.h"
 
 static GDBusConnection *bt_service_conn;
 static guint owner_id = 0;
@@ -2345,6 +2346,16 @@ int __bt_bluez_request(int function_name,
                        g_free(handle);
                break;
        }
+       case BT_OTP_SERVER_INIT: {
+               const char *directory;
+               directory = (const char *)g_variant_get_data(in_param1);
+               result = bt_otp_server_init(request_id, directory);
+               break;
+       }
+       case BT_OTP_SERVER_DEINIT: {
+               result = bt_otp_server_deinit(request_id);
+               break;
+       }
        default:
                result = BLUETOOTH_ERROR_INTERNAL;
                break;
@@ -3188,6 +3199,10 @@ gboolean __bt_service_check_privilege(int function_name,
        case BT_TDS_ENABLE_CONTROL_POINT:
        case BT_TDS_ACTIVATE_CONTROL_POINT:
 
+       /* OTP Server */
+       case BT_OTP_SERVER_INIT:
+       case BT_OTP_SERVER_DEINIT:
+
        case BT_MAP_CREATE_SESSION:
        case BT_MAP_DESTROY_SESSION:
        case BT_MAP_SET_FOLDER:
index 44d7679..32f8ce8 100644 (file)
@@ -1344,7 +1344,7 @@ int _bt_eventsystem_set_value(const char *event, const char *key, const char *va
 {
        int ret = ES_R_OK;
 /* Send event system event in bt-core process because bt-service's permission is not system in now */
-\r#if 0
+#if 0
        bundle *b = NULL;
 
        b = bundle_create();
index a7d3328..158e910 100644 (file)
@@ -115,6 +115,9 @@ int _bt_send_event(int event_type, int event, GVariant *param)
        case BT_A2DP_SOURCE_EVENT:
                path = BT_A2DP_SOURCE_PATH;
                break;
+       case BT_OTP_EVENT:
+               path = BT_OTP_PATH;
+               break;
        default:
                BT_ERR("Unknown event");
                return BLUETOOTH_ERROR_INTERNAL;
@@ -455,6 +458,9 @@ int _bt_send_event(int event_type, int event, GVariant *param)
        case BLUETOOTH_EVENT_PXP_PROPERTY_CHANGED:
                signal = BT_PXP_PROPERTY_CHANGED;
                break;
+       case BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED:
+               signal = BT_OTP_SERVER_STATE_CHANGED;
+               break;
        default:
                BT_ERR("Unknown event");
                return BLUETOOTH_ERROR_INTERNAL;
diff --git a/bt-service/bt-service-otp.c b/bt-service/bt-service-otp.c
new file mode 100644 (file)
index 0000000..432454e
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <string.h>
+#include <syspopup_caller.h>
+#include <vconf.h>
+#include <bundle_internal.h>
+
+#include "bluetooth-api.h"
+#include "bt-internal-types.h"
+
+#include "bt-service-common.h"
+#include "bt-service-device.h"
+#include "bt-service-util.h"
+#include "bt-service-event.h"
+#include "bt-service-otp.h"
+
+#define BT_OTP_SERVICE_NAME "org.projectx.otp"
+#define BT_OTP_OBJECT_PATH "/org/projectx/otp"
+#define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
+
+#define BT_OTP_BASE_DIR_PATH "/home/owner/media/otp/"
+
+static GDBusProxy *otp_gproxy;
+
+static GDBusProxy *_bt_core_gdbus_init_otp_proxy(void)
+{
+       GDBusProxy *proxy;
+       GError *err = NULL;
+       GDBusConnection *conn;
+
+       BT_DBG(" ");
+
+       conn = _bt_gdbus_get_system_gconn();
+       if (!conn)
+               return NULL;
+
+       proxy =  g_dbus_proxy_new_sync(conn,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       BT_OTP_SERVICE_NAME,
+                       BT_OTP_OBJECT_PATH,
+                       BT_OTP_INTERFACE_NAME,
+                       NULL, &err);
+       if (proxy == NULL) {
+               if (err) {
+                        BT_ERR("Unable to create proxy: %s", err->message);
+                        g_clear_error(&err);
+               }
+               return NULL;
+       }
+       BT_DBG("1");
+       otp_gproxy = proxy;
+
+       return proxy;
+}
+
+GDBusProxy *_bt_core_gdbus_get_otp_proxy(void)
+{
+       return (otp_gproxy) ? otp_gproxy : _bt_core_gdbus_init_otp_proxy();
+}
+
+void server_init_cb(GObject *object, GAsyncResult *res,
+                               gpointer user_data)
+{
+       BT_INFO("Server Init completed");
+       GError *error = NULL;
+       GVariant *result, *out_param, *param;
+       request_info_t *req_info = NULL;
+       int status = BLUETOOTH_ERROR_NONE;
+       bool server_state = false;
+
+       result = g_dbus_proxy_call_finish(otp_gproxy, res, &error);
+
+       if (result == NULL) {
+               BT_ERR("Dbus-RPC is failed\n");
+               if (error != NULL) {
+                       BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
+                               error->code, error->message);
+                       g_clear_error(&error);
+                       status = BLUETOOTH_ERROR_INTERNAL;
+               }
+       }
+
+       if (result) {
+               g_variant_get(result, "(i)", &status);
+       }
+
+       BT_DBG("Status [%d]", status);
+
+       if (status == BLUETOOTH_ERROR_NONE)
+               server_state = true;
+
+       param = g_variant_new("(ib)", status, server_state);
+
+       req_info = _bt_get_request_info(GPOINTER_TO_INT(user_data));
+
+       /* Send the event to application */
+       _bt_send_event(BT_OTP_EVENT,
+               BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED,
+               param);
+
+       out_param = g_variant_new_from_data((const GVariantType *)"i",
+                               result, sizeof(int), TRUE, NULL, NULL);
+
+       g_dbus_method_invocation_return_value(req_info->context,
+                               g_variant_new("(iv)", status, out_param));
+
+       _bt_delete_request_list(req_info->req_id);
+       g_variant_unref(result);
+}
+
+int bt_otp_server_init(int request_id, const char *directory)
+{
+       BT_INFO("relative_path: [%s]", directory);
+       char *base_dir = g_strconcat(BT_OTP_BASE_DIR_PATH, directory, NULL);
+
+       BT_DBG(" ");
+
+       otp_gproxy = _bt_core_gdbus_get_otp_proxy();
+       if (!otp_gproxy) {
+               BT_DBG("Couldn't get service proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       g_dbus_proxy_call(otp_gproxy,
+                       "enable",
+                       g_variant_new("(s)",
+                               base_dir),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL,
+                       (GAsyncReadyCallback) server_init_cb,
+                       GINT_TO_POINTER(request_id));
+
+       g_free(base_dir);
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+void server_deinit_cb(GObject *object, GAsyncResult *res,
+                               gpointer user_data)
+{
+       BT_INFO("Server Deinit completed");
+       GError *error = NULL;
+       GVariant *result, *out_param, *param;
+       request_info_t *req_info = NULL;
+       int status = BLUETOOTH_ERROR_NONE;
+       bool server_state = false;
+
+       result = g_dbus_proxy_call_finish(otp_gproxy, res, &error);
+
+       if (result == NULL) {
+               BT_ERR("Dbus-RPC is failed\n");
+               if (error != NULL) {
+                       BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n",
+                               error->code, error->message);
+                       g_clear_error(&error);
+                       status = BLUETOOTH_ERROR_INTERNAL;
+               }
+       }
+
+       if (result) {
+               g_variant_get(result, "(i)", &status);
+       }
+
+       BT_DBG("Status [%d]", status);
+
+       param = g_variant_new("(ib)", status, server_state);
+
+       req_info = _bt_get_request_info(GPOINTER_TO_INT(user_data));
+
+       /* Send the event to application */
+       _bt_send_event(BT_OTP_EVENT,
+               BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED,
+               param);
+
+       out_param = g_variant_new_from_data((const GVariantType *)"i",
+                               result, sizeof(int), TRUE, NULL, NULL);
+
+       g_dbus_method_invocation_return_value(req_info->context,
+                               g_variant_new("(iv)", status, out_param));
+
+       _bt_delete_request_list(req_info->req_id);
+       g_variant_unref(result);
+
+       if (otp_gproxy) {
+               g_object_unref(otp_gproxy);
+               otp_gproxy = NULL;
+       }
+}
+
+int bt_otp_server_deinit(int request_id)
+{
+       BT_DBG("+");
+
+       otp_gproxy = _bt_core_gdbus_get_otp_proxy();
+       if (!otp_gproxy) {
+               BT_DBG("Couldn't get service proxy");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       g_dbus_proxy_call(otp_gproxy,
+                       "disable",
+                       NULL, G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL,
+                       (GAsyncReadyCallback) server_deinit_cb,
+                       GINT_TO_POINTER(request_id));
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
diff --git a/bt-service/include/bt-service-otp.h b/bt-service/include/bt-service-otp.h
new file mode 100644 (file)
index 0000000..b952ec1
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _BT_SERVICE_OTP_SERVER_H_
+#define _BT_SERVICE_OTP_SERVER_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int bt_otp_server_init(int request_id, const char *directory);
+
+int bt_otp_server_deinit(int request_id);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /*_BT_SERVICE_OTP_SERVER_H_*/
index 1dac034..8adf067 100644 (file)
@@ -81,6 +81,11 @@ extern "C" {
 #define BLUETOOTH_TDS_DATA_LENGTH_MAX  239 /**< This specifies maximum AD data length: 0xEF */
 #define BLUETOOTH_TDS_CONTROL_POINT_PARAM_LENGTH_MAX   500 /**< TDS Control Point parameter Max length */
 
+/*
+ * < This defines the maximum size of OTP server directory name
+ */
+#define BLUETOOTH_MAX_OTP_SERVER_DIR_NAME 100
+
 /**
  * This is Bluetooth error code
  */
@@ -197,7 +202,7 @@ extern "C" {
 #define BLUETOOTH_ERROR_CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE 0x3d
 #define BLUETOOTH_ERROR_CONNECTION_FAILED_TO_BE_ESTABLISHED    0x3e
 
-
+#define BLUETOOTH_ERROR_INVALID_DIRECTORY 0x01
 
 /**
 * Device disconnect reason
@@ -798,6 +803,8 @@ typedef enum {
        BLUETOOTH_EVENT_TDS_ACTIVATION_RESULT,        /** TDS Activation Result */
        BLUETOOTH_EVENT_TDS_CONTROL_POINT_ENABLED,    /** TDS CCCD enabled event */
        BLUETOOTH_EVENT_TDS_ACTIVATION_INDICATION,    /** TDS Activation Indication from Provider */
+
+       BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED,       /* OTP Server Status **/
 } bluetooth_event_type_t;
 
  /**
@@ -7509,6 +7516,40 @@ int bluetooth_tds_activate_control_point(const bluetooth_device_address_t *devic
                                                unsigned char *buf, int length);
 
 /**
+ * @fn int bluetooth_otp_server_init(const char *directory);
+ *
+ * @brief Starts OTP server.
+ *
+ * This function is a synchronous call.
+ *
+ * @return
+ *
+ * @exception  None
+ * @param[in] None
+ * @param[out] None
+ *
+ * @remark     None
+ */
+int bluetooth_otp_server_init(const char *directory);
+
+/**
+ * @fn int bluetooth_otp_server_deinit();
+ *
+ * @brief Stops OTP server.
+ *
+ * This function is a synchronous call.
+ *
+ * @return
+ *
+ * @exception  None
+ * @param[in] None
+ * @param[out] None
+ *
+ * @remark     None
+ */
+int bluetooth_otp_server_deinit();
+
+/**
  * @}
  */
 
index 0283d7f..3992147 100644 (file)
@@ -66,6 +66,7 @@ typedef enum {
        BT_MAP_CLIENT_EVENT,
        BT_GATT_BLUEZ_EVENT, /* GattValueChanged from bluez directly */
        BT_TDS_EVENT,
+       BT_OTP_EVENT,
        /* Will be added */
 } bt_event_type_t;
 
@@ -134,6 +135,7 @@ typedef enum {
 #define BT_FUNC_PXP_BASE ((int)(BT_FUNC_DPM_BASE + 0x0030)) /* Adding 0x0030 to base, as DPM has more use case */
 #define BT_FUNC_MAP_BASE ((int)(BT_FUNC_PXP_BASE + 0x0020))
 #define BT_FUNC_TDS_BASE ((int)(BT_FUNC_MAP_BASE + 0x0020))
+#define BT_FUNC_OTP_BASE ((int)(BT_FUNC_TDS_BASE + 0x0020))
 
 typedef enum {
        BT_CHECK_ADAPTER = BT_FUNC_BASE,
@@ -379,6 +381,8 @@ typedef enum {
        BT_TDS_READ_TRANSPORT_DATA,
        BT_TDS_ENABLE_CONTROL_POINT,
        BT_TDS_ACTIVATE_CONTROL_POINT,
+       BT_OTP_SERVER_INIT = BT_FUNC_OTP_BASE,
+       BT_OTP_SERVER_DEINIT,
 } bt_function_t;
 
 typedef struct {
@@ -434,6 +438,7 @@ typedef struct {
 #define BT_A2DP_SOURCE_PATH "/org/projectx/bt/a2dp_source"
 #define BT_HID_DEVICE_PATH "/org/projectx/bt/hid_device"
 #define BT_TDS_PATH "/org/projectx/bt/tds"
+#define BT_OTP_PATH "/org/projectx/bt/otp"
 
 #define BT_ENABLED "Enabled"
 #define BT_DISABLED "Disabled"
@@ -554,6 +559,9 @@ typedef struct {
 #define BT_TDS_CONTROL_POINT_ENABLED   "TdsControlPointEnabled"
 #define BT_TDS_ACTIVATION_INDICATION   "TdsActivationIndication"
 
+/* OTP */
+#define BT_OTP_SERVER_STATE_CHANGED "OtpServerStateChanged"
+
 typedef enum {
        _PROFILE_UNKNOWN = 0,
        _PROFILE_MOBILE = 0x1,
index f90879d..76b29c1 100644 (file)
@@ -143,6 +143,14 @@ Requires:   %{name} = %{version}-%{release}
 %description httpproxy
 This package is Bluetooth HTTP Proxy Service daemon
 
+%package otp
+Summary:    Bluetooth OTP Service daemon
+Group:      Network & Connectivity/Bluetooth
+Requires:   %{name} = %{version}-%{release}
+
+%description otp
+This package is Bluetooth OTP Service daemon
+
 %package core
 Summary:    Bluetooth Core daemon
 Group:      Network & Connectivity/Bluetooth
@@ -363,6 +371,15 @@ popd
 %{_datadir}/dbus-1/system-services/org.projectx.httpproxy.service
 %{_sysconfdir}/dbus-1/system.d/bluetooth-frwk-httpproxy.conf
 
+
+%files otp
+%manifest %{name}.manifest
+%license LICENSE
+%defattr(-, root, root)
+%{_bindir}/bt-otp
+%{_datadir}/dbus-1/system-services/org.projectx.otp.service
+%{_sysconfdir}/dbus-1/system.d/bluetooth-frwk-otp.conf
+
 %files core
 %manifest %{name}.manifest
 %license LICENSE