From 759b6aa12863033f0f25d307b62597a829228160 Mon Sep 17 00:00:00 2001 From: Gowtham Anandha Babu Date: Tue, 28 Mar 2017 16:04:42 +0530 Subject: [PATCH] [Bluetooth][OTP] Add base code for OTP server role 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 --- CMakeLists.txt | 2 + bt-api/CMakeLists.txt | 4 +- bt-api/bt-common.c | 3 + bt-api/bt-event-handler.c | 44 +++++ bt-api/bt-otp.c | 80 ++++++++ bt-core/CMakeLists.txt | 1 + bt-core/bt-core-adapter.c | 4 + bt-core/bt-core-dbus-handler.c | 80 ++++++++ bt-core/include/bt-core-dbus-handler.h | 3 + bt-otp/CMakeLists.txt | 46 +++++ bt-otp/bluetooth-frwk-otp.conf | 14 ++ bt-otp/bt-otpserver.c | 329 +++++++++++++++++++++++++++++++++ bt-otp/bt-otpserver.h | 22 +++ bt-otp/org.projectx.otp.service | 4 + bt-service/CMakeLists.txt | 2 + bt-service/bt-request-handler.c | 15 ++ bt-service/bt-service-common.c | 2 +- bt-service/bt-service-event-sender.c | 6 + bt-service/bt-service-otp.c | 227 +++++++++++++++++++++++ bt-service/include/bt-service-otp.h | 36 ++++ include/bluetooth-api.h | 43 ++++- include/bt-internal-types.h | 8 + packaging/bluetooth-frwk.spec | 17 ++ 23 files changed, 989 insertions(+), 3 deletions(-) create mode 100644 bt-api/bt-otp.c create mode 100644 bt-otp/CMakeLists.txt create mode 100644 bt-otp/bluetooth-frwk-otp.conf create mode 100644 bt-otp/bt-otpserver.c create mode 100755 bt-otp/bt-otpserver.h create mode 100644 bt-otp/org.projectx.otp.service create mode 100644 bt-service/bt-service-otp.c create mode 100644 bt-service/include/bt-service-otp.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f616072..ec41c20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ ENDIF() ADD_SUBDIRECTORY(bt-httpproxy) +ADD_SUBDIRECTORY(bt-otp) + ADD_SUBDIRECTORY(bt-core) ADD_SUBDIRECTORY(plugin) diff --git a/bt-api/CMakeLists.txt b/bt-api/CMakeLists.txt index 32024cd..8ec4d16 100644 --- a/bt-api/CMakeLists.txt +++ b/bt-api/CMakeLists.txt @@ -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) diff --git a/bt-api/bt-common.c b/bt-api/bt-common.c index d46ec6d..3839810 100644 --- a/bt-api/bt-common.c +++ b/bt-api/bt-common.c @@ -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(); diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c index 8f7a64a..a354dce 100644 --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -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 index 0000000..f10d0d7 --- /dev/null +++ b/bt-api/bt-otp.c @@ -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 diff --git a/bt-core/CMakeLists.txt b/bt-core/CMakeLists.txt index 1bbf1cc..acaddb4 100644 --- a/bt-core/CMakeLists.txt +++ b/bt-core/CMakeLists.txt @@ -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") diff --git a/bt-core/bt-core-adapter.c b/bt-core/bt-core-adapter.c index 1860931..f42caa9 100644 --- a/bt-core/bt-core-adapter.c +++ b/bt-core/bt-core-adapter.c @@ -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); diff --git a/bt-core/bt-core-dbus-handler.c b/bt-core/bt-core-dbus-handler.c index 34c34c7..41f15b0 100644 --- a/bt-core/bt-core-dbus-handler.c +++ b/bt-core/bt-core-dbus-handler.c @@ -35,12 +35,22 @@ #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; diff --git a/bt-core/include/bt-core-dbus-handler.h b/bt-core/include/bt-core-dbus-handler.h index dfaef71..25d0bed 100755 --- a/bt-core/include/bt-core-dbus-handler.h +++ b/bt-core/include/bt-core-dbus-handler.h @@ -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 index 0000000..eb3a814 --- /dev/null +++ b/bt-otp/CMakeLists.txt @@ -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 index 0000000..537575f --- /dev/null +++ b/bt-otp/bluetooth-frwk-otp.conf @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/bt-otp/bt-otpserver.c b/bt-otp/bt-otpserver.c new file mode 100644 index 0000000..b2c0f0d --- /dev/null +++ b/bt-otp/bt-otpserver.c @@ -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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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[] = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +""; + +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 index 0000000..046c808 --- /dev/null +++ b/bt-otp/bt-otpserver.h @@ -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 index 0000000..0143eef --- /dev/null +++ b/bt-otp/org.projectx.otp.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.projectx.otp +Exec=/usr/bin/bt-otp +User=root diff --git a/bt-service/CMakeLists.txt b/bt-service/CMakeLists.txt index a5007c3..a7290c6 100644 --- a/bt-service/CMakeLists.txt +++ b/bt-service/CMakeLists.txt @@ -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") diff --git a/bt-service/bt-request-handler.c b/bt-service/bt-request-handler.c index 08cb882..2a3275f 100644 --- a/bt-service/bt-request-handler.c +++ b/bt-service/bt-request-handler.c @@ -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: diff --git a/bt-service/bt-service-common.c b/bt-service/bt-service-common.c index 44d7679..32f8ce8 100644 --- a/bt-service/bt-service-common.c +++ b/bt-service/bt-service-common.c @@ -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 */ - #if 0 +#if 0 bundle *b = NULL; b = bundle_create(); diff --git a/bt-service/bt-service-event-sender.c b/bt-service/bt-service-event-sender.c index a7d3328..158e910 100644 --- a/bt-service/bt-service-event-sender.c +++ b/bt-service/bt-service-event-sender.c @@ -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 index 0000000..432454e --- /dev/null +++ b/bt-service/bt-service-otp.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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 index 0000000..b952ec1 --- /dev/null +++ b/bt-service/include/bt-service-otp.h @@ -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 +#include +#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_*/ diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h index 1dac034..8adf067 100644 --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -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(); + +/** * @} */ diff --git a/include/bt-internal-types.h b/include/bt-internal-types.h index 0283d7f..3992147 100644 --- a/include/bt-internal-types.h +++ b/include/bt-internal-types.h @@ -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, diff --git a/packaging/bluetooth-frwk.spec b/packaging/bluetooth-frwk.spec index f90879d..76b29c1 100644 --- a/packaging/bluetooth-frwk.spec +++ b/packaging/bluetooth-frwk.spec @@ -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 -- 2.7.4