From db8a8d06d4b555be2f0ec97eed0cb37b8871ee80 Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Tue, 13 Feb 2018 17:53:05 +0900 Subject: [PATCH 01/16] Fix build failure Change-Id: I98763329e3bdf4bcfc8971188be80caaee6a7df2 Signed-off-by: Hyotaek Shim --- packaging/feedbackd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index fbffb0d..7526934 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -329,6 +329,6 @@ mv %{_sysconfdir}/feedbackd/haptic-level6.conf %{_sysconfdir}/feedbackd/haptic.c %config %{_sysconfdir}/feedbackd/haptic-level6.conf %files auto-test -%license LICENSE +%license LICENSE.Apache-2.0 %manifest %{name}.manifest %{_bindir}/feedbackd-auto-test -- 2.7.4 From 1a90db017ff25ec11b0babc0228cf1d1b01bc739 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Thu, 22 Feb 2018 14:52:50 +0900 Subject: [PATCH 02/16] haptic: Change g_timeout_add_seconds to g_timeout_add - g_timeout_add interval is in milliseconds - g_timeout_add_seconds interval is in seconds Change-Id: Ide64c518d1249bd4861e5749a8e5122fadf71166 Signed-off-by: pr.jung --- src/haptic/circle.c | 2 +- src/haptic/gpio_haptic.c | 2 +- src/haptic/standard-mix.c | 8 ++++---- src/haptic/standard-vibcore.c | 4 ++-- src/haptic/standard.c | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index 6555d40..1b63660 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -220,7 +220,7 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p /* register timer */ if (duration) { - stop_timer = g_timeout_add_seconds(duration/1000, timer_cb, (void *)(long)device_handle); + stop_timer = g_timeout_add(duration, timer_cb, (void *)(long)device_handle); if (!stop_timer) _E("Failed to add timer callback"); diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index c44e768..45ffdac 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -248,7 +248,7 @@ static int gpio_haptic_vibrate_monotone(int handle, int duration, int level, int /* register timer */ if (duration) { //stop_timer = ecore_timer_add(duration/1000.f, gpio_haptic_timer_cb, (void *)(long)handle); - stop_timer = g_timeout_add_seconds(duration/1000, gpio_haptic_timer_cb, (void *)(long)handle); + stop_timer = g_timeout_add(duration, gpio_haptic_timer_cb, (void *)(long)handle); if (!stop_timer) _E("Failed to add timer callback"); } diff --git a/src/haptic/standard-mix.c b/src/haptic/standard-mix.c index a234ec7..578a700 100644 --- a/src/haptic/standard-mix.c +++ b/src/haptic/standard-mix.c @@ -488,7 +488,7 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p /* register timer */ if (duration) { - info->timer = g_timeout_add_seconds(duration/1000, timer_cb, info); + info->timer = g_timeout_add(duration, timer_cb, info); if (!info->timer) _E("Failed to add timer callback"); } @@ -525,12 +525,12 @@ static gboolean _buffer_play(void *cbdata) if (info->currentindex < header->ff_info_data_count) { info->currentindex++; - info->timer = g_timeout_add_seconds(length/1000, _buffer_play, info); + info->timer = g_timeout_add(length, _buffer_play, info); } else { --header->iteration; if (header->iteration > 0) { info->currentindex = 0; - info->timer = g_timeout_add_seconds(0, _buffer_play, info); + info->timer = g_timeout_add(0, _buffer_play, info); } else info->timer = NULL; } @@ -642,7 +642,7 @@ static gboolean haptic_duration_play(void *data) time = duration + h_data->waiting_config[index]; /*duration_timer = ecore_timer_add(time/1000.0f, haptic_duration_play, (void *)h_data);*/ - duration_timer = g_timeout_add_seconds(time/1000, haptic_duration_play, (void *)h_data); + duration_timer = g_timeout_add(time, haptic_duration_play, (void *)h_data); _D("timer: %d", time); } diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 7361bb2..f8982c9 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -197,9 +197,9 @@ static gboolean haptic_duration_play(void *data) if (next) { h_data->vibration_data = next; - duration_timer = g_timeout_add_seconds((node->duration + node->wait)/1000, haptic_duration_play, (void *)h_data); + duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)h_data); } else - duration_timer = g_timeout_add_seconds((node->duration + node->wait)/1000, haptic_duration_play, NULL); + duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, NULL); ret = real_vibrate_monotone(h_data->handle, node->duration, h_data->level, h_data->priority, NULL); if (!next) diff --git a/src/haptic/standard.c b/src/haptic/standard.c index 39f6866..6a42bd1 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -452,7 +452,7 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p /* register timer */ if (duration) { - info->timer = g_timeout_add_seconds(duration/1000, timer_cb, info); + info->timer = g_timeout_add(duration, timer_cb, info); if (!info->timer) _E("Failed to add timer callback"); } @@ -489,12 +489,12 @@ static gboolean _buffer_play(void *cbdata) if (info->currentindex < header->ff_info_data_count) { info->currentindex++; - info->timer = g_timeout_add_seconds(length/1000, _buffer_play, info); + info->timer = g_timeout_add(length, _buffer_play, info); } else { --header->iteration; if (header->iteration > 0) { info->currentindex = 0; - info->timer = g_timeout_add_seconds(0, _buffer_play, info); + info->timer = g_timeout_add(0, _buffer_play, info); } else info->timer = 0; } -- 2.7.4 From 92f2f8ad90387eed109b3c03f9aacca094786cbf Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Tue, 6 Mar 2018 11:12:55 +0900 Subject: [PATCH 03/16] dbus: modify dbus policy correctly Change-Id: I64eb9361c4f5ad7c3dc418ab927b53afcce589a7 Signed-off-by: sanghyeok.oh --- scripts/feedbackd.conf | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/feedbackd.conf b/scripts/feedbackd.conf index d17e13a..05f4ece 100755 --- a/scripts/feedbackd.conf +++ b/scripts/feedbackd.conf @@ -1,12 +1,21 @@ + - - - + + + + + + + + + + + + send_path="/Org/Tizen/System/Vibrator/Haptic" + privilege="http://tizen.org/privilege/haptic"/> -- 2.7.4 From f533c93a6de4df28c9c58287bb17af5eab53791a Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Wed, 21 Mar 2018 17:22:14 +0900 Subject: [PATCH 04/16] libgdbus: Move common gdbus interfaces to libsystem package Change-Id: I17034bb99d971a75a0a770861596c33f9cfbdc73 Signed-off-by: pr.jung --- CMakeLists.txt | 2 +- packaging/feedbackd.spec | 2 +- src/auto-test/CMakeLists.txt | 1 - src/auto-test/haptic.c | 14 +- src/auto-test/test.c | 1 + src/auto-test/test.h | 6 +- src/core/dbus.c | 2521 ------------------------------------------ src/core/dbus.h | 234 ---- src/core/edbus-handler.h | 1 - src/core/main.c | 4 +- src/haptic/haptic.c | 9 +- 11 files changed, 21 insertions(+), 2774 deletions(-) delete mode 100644 src/core/dbus.c delete mode 100644 src/core/dbus.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 55c3880..b2c4c8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,6 @@ SET(SRCS src/core/config-parser.c src/core/device-idler.c src/core/log.c - src/core/dbus.c src/haptic/haptic.c ) @@ -41,6 +40,7 @@ SET(PKG_MODULES gio-2.0 gio-unix-2.0 capi-system-info + libgdbus ) IF(DRIVER STREQUAL gpio) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index 7526934..c87d08a 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -18,12 +18,12 @@ BuildRequires: cmake BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(capi-base-common) -BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gio-unix-2.0) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-peripheral-io) +BuildRequires: pkgconfig(libgdbus) Requires(post): /usr/bin/vconftool diff --git a/src/auto-test/CMakeLists.txt b/src/auto-test/CMakeLists.txt index 5e40bd7..5547560 100644 --- a/src/auto-test/CMakeLists.txt +++ b/src/auto-test/CMakeLists.txt @@ -7,7 +7,6 @@ SET(SRCS test.c main.c result.c - ../core/dbus.c haptic.c ) diff --git a/src/auto-test/haptic.c b/src/auto-test/haptic.c index 7171d38..004d72a 100755 --- a/src/auto-test/haptic.c +++ b/src/auto-test/haptic.c @@ -33,7 +33,7 @@ static bool request_haptic_method(const char *method, GVariant *param) int val; bool ret = FALSE; - msg = dbus_method_sync_with_reply_var(VIBRATOR_BUS_NAME, + msg = dbus_handle_method_sync_with_reply_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, method, param); @@ -82,7 +82,7 @@ static bool haptic_closedevice() bool ret = FALSE; _D("----------------------------------------------------------------------------------"); - msg = dbus_method_sync_with_reply_var(VIBRATOR_BUS_NAME, + msg = dbus_handle_method_sync_with_reply_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, METHOD_HAPTIC_OPENDEVICE, @@ -109,7 +109,7 @@ static bool haptic_vibratemonotone(int duration, int level, int priority) bool ret = FALSE; _D("----------------------------------------------------------------------------------"); - msg = dbus_method_sync_with_reply_var(VIBRATOR_BUS_NAME, + msg = dbus_handle_method_sync_with_reply_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, METHOD_HAPTIC_OPENDEVICE, @@ -136,7 +136,7 @@ static bool haptic_vibrateeffect(char *pattern, int level, int priority) bool ret = FALSE; _D("----------------------------------------------------------------------------------"); - msg = dbus_method_sync_with_reply_var(VIBRATOR_BUS_NAME, + msg = dbus_handle_method_sync_with_reply_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, METHOD_HAPTIC_OPENDEVICE, @@ -164,7 +164,7 @@ static bool haptic_stopdevice() bool ret = FALSE; _D("----------------------------------------------------------------------------------"); - msg = dbus_method_sync_with_reply_var(VIBRATOR_BUS_NAME, + msg = dbus_handle_method_sync_with_reply_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, METHOD_HAPTIC_OPENDEVICE, @@ -181,7 +181,7 @@ static bool haptic_stopdevice() } g_variant_unref(msg); - msg = dbus_method_sync_with_reply_var(VIBRATOR_BUS_NAME, + msg = dbus_handle_method_sync_with_reply_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, METHOD_HAPTIC_VIBRATEMONOTONE, @@ -211,7 +211,7 @@ static bool haptic_showhandlelist() GVariant *msg; _D("----------------------------------------------------------------------------------"); - msg = dbus_method_sync_with_reply_var(VIBRATOR_BUS_NAME, + msg = dbus_handle_method_sync_with_reply_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, METHOD_HAPTIC_SHOWHANDLELIST, diff --git a/src/auto-test/test.c b/src/auto-test/test.c index 15f27be..bf0985c 100644 --- a/src/auto-test/test.c +++ b/src/auto-test/test.c @@ -16,6 +16,7 @@ * limitations under the License. */ +#include #include "test.h" static dd_list *dd_head; diff --git a/src/auto-test/test.h b/src/auto-test/test.h index e5d5801..4454d1a 100644 --- a/src/auto-test/test.h +++ b/src/auto-test/test.h @@ -17,14 +17,14 @@ */ -#ifndef __TEST_H__ -#define __TEST_H__ +#ifndef FEEDBACKD__TEST_H__ +#define FEEDBACKD__TEST_H__ #include #include +#include #include "core/list.h" #include "core/log.h" -#include "core/dbus.h" #include "core/common.h" #ifdef ENABLE_TEST_DLOG diff --git a/src/core/dbus.c b/src/core/dbus.c deleted file mode 100644 index 42137a7..0000000 --- a/src/core/dbus.c +++ /dev/null @@ -1,2521 +0,0 @@ -/* - * feedbackd - * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. - * - * 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 "core/log.h" -#include "core/common.h" -#include "dbus.h" - -/* -1 is a default timeout value, it's converted to 25*1000 internally. */ -#define DBUS_REPLY_TIMEOUT (-1) - -static GBusType g_default_bus_type = G_BUS_TYPE_SYSTEM; -pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; - -void dbus_handle_set_default_bus_type(GBusType bus_type) -{ - if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) - return ; - - pthread_mutex_lock(&g_mutex); - g_default_bus_type = bus_type; - pthread_mutex_unlock(&g_mutex); -} - -GBusType dbus_handle_get_default_bus_type(void) -{ - GBusType type; - - pthread_mutex_lock(&g_mutex); - type = g_default_bus_type; - pthread_mutex_unlock(&g_mutex); - - return type; -} - -typedef struct { - const char *bus_name; - guint id; -} dbus_name; - -/* basic information */ -typedef struct { - GDBusConnection *conn; - GBusType bus_type; - gboolean priv; - GList *list_names; // dbus_name - GList *list_object; /* dbus_object_handle_s */ - pthread_mutex_t mutex;// = PTHREAD_MUTEX_INITIALIZER; -} dbus_handle_s; - -/* path + interfaces */ -typedef struct { - dbus_handle_s *dh; /* dbus handle */ - const char *path; - GList *list_ifaces; /* dbus_interface_s */ -} dbus_object_handle_s; - -typedef struct { - dbus_object_handle_s *oh; - const char *name; - GList *list_methods; // const dbus_method_s; - guint reg_id; - int modified; -} dbus_interface_s; - -#define get_dh_from_oh(oh) ((dbus_object_handle_s*)oh)->dh - -static dbus_handle_s g_dh[2]; - -static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type); - -dbus_handle_s * _dbus_handle_get_default_connection(void) -{ - return _dbus_handle_get_connection(dbus_handle_get_default_bus_type()); -} - -#define dbus_handle_lock(handle) do {\ - assert(handle);\ - pthread_mutex_lock(&((handle)->mutex));\ -} while (0); - -#define dbus_handle_unlock(handle) do {\ - assert(handle);\ - pthread_mutex_unlock(&(handle)->mutex);\ -} while (0); - -#define dcl_dbus_handle() dbus_handle_s *dh = (dbus_handle_s *)handle; -#define dcl_dbus_handle_null_check() dbus_handle_s *dh = (dbus_handle_s *)handle;\ - if (!dh) {\ - _E("dbus handle is null\n");\ - return 0;\ - } - -dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path); -dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name); -dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name); -static GVariant* _append_variant(const char *signature, const char *param[]); - -dbus_interface_s *_iface_u_to_s(const dbus_interface_u *iface_u) -{ - dbus_interface_s *iface = NULL; - - if (!iface_u || !iface_u->methods) { - _E("param is null"); - return NULL; - } - - iface = (dbus_interface_s *)calloc(1, sizeof(dbus_interface_s)); - if (!iface) { - _E("failed to calloc"); - return NULL; - } - - iface->name = iface_u->name; - iface->modified = TRUE; - - for (int i = 0 ; i < iface_u->nr_methods; ++i) { - //_D("attached %s:%p", iface_u->methods[i].member, iface_u->methods[i].func); - iface->list_methods = g_list_prepend(iface->list_methods, (void*)(iface_u->methods + i)); - } - - return iface; -} - -static GDBusConnection * _get_bus(GBusType bus_type) -{ - GDBusConnection *conn = NULL; - GError *err = NULL; - - if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { - _E("Wrong bus_type %d", bus_type); - return NULL; - } - - conn = g_bus_get_sync(bus_type, NULL, &err); - if (!conn || err) { - _E("failed to get bus:type:%d, %s\n", bus_type, err->message); - g_error_free(err); - return NULL; - } - - return conn; -} - -static GDBusConnection * _get_bus_private(GBusType bus_type) -{ - GError *err = NULL; - GDBusConnection *conn = NULL; - const char * address; - - if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { - _E("Wrong bus_type %d", bus_type); - return NULL; - } - - address = g_dbus_address_get_for_bus_sync(bus_type, NULL, &err); - if (!address || err) { - _E("failed to get bus address\n"); - g_error_free(err); - return NULL; - } - - conn = g_dbus_connection_new_for_address_sync(address, - (GDBusConnectionFlags) (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | - G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), - NULL, /* GDBusAuthObserver */ - NULL, - &err); - if (!conn || err) { - _E("failed to get private bus\n"); - g_error_free(err); - return NULL; - } - - return conn; -} - -/* ref cout is 1 */ -static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type) -{ - int ibus = bus_type - 1; - dbus_handle_s *dh = NULL; - - if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { - _E("Unknown bus type %d", bus_type); - return NULL; - } - dh = &g_dh[ibus]; - - dbus_handle_lock(dh); - - if (!dh->conn) { - dh->conn = _get_bus(bus_type); - dh->priv = FALSE; - dh->bus_type = bus_type; - if (!dh->conn) - dh = NULL; - } - - dbus_handle_unlock(dh); - - return dh; -} - -/* ref cout is 1 */ -static dbus_handle_s *_dbus_handle_get_connection_private(GBusType bus_type) -{ - dbus_handle_s * dh; - - if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { - _E("Unknown bus type %d", bus_type); - return NULL; - } - - dh = (dbus_handle_s *)calloc(1, sizeof(dbus_handle_s)); - if (!dh) { - _E("failed to allocate memory for dbus handle"); - return NULL; - } - - dbus_handle_lock(dh); - - if (!dh->conn) { - dh->conn = _get_bus_private(bus_type); - dh->bus_type = bus_type; - if (!dh->conn) - goto err; - } - - dbus_handle_unlock(dh); - - return dh; -err: - if (dh) { - dbus_handle_unlock(dh); - free(dh); - } - return NULL; -} - -dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv) -{ - dbus_handle_s *dh = NULL; - - if (bus_type != G_BUS_TYPE_SYSTEM && bus_type != G_BUS_TYPE_SESSION) { - _E("Wrong bus_type %d\n", bus_type); - return dh; - } - - /* private */ - if (priv) - dh = _dbus_handle_get_connection_private(bus_type); - /* shared */ - else - dh = _dbus_handle_get_connection(bus_type); - - return dh; -} - -static void _dbus_handle_add_bus_name(dbus_handle_s *handle, const char *name, guint id) -{ - dbus_name *dn = NULL; - int locked = 0; - - if (!handle || !name || !id) - return ; - - dn = (dbus_name*)calloc(1, sizeof(dbus_name)); - if (!dn) { - _E("failed to calloc"); - assert(0); - } - dn->bus_name = name; - dn->id = id; - - // todo : delete lock ? - locked = pthread_mutex_trylock(&handle->mutex); - if (locked != 0 && locked != EBUSY) { - _E("failed to lock %d\n", locked); - assert(0); - } - - handle->list_names = g_list_prepend(handle->list_names, dn); - - // todo : delete lock ? - if (locked != EBUSY) - dbus_handle_unlock(handle); -} - -static gint _compare_dbus_name(gconstpointer a, gconstpointer b) -{ - const char *bus_name = ((dbus_name *)a)->bus_name; - if (!bus_name || !b) - return -1; - return strcmp(bus_name, (const char *)b); -} - -dbus_name * _dbus_handle_lookup_dbus_name(GList *list_name, const char *bus_name) -{ - if (!list_name || !bus_name) - return NULL; - - GList *item = g_list_find_custom(list_name, bus_name, _compare_dbus_name); - if (!item) - return NULL; - - return (dbus_name *)item->data; -} - -#define dh_to_ds(x) ((dbus_handle_s*)x) - -/* remove dbus_name from dbus handle */ -static void _dbus_handle_remove_bus_name(dbus_handle_s *handle, const char *bus_name) -{ - dcl_dbus_handle(); - dbus_name *dn = NULL; - - if (!bus_name) { - _E("wrong bus_name %s", bus_name); - return ; - } - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return ; - } - } - - dbus_handle_lock(dh); - dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name); - if (!dn) { - _E("failed to find dbus name %s", bus_name); - goto out; - } - dh->list_names = g_list_remove(dh->list_names, dn); - free(dn); -out: - dbus_handle_unlock(dh); -} - -static void _name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) -{ - dbus_handle_s *dh = (dbus_handle_s *)user_data; - - _D("name %s", name); - - if (!dh) { - _E("%s:%d:dbus handle is null\n", __func__, __LINE__); - return ; - } - // todo: add bus name? - //dh->bus_name = name; -} - -static void _name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data) -{ - _E("%s:%d:%s\n", __func__, __LINE__, name); - dbus_handle_s *dh = (dbus_handle_s *)user_data; - if (!dh) { - _E("%s:%d:dbus handle is null\n", __func__, __LINE__); - return ; - } - _dbus_handle_remove_bus_name(dh, name); -} - -int dbus_handle_request_bus_name(dbus_handle_h handle, const char *bus_name) -{ - dcl_dbus_handle(); - int id = -1; - GList *item = NULL; - - if (!bus_name) { - _E("bus_name is NULL"); - return -1; - } - - /* get shared connection */ - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - - dbus_handle_lock(dh); - if (!dh->conn) { - _E("failed to register name: connection is null\n"); - goto out; - } - - /* todo : search name on connection */ - item = g_list_find_custom(dh->list_names, bus_name, _compare_dbus_name); - if (item) { - id = ((dbus_name*)(item->data))->id; - _E("name already exist:%u", id); - goto out; - } - - id = g_bus_own_name_on_connection(dh->conn, bus_name, G_BUS_NAME_OWNER_FLAGS_NONE, _name_acquired, _name_lost, dh, NULL); - if (!id) { - _E("failed to own name:%s\n", bus_name); - goto out; - } - - _dbus_handle_add_bus_name(dh, bus_name, id); - -out: - dbus_handle_unlock(dh); - return id; -} - -int dbus_handle_release_bus_name(dbus_handle_h handle, const char *bus_name) -{ - dcl_dbus_handle(); - dbus_name *dn = NULL; - - if (!bus_name) { - _E("Wrong bus name"); - return -1; - } - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - - dn = _dbus_handle_lookup_dbus_name(dh->list_names, bus_name); - if (!dn) { - _E("failed to find bus_name %s on dbus handle", bus_name); - return -1; - } - - _E("unown name %d", dn->id); - /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */ - g_bus_unown_name(dn->id); - - dbus_handle_lock(dh); - dh->list_names = g_list_remove(dh->list_names, dn); - free(dn); - dbus_handle_unlock(dh); - - return 0; -} - -int dbus_handle_free_connection(dbus_handle_h handle) -{ - dcl_dbus_handle(); - dbus_handle_s *pdh = NULL; - GError *err = NULL; - GList *item = NULL; - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - - if (!dh->conn) { - _E("connection is NULL"); - return 0; - } - - pdh = dh; - - /* disable dbus handler */ - dbus_handle_lock(dh); - if (!pdh->conn) { - _E("conn is null"); - free(pdh); - return 0; - } - - /* flush everything */ - if (!g_dbus_connection_flush_sync(pdh->conn, NULL, &err)) { - _E("failed to flush %s\n", err->message); - g_error_free(err); - err = NULL; - } - - _D("list_names %u", g_list_length(pdh->list_names)); - - /* unown every well-knwon name */ - if (pdh->list_names) { - dbus_name *dn = NULL; - for (item = g_list_first(pdh->list_names); item != NULL; item = g_list_next(item)) { - dn = (dbus_name *)item->data; - if (!dn) - continue; - - /* _name_lost handler is disabled by g_bus_unown_name : ubuntu */ - _D("unown name id : %u", dn->id); - g_bus_unown_name(dn->id); - free(dn); - } - g_list_free(pdh->list_names); - pdh->list_names = NULL; - } - - _D("list_object %u", g_list_length(pdh->list_object)); - - /* unregister every object */ - if (pdh->list_object) { - dbus_object_handle_s * oh = NULL; - //g_list_foreach(pdh->list_object, [] (gpointer data, gpointer user_data){}, NULL); - for (item = g_list_first(pdh->list_object); item != NULL; item = g_list_next(item)) { - oh = (dbus_object_handle_s *)item->data; - if (!oh || !oh->list_ifaces) - continue; - - _D("delete object path %s", oh->path); - - /* unregister every interface, method handles */ - for (GList *iface = g_list_first(oh->list_ifaces); iface != NULL; iface = g_list_next(iface)) { - dbus_interface_s *ih = (dbus_interface_s *)iface->data; - if (!ih) - continue; - - _D("delete object iface %s", ih->name); - - if (ih->reg_id) - g_dbus_connection_unregister_object(pdh->conn, ih->reg_id); - } - } - } - - /* close connection */ - if (pdh->priv) { - _E("close private connection\n"); - - if (!g_dbus_connection_close_sync(pdh->conn, NULL, &err)) { - _E("Error closing connection %s\n", err->message); - g_error_free(err); - err = NULL; - } - } - - /* _free_func_object callback free the data */ - //assert(g_list_length(pdh->list_names) == 0); - //assert(g_list_length(pdh->list_object) == 0); - - g_object_unref(pdh->conn); - - dbus_handle_unlock(dh); - - if (dh->priv) - free(dh); - - return 0; - - // todo: signal ? -} - -#define buf_cal_free_space(size, nwrite) ((size - nwrite - 1) > 0 ? (size - nwrite - 1) : 0) -#define buf_block_size 8192 - -#define buf_check_space_realloc(buf, nwrite, buf_len) do {\ - if ((nwrite >= buf_len - 1024)) {\ - if (buf_len >= buf_block_size * 10) {\ - _E("buf is too big to allocate. %d", buf_len);\ - } else {\ - _E("buf_check_space_realloc");\ - char *tmp = NULL;\ - buf_len += buf_block_size;\ - tmp = (char *)realloc(buf, buf_len);\ - if (!tmp) {\ - _E("failed to realloc");\ - } else\ - buf = tmp;\ - } \ - } \ -} while (0); - -static int _check_brace(const char * expr) -{ - int len = 0; - char qu[128]; - int qucnt = 0; - - if (!expr) - return -1; - - len = strlen(expr); - - if (expr[0] != '(' && expr[0] != '{') - return -1; - - for (int i = 0 ; i < len; ++i) { - - if (expr[i] == '(' || expr[i] == '{') { - qu[qucnt++] = expr[i]; - if (qucnt >= sizeof(qu)) { - _E("queue is too large. %s", expr); - return -1; - } - continue; - } - - if (expr[i] == ')' || expr[i] == '}') { - char ch; - - if (qucnt > 0) - ch = qu[qucnt-1]; - else - return -1; - - if (expr[i] == ')') { - if (ch == '(') { - --qucnt; - } else - return -1; - } else if (expr[i] == '}') { - if (ch == '{') { - --qucnt; - } else - return -1; - } else - return -1; - - if (qucnt == 0) { - return i + 1; - } - } - } - - return -1; -} - -static int _get_xml_from_interfaces(char **xml, const dbus_interface_s *interfaces) -{ - int nwrite = 0; - int len_args; - char *buf = NULL; - const dbus_method_s *pmethod; - int buf_len = buf_block_size; - - if (!interfaces) { - _E("interfaces is null"); - return -1; - } - - // todo : check dbus naming rule for interface name. ? - if (!interfaces->name) { - _E("wrong interface name"); - return -1; - } - if (!interfaces->list_methods) { - _E("no methods"); - return -1; - } - - buf = (char *)malloc(buf_len); - if (!buf) { - _E("buf is null. not enough memory\n"); - return -1; - } - - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), """\n""\t""""\n", interfaces->name); - - /* members */ - for (GList *item = g_list_first(interfaces->list_methods); item != NULL; item = g_list_next(item)) { - pmethod = (const dbus_method_s *)item->data; - if (!pmethod) - continue; - - /* check free space of buf */ - buf_check_space_realloc(buf, nwrite, buf_len); - - if (pmethod->signature_in == NULL && pmethod->signature_out == NULL) { - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""""\n", pmethod->member); - continue; - } - - /* */ - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""""\n", pmethod->member); - - /* in args */ - len_args = pmethod->signature_in ? strlen(pmethod->signature_in) : 0; - for (int m = 0; m < len_args; ++m) { - // todo - // array a(), as, ay ? - if (pmethod->signature_in[m] == 'a') { - int ei; //end index - ei = _check_brace(pmethod->signature_in + m + 1); - if (ei > 0) { - char tmp[128] = {0,}; - strncpy(tmp, pmethod->signature_in + m, ei + 1); - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", tmp, m); - m += ei; - continue; - } else { - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_in[m], pmethod->signature_in[m+1], m); - m += 1; - continue; - } - } - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_in[m], m); - } - - /* out args */ - len_args = pmethod->signature_out ? strlen(pmethod->signature_out) : 0; - for (int m = 0; m < len_args; ++m) { - // array - // todo: container type - if (pmethod->signature_out[m] == 'a') { - int ei; //end index - ei = _check_brace(pmethod->signature_out + m + 1); - if (ei > 0) { - char tmp[128] = {0,}; - strncpy(tmp, pmethod->signature_out + m, ei + 1); - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", tmp, m); - m += ei; - continue; - } else { - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_out[m], pmethod->signature_out[m+1], m); - m += 1; - continue; - } - } - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""""\n", pmethod->signature_out[m], m); - } - - /* */ - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""""\n"); - } - - nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t""""\n"""""); - - *xml = buf; - - return 0; -} - -static gint _compare_dbus_object(gconstpointer a, gconstpointer b) -{ - dbus_object_handle_s * pa = (dbus_object_handle_s *)a; - if (!pa->path || !((const char*)b)) - return -1; - return strcmp(pa->path, (const char*)b); -} - -static gint _compare_dbus_interface(gconstpointer a, gconstpointer b) -{ - dbus_interface_s * pa = (dbus_interface_s *)a; - if (!pa->name || !((const char*)b)) - return -1; - return strcmp(pa->name, (const char*)b); -} - -static gint _compare_dbus_interface_by_id(gconstpointer a, gconstpointer b) -{ - dbus_interface_s * pa = (dbus_interface_s *)a; - if (!pa->reg_id || !((guint*)b)) - return -1; - return !(pa->reg_id == *((guint*)b)); -} - -static gint _compare_dbus_method(gconstpointer a, gconstpointer b) -{ - dbus_method_s *pa = (dbus_method_s*)a; - if (!pa->member || !((const char*)b)) - return -1; - return strcmp(pa->member, (const char*)b); -} - -dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path) -{ - if (!list_obj || !obj_path) - return NULL; - - GList *item = g_list_find_custom(list_obj, obj_path, _compare_dbus_object); - if (!item) - return NULL; - - return (dbus_object_handle_s *)item->data; -} - -dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name) -{ - if (!list_iface || !iface_name) - return NULL; - - GList *item = g_list_find_custom(list_iface, iface_name, _compare_dbus_interface); - if (!item) - return NULL; - - return (dbus_interface_s *)item->data; -} - -dbus_interface_s * _dbus_handle_lookup_interface_by_id(GList *list_iface, guint id) -{ - if (!list_iface || !id) - return NULL; - - GList *item = g_list_find_custom(list_iface, &id, _compare_dbus_interface_by_id); - if (!item) - return NULL; - - return (dbus_interface_s *)item->data; -} - -dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name) -{ - if (!list_methods || !method_name) - return NULL; - - GList *item = g_list_find_custom(list_methods, method_name, _compare_dbus_method); - if (!item) - return NULL; - - return (dbus_method_s *)item->data; -} - -static void _free_func_object(gpointer data) -{ - dbus_interface_s *ih = (dbus_interface_s *)data; - dbus_object_handle_s *oh = NULL; - - if (!ih) { - _E("interface handle is null"); - assert(0); // something wrong - return ; - } - - /* just free list, not data(static dbus_method_s) */ - g_list_free(ih->list_methods); - - oh = ih->oh; - if (!oh) { - _E("object handle is null"); - assert(0); // something wrong - return ; - } - - /* remove ih from list_ifaces */ - oh->list_ifaces = g_list_remove(oh->list_ifaces, ih); - - /* interface_s is copy of interface_u */ - free(ih); - - /* remove oh from list_object */ - if (!oh->list_ifaces) { - oh->dh->list_object = g_list_remove(oh->dh->list_object, oh); - free(oh); - } -} - -static int _dbus_handle_attach_object(dbus_handle_s *dh, const char *obj_path, dbus_interface_s *iface) -{ - dbus_object_handle_s *oh = NULL; - - if (!dh || !obj_path || !iface) { - _E("failed to attache object. wrong parameter"); - return -1; - } - - /* find object handle */ - if (dh->list_object) - oh = _dbus_handle_lookup_object(dh->list_object, obj_path); - - if (!oh) { - oh = (dbus_object_handle_s*)calloc(1, sizeof(dbus_object_handle_s)); - if (!oh) { - _E("failed to calloc"); - return -1; - } - oh->dh = dh; - oh->path = obj_path; - - /* attach object */ - dh->list_object = g_list_prepend(dh->list_object, oh); - } - - iface->oh = oh; - /* attach interface */ - oh->list_ifaces = g_list_prepend(oh->list_ifaces, iface); - - return 0; -} - -/* libgio verify path and interface */ -static void _method_call_handler(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) -{ - dbus_interface_s *iface_s = (dbus_interface_s *)user_data; - const dbus_method_s *methods; - GVariant *result = NULL; - - /* todo: ghash ? */ - methods = _dbus_handle_lookup_method(iface_s->list_methods, name); - if (methods) { - result = methods->func(conn, sender, path, iface, name, param, invocation, get_dh_from_oh(iface_s->oh)); - - /* async, maybe they will reply...maybe.. */ - if (!result) { - _E("finish method handle : NULL"); - return ; - } - } else { - _E("no methods"); - } - - g_dbus_method_invocation_return_value(invocation, result); - //if (g_variant_is_of_type(result, G_VARIANT_TYPE_TUPLE)) { - // //_E("TUPLE %s", g_variant_get_type_string(result)); - // g_dbus_method_invocation_return_value(invocation, result); - //} - //else if (g_variant_is_container(result)) { - // /* todo: we don't have any plan to using variant type for reply */ - // _E("CONTAINER %s", g_variant_get_type_string(result)); - // g_dbus_method_invocation_return_value(invocation, result); - // //g_dbus_method_invocation_return_value(invocation, g_variant_new("(v)", result)); - //} else { - // _E("Type is not Container : %s", g_variant_get_type_string(result)); - //} -} - -static GDBusInterfaceVTable path_vtable = {_method_call_handler}; - - -/* -before register object, attach object into dbus handle -_dbus_handle_attach_object() -*/ -static int _dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, dbus_interface_s *iface) -{ - dcl_dbus_handle(); - int ret = 0; - char *buf = NULL; - GError *err = NULL; - GDBusNodeInfo * nodeinfo = NULL; - GDBusInterfaceInfo *ifaceinfo = NULL; - - if (!obj_path || !iface) { - _E("wrong parameter\n"); - return -1; - } - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - if (!dh->conn) { - _E("connection is null\n"); - return -1; - } - - ret = _get_xml_from_interfaces(&buf, iface); - if (ret < 0) { - _E("failed to make xml format"); - goto err; - } - - /* todo: delete this */ -#if 0 - if (strlen(buf) <= 512) { - _E("%s", buf); - } else { - _E("%s", buf + strlen(buf) - 512); - } -#endif - - nodeinfo = g_dbus_node_info_new_for_xml(buf, &err); - if (!nodeinfo || err) { - _E("failed to make introspection data:err:%s:xml:%s\n", err->message, buf); - ret = -1; - goto err; - } - - ifaceinfo = g_dbus_node_info_lookup_interface(nodeinfo, iface->name); - if (!ifaceinfo) { - _E("failed to g_dbus_node_info_lookup_interface"); - ret = -1; - goto err; - } - - /* - path own single interface - if interface is already registered, then failed. - g_dbus_connection_register_object ref(ifaceinfo) now, unref if object is unregistered - */ - ret = g_dbus_connection_register_object(dh->conn, obj_path, ifaceinfo/*ref 2*/, &path_vtable, (void*)iface, - _free_func_object, - &err); - if (err) { - _E("failed to register object:err:%s:\n", err->message); - ret = -1; - goto err; - } - - iface->reg_id = ret; - iface->modified = FALSE; - -err: - /* todo: detach object */ - //_dbus_handle_detach_object(dh, obj_path, iface); - /* attach interface before register object */ - /*ret = _dbus_handle_detach_object(dh, obj_path, iface); - if (ret < 0) { - _E("failed to attach object"); - goto err; - }*/ - - if (nodeinfo) - g_dbus_node_info_unref(nodeinfo); - if (buf) - free(buf); - if (err) - g_error_free(err); - - return ret; -} - -/* -register same interface at once - -if interface is constructed by multiple methods, -also it is not possible to make methods struct at once, - -use dbus_handle_add_dbus_object(), dbus_handle_register_dbus_object_all(). - -return reg_id -*/ -int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u) -{ - dcl_dbus_handle(); - int ret = 0; - dbus_interface_s *iface = NULL; - - if (!obj_path || !iface_u) { - _E("wrong parameter\n"); - return -1; - } - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - if (!dh->conn) { - _E("connection is null\n"); - return -1; - } - - /* check registered interface */ - if (dh->list_object) { - dbus_object_handle_s *oh = _dbus_handle_lookup_object(dh->list_object, obj_path); - if (oh) { - dbus_interface_s *ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name); - if (ih) { - _E("path %s, interface %s already registered", obj_path, iface_u->name); - return -1; - } - } - } - - iface = _iface_u_to_s(iface_u); - if (!iface) { - _E("failed to _iface_u_to_s"); - return -1; - } - - /* attach interface before register object */ - ret = _dbus_handle_attach_object(dh, obj_path, iface); - if (ret < 0) { - _E("failed to attach object"); - goto err; - } - - ret = _dbus_handle_register_dbus_object(dh, obj_path, iface); - if (ret <= 0) { - _E("failed to register dbus object%d", ret); - goto err; - } -err: - return ret; -} - -int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path) -{ - dcl_dbus_handle(); - dbus_object_handle_s *oh = NULL; - int ret = 0; - - if (!obj_path) { - return -1; - } - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - if (!dh->list_object) { - _E("list_object is empty"); - return 0; - } - - oh = _dbus_handle_lookup_object(dh->list_object, obj_path); - if (!oh) { - _E("no object with name %s", obj_path); - return -1; - } - - /* unregister every interface of object*/ - for (GList *item = g_list_first(oh->list_ifaces); item != NULL; item = g_list_next(item)) { - dbus_interface_s *ih = item->data; - if (!ih) { - _E("this is error"); - assert(0); - } - - /* remove ih from list_ifaces */ - if (!ih->reg_id) { - item = g_list_previous(item); - - /* remove and free link */ - oh->list_ifaces = g_list_remove(oh->list_ifaces, ih); - - /* free list_methods */ - g_list_free(ih->list_methods); - - /* free data */ - free(ih); - continue; - } - - /* unregister object by id */ - ret = g_dbus_connection_unregister_object(dh->conn, ih->reg_id); - if (!ret) - _E("failed to unregister object %s, interface %s, regid %d", oh->path, ih->name, ih->reg_id); - } - - return 0; -} - -/* -add object temporarily. -dbus_handle_register_dbus_object_all will register every objects on connection. - -return registered method count -*/ -int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u) -{ - dcl_dbus_handle(); - dbus_object_handle_s *oh = NULL; - dbus_interface_s *ih = NULL; - int cnt; - - if (!obj_path || !iface_u) { - _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u); - return -1; - } - if (iface_u && (!iface_u->name || !iface_u->methods)) { - _E("wrong parameter path %s, iface_u %p\n", obj_path, iface_u); - return -1; - } - - cnt = iface_u->nr_methods; - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - - if (!dh->conn) { - _E("failed to register method. connection is null\n"); - return -1; - } - - /* if there are no object list, just add */ - if (!dh->list_object) { - if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) { - _E("failed to attach object"); - return -1; - } - goto out; - } - - oh = _dbus_handle_lookup_object(dh->list_object, obj_path); - /* if there are no matched object, just add */ - if (!oh) { - if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) { - _E("failed to attach object"); - return -1; - } - goto out; - } - - /* this is an error, interface must have one or more item ? */ - if (!oh->list_ifaces) { - _E("error. list_ifaces is null\n"); - assert(0); - goto out; - } - - ih = _dbus_handle_lookup_interface(oh->list_ifaces, iface_u->name); - /* if there are no matched interface, just add */ - if (!ih) { - if (_dbus_handle_attach_object(dh, obj_path, _iface_u_to_s(iface_u))) { - _E("failed to attach object"); - return -1; - } - goto out; - } - - /* todo: - 1. unregister interface - 2. update interface and methods - 3. register interface - */ - if (ih->reg_id) { - _E("interface already registered, ignore new interface"); - return -1; - } - - /* attach new methods */ - cnt = 0; - for (int i = 0; i < iface_u->nr_methods; ++i) { - GList *item = g_list_find_custom(g_list_first(ih->list_methods), iface_u->methods[i].member, _compare_dbus_method); - if (!item) { - //_D("attached %s", iface_u->methods[i].member); - ih->list_methods = g_list_prepend(ih->list_methods, (void*)(iface_u->methods + i)); - ++cnt; - } - } - - if (cnt) - ih->modified = TRUE; - -out: - /*todo: delete debugging log */ - //if (dh && dh->list_object) - // _D("obj list len %d", g_list_length(dh->list_object)); - //if (oh && oh->list_ifaces) - // _D("iface list len %d", g_list_length(oh->list_ifaces)); - //if (ih && ih->list_methods) - // _D("method list len %d", g_list_length(ih->list_methods)); - - return cnt; -} - -int dbus_handle_register_dbus_object_all(dbus_handle_h handle) -{ - dcl_dbus_handle(); - dbus_object_handle_s *oh = NULL; - dbus_interface_s *ih = NULL; - int ret = 0; - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - if (!dh->conn) { - _E("connection is null\n"); - return -1; - } - - if (!dh->list_object) { - _E("obj list is empty"); - return -1; - } - - /*if (dh && dh->list_object) - _D("obj list len %d", g_list_length(dh->list_object));*/ - - for (GList *item = g_list_first(dh->list_object); item != NULL; item = g_list_next(item)) { - oh = (dbus_object_handle_s *)item->data; - - if (!oh) { - _E("something wrong"); - assert(0); - } - if (!oh->list_ifaces) { - _E("path %s: list_ifaces are null", oh->path); - goto err; - } - - //_D("iface list len %d", g_list_length(oh->list_ifaces)); - - for (GList *li = g_list_first(oh->list_ifaces); li != NULL; li = g_list_next(li)) { - ih = (dbus_interface_s *)li->data; - - /* if there are no modification, goto next */ - if (!ih->modified) - continue; - - /* todo: if already registered interface, unregister first */ - - /*_E("interface %s:", ih->name); - if (ih && ih->list_methods) - _D("method list len %d", g_list_length(ih->list_methods));*/ - - ret = _dbus_handle_register_dbus_object(dh, oh->path, ih); - if (ret <= 0) - _E("failed to register dbus object%d", ret); - - } - } - return 0; -err: - - // todo: delete all updates - - return -1; -} - -static void _free_func_signal(gpointer data) -{ - //_D("free signal subscribe"); -} - -guint subscribe_dbus_signal(dbus_handle_h handle, const char *path, - const char *iface, const char *name, - GDBusSignalCallback cb, void *data, - destroy_notified free_func) -{ - dcl_dbus_handle(); - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return 0; - } - } - - if (!dh->conn) { - _E("connection is null. check bus status"); - return 0; - } - return g_dbus_connection_signal_subscribe(dh->conn, NULL, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, cb, data, _free_func_signal); -} - -void unsubscribe_dbus_signal(dbus_handle_h handle, guint id) -{ - dcl_dbus_handle(); - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return; - } - } - - if (!dh->conn) { - _E("connection is null. check bus status"); - return; - } - - g_dbus_connection_signal_unsubscribe(dh->conn, id); -} - -int _check_type_string_is_container(const char *signature) -{ - if (!signature) - return FALSE; - - switch (signature[0]) { - case 'a': - case 'm': - case 'r': - case '(': - case '{': - case 'v': - return TRUE; - default: - return FALSE; - } - - return TRUE; -} - -GVariant *dbus_handle_make_simple_array(const char *sig, int *param) -{ - GVariantBuilder *builder = NULL; - char format[256]; - int i = 0; - - builder = g_variant_builder_new(G_VARIANT_TYPE(sig)); - if (!builder) { - _E("failed to g_variant_builder_new"); - return NULL; - } - - while (param[i]) - g_variant_builder_add(builder, "i", param[i++]); - - snprintf(format, sizeof(format) - 1, "(%s)", sig); - return g_variant_new(format, builder); -} - -/* todo: looks like garbage... */ -static GVariant* _append_variant(const char *signature, const char *param[]) -{ - char *ch; - int i; - int pi; - int int_type; - gboolean bool_type; - unsigned long long int64_type; - GVariant *ret; - int len; - char container[255];// The maximum length of a signature is 255. - const char *sig = signature; - GVariantBuilder *builder = NULL; - - if (!signature || !param) - return 0; - - /* workaround for user fault "(i) != i" but we treat this as same signature */ - /* G_VARIANT_TYPE("si") return NULL */ - /* todo: actually user have to use correct signature */ - if (!_check_type_string_is_container(signature)) { - snprintf(container, sizeof(container) - 1, "(%s)", signature); - sig = container; - } - if (!g_variant_type_is_container(G_VARIANT_TYPE(sig))) { - _E("signature (%s) is not container type", signature); - } - - builder = g_variant_builder_new(G_VARIANT_TYPE(sig)); - len = strlen(sig); - pi = 0; - for (ch = (char *)sig, i = 0; i < len; ++i, ++ch) { - switch (*ch) { - case '(': - case ')': - continue; - case 'b': - bool_type = (atoi(param[pi++]) == 0 ? FALSE : TRUE); - g_variant_builder_add(builder, "b", bool_type); - break; - case 'i': - int_type = atoi(param[pi++]); - g_variant_builder_add(builder, "i", int_type); - break; - case 'u': - int_type = strtoul(param[pi++], NULL, 10); - g_variant_builder_add(builder, "u", int_type); - break; - case 't': - int64_type = atoll(param[pi++]); - g_variant_builder_add(builder, "t", int64_type); - break; - case 's': - g_variant_builder_add(builder, "s", param[pi++]); - break; - case 'a': - ++ch; - switch (*ch) { - case 'y': - g_variant_builder_add(builder, "^ay", param[pi++]); - ++i; - break; - default: - break; - } - break; - default: - break; - } - } - ret = g_variant_builder_end(builder); - g_variant_builder_clear(builder); - g_variant_builder_unref(builder); - - return ret; -} - -int dbus_handle_broadcast_dbus_signal(const char *path, - const char *iface, const char *name, - const char *signature, const char *param[]) -{ - dbus_handle_s *dh = NULL; - GError *err = NULL; - gboolean ret = 0; - GVariant *var = NULL; - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - - if (signature && param) - var = _append_variant(signature, param); - ret = g_dbus_connection_emit_signal(dh->conn, NULL, path, iface, name, var, &err); - if (err) { - _E("%d %s\n", ret, err ? err->message : NULL); - g_error_free(err); - } - - return ret; -} - -int dbus_handle_broadcast_dbus_signal_var(const char *path, - const char *iface, const char *name, - GVariant *param) -{ - dbus_handle_s *dh = NULL; - GError *err = NULL; - gboolean ret = 0; - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - - ret = g_dbus_connection_emit_signal(dh->conn, NULL, path, iface, name, param, &err); - if (err) { - _E("%d %s\n", ret, err ? err->message : NULL); - g_error_free(err); - } - - return ret; -} - -GVariant *dbus_method_sync_with_reply(const char *dest, const char *path, - const char *iface, const char *method, - const char *signature, const char *param[]) -{ - GError *err = NULL; - GVariant * var = NULL; - GVariant * ret = NULL; - dbus_handle_s *dh = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return NULL; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return NULL; - } - - if (signature && param) - var = _append_variant(signature, param); - - ret = g_dbus_connection_call_sync(dh->conn, - dest, path, iface, method, - var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err); - if (!ret || err) { - if (err) { - _E("failed to g_dbus_connection_call_sync:%s", err->message); - g_error_free(err); - } else { - _E("failed to g_dbus_connection_call_sync"); - g_variant_unref(var); - } - return NULL; - } - - return ret; -} - -GVariant *dbus_method_sync_with_reply_var(const char *dest, const char *path, - const char *iface, const char *method, GVariant *var) -{ - GError *err = NULL; - GVariant * ret = NULL; - dbus_handle_s *dh = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - if (var) - g_variant_unref(var); - return NULL; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - if (var) - g_variant_unref(var); - return NULL; - } - - ret = g_dbus_connection_call_sync(dh->conn, - dest, path, iface, method, - var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err); - if (!ret || err) { - if (err) { - _E("failed to g_dbus_connection_call_sync:%s", err->message); - g_error_free(err); - } else { - _E("failed to g_dbus_connection_call_sync"); - } - return NULL; - } - - return ret; -} - -gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size) -{ - GUnixFDList *fd_list = NULL; - int length = 0; - - fd_list = g_dbus_message_get_unix_fd_list(g_dbus_method_invocation_get_message(invocation)); - - if (!fd_list) { - _E("failed to g_unix_fd_list_get_length: fd_list is null"); - return NULL; - } - - length = g_unix_fd_list_get_length(fd_list); - if (length == 0) { - _E("failed to g_unix_fd_list_get_length: list size is 0"); - return NULL; - } - if (size) - *size = length; - - return g_unix_fd_list_steal_fds(fd_list, NULL); -} - -GVariant *dbus_method_with_unix_fd_list_sync_with_reply(const char *dest, const char *path, - const char *iface, const char *method, - const char *signature, const char *param[], - int *in_fdlist, int in_size, - int **out_fdlist, int *out_size) -{ - GError *err = NULL; - GVariant * var = NULL; - GVariant * ret = NULL; - dbus_handle_s *dh = NULL; - GDBusProxy *proxy = NULL; - GUnixFDList *g_infdlist = NULL; - GUnixFDList *g_outfdlist = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return NULL; - } - if (in_fdlist && in_size == 0) { - _E("wrong in_fdlist is not null but in_size is 0"); - return NULL; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return NULL; - } - - if (signature && param) - var = _append_variant(signature, param); - - proxy = g_dbus_proxy_new_sync(dh->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, dest, path, iface, NULL, &err); - if (!proxy) { - if (err) { - _E("failed to proxy_new_sync(%s)\n", err->message); - g_error_free(err); - } else { - _E("failed to proxy_new_sync\n"); - if (var) - g_variant_unref(var); - } - } - - /* append fd */ - if (in_fdlist) { - g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size); - if (!g_infdlist) { - _E("failed to g_unix_fd_list_new_from_array\n"); - goto out; - } - //g_infdlist = g_unix_fd_list_new(); - //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) { - } - - ret = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, method, var, G_DBUS_CALL_FLAGS_NONE, -1, - g_infdlist, &g_outfdlist, NULL, &err); - if (!ret || err) { - if (err) { - _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:%s", err->message); - g_error_free(err); - } else { - _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:"); - if (var) - g_variant_unref(var); - if (g_infdlist) - g_object_unref(g_infdlist); - } - goto out; - } - - /* fds to out array */ - if (g_outfdlist) { - *out_size = g_unix_fd_list_get_length(g_outfdlist); - if (*out_size == 0) - goto out; - - *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL); - } - -out: - if (g_outfdlist) - g_object_unref(g_outfdlist); - if (proxy) - g_object_unref(proxy); - - return ret; -} - -GVariant *dbus_method_with_unix_fd_list_sync_with_reply_var(const char *dest, const char *path, - const char *iface, const char *method, - GVariant *param, - int *in_fdlist, int in_size, - int **out_fdlist, int *out_size) -{ - GError *err = NULL; - GVariant * ret = NULL; - dbus_handle_s *dh = NULL; - GDBusProxy *proxy = NULL; - GUnixFDList *g_infdlist = NULL; - GUnixFDList *g_outfdlist = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return NULL; - } - if (in_fdlist && in_size == 0) { - _E("wrong in_fdlist is not null but in_size is 0"); - return NULL; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return NULL; - } - - proxy = g_dbus_proxy_new_sync(dh->conn, G_DBUS_PROXY_FLAGS_NONE, NULL, dest, path, iface, NULL, &err); - if (!proxy) { - if (err) { - _E("failed to proxy_new_sync(%s)\n", err->message); - g_error_free(err); - } else { - _E("failed to proxy_new_sync\n"); - if (param) - g_variant_unref(param); - } - goto out; - } - - /* append fd */ - if (in_fdlist) { - g_infdlist = g_unix_fd_list_new_from_array(in_fdlist, in_size); - if (!g_infdlist) { - _E("failed to g_unix_fd_list_new_from_array\n"); - goto out; - } - //g_infdlist = g_unix_fd_list_new(); - //if (g_unix_fd_list_append(g_infdlist, in_fdlist[0], &err) < 0) { - } - - /* send message */ - ret = g_dbus_proxy_call_with_unix_fd_list_sync(proxy, method, param, G_DBUS_CALL_FLAGS_NONE, -1, - g_infdlist, &g_outfdlist, NULL, &err); - if (!ret || err) { - if (err) { - _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:%s", err->message); - g_error_free(err); - } else { - _E("failed to g_dbus_proxy_call_with_unix_fd_list_sync:"); - if (param) - g_variant_unref(param); - if (g_infdlist) - g_object_unref(g_infdlist); - } - goto out; - } - - /* copy fds to out array */ - if (g_outfdlist) { - *out_size = g_unix_fd_list_get_length(g_outfdlist); - if (*out_size == 0) - goto out; - *out_fdlist = g_unix_fd_list_steal_fds(g_outfdlist, NULL); - } -out: - if (g_outfdlist) - g_object_unref(g_outfdlist); - if (proxy) - g_object_unref(proxy); - return ret; -} - -int dbus_method_sync(const char *dest, const char *path, - const char *iface, const char *method, - const char *signature, const char *param[]) -{ - int result; - gboolean result_bool; - GVariant *reply = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - reply = dbus_method_sync_with_reply(dest, path, iface, method, signature, param); - if (!reply) - return -ECOMM; - - if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) { - g_variant_get(reply, "(i)", &result); - } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) { - g_variant_get(reply, "(b)", &result_bool); - result = (int)result_bool; - } else { - result = -ENOMSG; - } - - g_variant_unref(reply); - - return result; -} - -int dbus_method_sync_var(const char *dest, const char *path, - const char *iface, const char *method, GVariant *param) -{ - int result; - gboolean result_bool; - GVariant *reply = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - reply = dbus_method_sync_with_reply_var(dest, path, iface, method, param); - if (!reply) - return -ECOMM; - - if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) { - g_variant_get(reply, "(i)", &result); - } else if (g_strcmp0("(b)", g_variant_get_type_string(reply)) == 0) { - g_variant_get(reply, "(b)", &result_bool); - result = (int)result_bool; - } else { - result = -ENOMSG; - } - - g_variant_unref(reply); - - return result; -} - -int dbus_method_sync_timeout(const char *dest, const char *path, - const char *iface, const char *method, - const char *signature, const char *param[], int timeout) -{ - dbus_handle_s *dh = NULL; - GError *err = NULL; - GVariant * var = NULL; - GVariant * reply = NULL; - int result = 0; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -EPERM; - } - - if (signature && param) - var = _append_variant(signature, param); - - reply = g_dbus_connection_call_sync(dh->conn, - dest, path, iface, method, - var, NULL, G_DBUS_CALL_FLAGS_NONE, timeout, NULL, &err); - if (!reply || err) { - _E("failed to g_dbus_connection_call_sync:%s", err->message); - g_error_free(err); - return -1; - } - - if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) - g_variant_get(reply, "(i)", &result); - else - result = -ENOMSG; - - g_variant_unref(reply); - - return result; -} - -int dbus_method_sync_pairs(const char *dest, const char *path, - const char *iface, const char *method, - int num, va_list args) -{ - GError *err = NULL; - GVariant * reply = NULL; - char *key, *value; - int ret = 0; - GVariant *var; - GVariantBuilder *builder; - dbus_handle_s *dh = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - - builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}")); - - for (int i = 0 ; i < num ; i = i + 2) { - key = va_arg(args, char *); - value = va_arg(args, char *); - _I("key(%s), value(%s)", key, value); - g_variant_builder_add(builder, "{ss}", key, value); - } - - var = g_variant_new("(a{ss})", builder); - - reply = g_dbus_connection_call_sync(dh->conn, - dest, path, iface, method, - var, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err); - if (!reply || err) { - _E("failed to g_dbus_connection_call_sync"); - return -1; - } - - if (g_strcmp0("(i)", g_variant_get_type_string(reply)) == 0) - g_variant_get(reply, "(i)", &ret); - else - ret = -ENOMSG; - - g_variant_unref(reply); - - return ret; -} - -int dbus_method_async_pairs(const char *dest, const char *path, - const char *iface, const char *method, - int num, va_list args) -{ - char *key, *value; - GVariant *var; - GVariantBuilder *builder; - dbus_handle_s *dh = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - - // dict - builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}")); - - for (int i = 0 ; i < num ; i = i + 2) { - key = va_arg(args, char *); - value = va_arg(args, char *); - _I("key(%s), value(%s)", key, value); - g_variant_builder_add(builder, "{ss}", key, value); - } - - var = g_variant_new("(a{ss})", builder); - - g_dbus_connection_call(dh->conn, dest, path, iface, method, - var, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, - NULL, - NULL); - - return 0; -} - -int dbus_method_async(const char *dest, const char *path, - const char *iface, const char *method, - const char *signature, const char *param[]) -{ - GVariant * var = NULL; - dbus_handle_s *dh = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - - if (signature && param) - var = _append_variant(signature, param); - - g_dbus_connection_call(dh->conn, dest, path, iface, method, - var, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, - NULL, - NULL); - - return 0; -} - -int dbus_method_async_var(const char *dest, const char *path, - const char *iface, const char *method, GVariant *param) -{ - dbus_handle_s *dh = NULL; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - - g_dbus_connection_call(dh->conn, dest, path, iface, method, - param, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, - NULL, - NULL); - - return 0; -} - -/* callback should free gvariant */ -static void _cb_pending(GDBusConnection *conn, - GAsyncResult *res, - gpointer user_data) -{ - GVariant *reply = NULL; - GError *err = NULL; - pending_call_data *data = (pending_call_data *)user_data; - - reply = g_dbus_connection_call_finish(conn, res, &err); - if (!reply || err) { - if (err) { - _E("no message : [%s]", err->message); - g_error_free(err); - } else { - _E("no message"); - } - - if (data && data->func) - data->func(NULL, data->data, err); - goto out; - } - - if (data && data->func) - data->func(reply, data->data, err); -out: - if (data) - free(data); -} - -int dbus_method_async_with_reply(const char *dest, - const char *path, - const char *iface, - const char *method, - const char *signature, - const char *param[], - dbus_pending_cb cb, - int timeout_msec, - void *data) -{ - dbus_handle_s *dh = NULL; - pending_call_data *pdata = NULL; - GVariant * var = NULL; - int ret = 0; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - if (timeout_msec < -1) { - _E("wrong timeout %d", timeout_msec); - return -1; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -EPERM; - } - - if (signature && param) - var = _append_variant(signature, param); - - if (cb) { - pdata = (pending_call_data*)malloc(sizeof(pending_call_data)); - if (!pdata) { - ret = -ENOMEM; - goto err; - } - - pdata->func = cb; - pdata->data = data; - } - g_dbus_connection_call(dh->conn, dest, path, iface, method, - var, NULL, G_DBUS_CALL_FLAGS_NONE, timeout_msec, NULL, - (GAsyncReadyCallback)_cb_pending, - pdata); - - return ret; -err: - if (var) - g_variant_unref(var); - return ret; -} - -int dbus_method_async_with_reply_var(const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param, - dbus_pending_cb cb, - int timeout_msec, - void *data) -{ - dbus_handle_s *dh = NULL; - pending_call_data *pdata = NULL; - int ret = 0; - - if (!dest || !path || !iface || !method) { - _E("wrong parameters dest(%s) path(%s) iface(%s) method(%s)", dest, path, iface, method); - return -1; - } - - if (timeout_msec < -1) { - _E("wrong timeout %d", timeout_msec); - return -1; - } - - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -EPERM; - } - - if (cb) { - pdata = (pending_call_data*)malloc(sizeof(pending_call_data)); - if (!pdata) { - ret = -ENOMEM; - goto err; - } - - pdata->func = cb; - pdata->data = data; - } - g_dbus_connection_call(dh->conn, dest, path, iface, method, - param, NULL, G_DBUS_CALL_FLAGS_NONE, timeout_msec, NULL, - (GAsyncReadyCallback)_cb_pending, - pdata); - - return ret; -err: - if (param) - g_variant_unref(param); - return ret; -} - -int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender) -{ - GError *err = NULL; - GVariant *vret = NULL; - pid_t pid = 0; - - if (!conn) { - _E("connection is null"); - return -1; - } - if (!sender) { - _E("sender is null"); - return -1; - } - - vret = g_dbus_connection_call_sync(conn, - "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetConnectionUnixProcessID", - g_variant_new("(s)", sender), - NULL, - G_DBUS_CALL_FLAGS_NONE, - DBUS_REPLY_TIMEOUT, - NULL, - &err); - if (!vret || err) { - _E("failed to g_dbus_connection_call_sync:%s", err->message); - g_error_free(err); - return -1; - } - - g_variant_get(vret, "(u)", &pid); - g_variant_unref(vret); - - return pid; -} - -int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender) -{ - dcl_dbus_handle(); - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - if (!dh->conn) { - _E("wrong dbus handle. connection is null"); - assert(0); - return -1; - } - - return dbus_connection_get_sender_pid(dh->conn, sender); -} - -int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds) -{ - dcl_dbus_handle(); - GVariant *vret = NULL; - GError *err = NULL; - GVariantIter *iter = NULL; - char * item; - GVariant *sub; - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return -1; - } - } - vret = g_dbus_connection_call_sync(dh->conn, - DBUS_BUS_NAME, - DBUS_OBJECT_PATH, - DBUS_INTERFACE_NAME, - "GetConnectionCredentials", - g_variant_new("(s)", name), - NULL, - G_DBUS_CALL_FLAGS_NONE, - DBUS_REPLY_TIMEOUT, - NULL, - &err); - if (!vret || err) { - _E("failed to g_dbus_connection_call_sync:%s", err->message); - return -1; - } - - g_variant_get(vret, "(a{sv})", &iter); - - while (g_variant_iter_loop(iter, "{sv}", &item, &sub)) { - if (!g_strcmp0(item, "UnixUserID")) { - g_variant_get(sub, "u", &creds->uid); - _D("UnixUserID %u", creds->uid); - } else if (!g_strcmp0(item, "ProcessID")) { - g_variant_get(sub, "u", &creds->pid); - _D("ProcessID %u", creds->pid); - } else if (!g_strcmp0(item, "LinuxSecurityLabel")) { - g_variant_get(sub, "^ay", &creds->sec_label); - _D("%s", creds->sec_label); - } - } - - if (iter) - g_variant_iter_free(iter); - if (vret) - g_variant_unref(vret); - - return 0; -} - -void _destroy_notify_watch_name(gpointer data) -{ - /*if (data) - free(data);*/ -} - -int dbus_handle_watch_name(const char *name, - GBusNameAppearedCallback name_appeared_handler, - GBusNameVanishedCallback name_vanished_handler, - void *user_data) -{ - guint id = 0; - - if (!name) { - _E("wrong name name %s", name); - return -1; - } - if (!name_appeared_handler && !name_vanished_handler) { - _E("both function pointers are null"); - return -1; - } - - id = g_bus_watch_name(dbus_handle_get_default_bus_type(), - name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - name_appeared_handler, - name_vanished_handler, - user_data, - _destroy_notify_watch_name); - if (!id) { - _E("failed to g_bus_watch_name"); - return -1; - } - - return id; -} - -void dbus_handle_unwatch_name(guint id) -{ - if (id == 0) { - _E("wrong id %d", id); - return; - } - g_bus_unwatch_name(id); -} - -int _get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size) -{ - int fd, ret; - char buf[PATH_MAX + 1]; - char *filename; - - snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); - fd = open(buf, O_RDONLY); - if (fd < 0) { - errno = ESRCH; - return -1; - } - - ret = read(fd, buf, PATH_MAX); - close(fd); - if (ret < 0) - return -1; - - buf[PATH_MAX] = '\0'; - - filename = strrchr(buf, '/'); - if (filename == NULL) - filename = buf; - else - filename = filename + 1; - - if (cmdline_size < strlen(filename) + 1) { - errno = EOVERFLOW; - return -1; - } - - strncpy(cmdline, filename, cmdline_size - 1); - cmdline[cmdline_size - 1] = '\0'; - return 0; -} - -// g_strfreev(strv) -char **dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name) -{ - dcl_dbus_handle(); - GError *err = NULL; - GVariant *vret = NULL; - GVariantIter *iter = NULL; - gchar **strv = NULL; - gchar *str = NULL; - int i = 0; - - if (!bus_name) { - _E("wrong parameter bus_name(%s)", bus_name); - return NULL; - } - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return NULL; - } - } - - vret = g_dbus_connection_call_sync(dh->conn, - "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListQueuedOwners", - g_variant_new("(s)", bus_name), - NULL, - G_DBUS_CALL_FLAGS_NONE, - DBUS_REPLY_TIMEOUT, - NULL, - &err); - if (!vret || err) { - _E("failed to g_dbus_connection_call_sync:%s", err->message); - g_error_free(err); - return NULL; - } - - g_variant_get(vret, "(as)", &iter); - strv = g_new(gchar *, g_variant_iter_n_children(iter) + 1); - - i = 0; - while (g_variant_iter_loop(iter, "s", &str)) - strv[i++] = g_strdup(str); - strv[i] = NULL; - - g_variant_iter_free(iter); - g_variant_unref(vret); - - return strv; -} - -void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name) -{ - dcl_dbus_handle(); - char exe_name[PATH_MAX]; - int pid; - char **strv = NULL; - int i; - - if (!dh) { - dh = _dbus_handle_get_default_connection(); - if (!dh) { - _E("failed to get default connection, bustype:%d", (int)dbus_handle_get_default_bus_type()); - return ; - } - } - - strv = dbus_handle_get_owner_list(dh, owner_name); - if (!strv) { - _E("failed to get owner list of %s", owner_name); - return ; - } - - for (i = 0; strv[i] != NULL; ++i) { - pid = dbus_handle_get_sender_pid(dh, strv[i]); - if (_get_cmdline_name(pid, exe_name, PATH_MAX) != 0) - break; - _I("%s(%d)", exe_name, pid); - } - - g_strfreev(strv); -} - -dbus_handle_h dbus_handle_init(GBusType type, const char* bus_name) -{ - dbus_handle_h handle = NULL; - int i, ret = 0; - - if (!bus_name) { - _E("Wrong bus name, %s", bus_name); - return NULL; - } - - // todo: do we need retry ? - booting time - for (i = 0 ; i < 3; ++i) { - handle = dbus_handle_get_connection(type, FALSE); - if (handle) - break; - usleep(5000); - } - ret = dbus_handle_request_bus_name(handle, bus_name); - if (ret <= 0) - goto out; - - dbush_handle_check_owner_name(NULL, bus_name); - - return handle; - -out: - return NULL; -} diff --git a/src/core/dbus.h b/src/core/dbus.h deleted file mode 100644 index cca491a..0000000 --- a/src/core/dbus.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * feedbackd - * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. - * - * 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 __DBUS_H__ -#define __DBUS_H__ - -#include -#include -#include -#include -#include - -/* - * Template - * -#define XXX_BUS_NAME "org.tizen.system.XXX" -#define XXX_OBJECT_PATH "/Org/Tizen/System/XXX" -#define XXX_INTERFACE_NAME XXX_BUS_NAME -#define XXX_PATH_YYY XXX_OBJECT_PATH"/YYY" -#define XXX_INTERFACE_YYY XXX_INTERFACE_NAME".YYY" -#define XXX_SIGNAL_ZZZ "ZZZ" -#define XXX_METHOD_ZZZ "ZZZ" - */ - -/* - * DBus daemon - */ -#define DBUS_BUS_NAME "org.freedesktop.DBus" -#define DBUS_OBJECT_PATH "/org/freedesktop/DBus" -#define DBUS_INTERFACE_NAME DBUS_BUS_NAME - -/* - * Device daemon - */ -#define DEVICED_BUS_NAME "org.tizen.system.deviced" -#define DEVICED_OBJECT_PATH "/Org/Tizen/System/DeviceD" -#define DEVICED_INTERFACE_NAME DEVICED_BUS_NAME -/* Core service: get/set device status operations about device */ -#define DEVICED_PATH_CORE DEVICED_OBJECT_PATH"/Core" -#define DEVICED_INTERFACE_CORE DEVICED_INTERFACE_NAME".core" -/* Poweroff service: get power off status operations about Poweroff */ -#define DEVICED_PATH_POWEROFF DEVICED_OBJECT_PATH"/PowerOff" -#define DEVICED_INTERFACE_POWEROFF DEVICED_INTERFACE_NAME".PowerOff" -/* Key service: operations about key */ -#define DEVICED_PATH_KEY DEVICED_OBJECT_PATH"/Key" -#define DEVICED_INTERFACE_KEY DEVICED_INTERFACE_NAME".Key" - -/* - * Vibrator daemon - */ -#define VIBRATOR_BUS_NAME "org.tizen.system.vibrator" -#define VIBRATOR_OBJECT_PATH "/Org/Tizen/System/Vibrator" -#define VIBRATOR_INTERFACE_NAME VIBRATOR_BUS_NAME -/* Core service: get/set device status operations about device */ -#define VIBRATOR_PATH_CORE VIBRATOR_OBJECT_PATH"/Core" -#define VIBRATOR_INTERFACE_CORE VIBRATOR_INTERFACE_NAME".core" - -#define VIBRATOR_PATH_HAPTIC VIBRATOR_OBJECT_PATH"/Haptic" -#define VIBRATOR_INTERFACE_HAPTIC VIBRATOR_INTERFACE_NAME".haptic" - -typedef struct { - const unsigned char *data; - int size; -} dbus_byte; - -GVariant *dbus_method_sync_with_reply(const char *dest, const char *path, - const char *interface, const char *method, - const char *sig, const char *param[]); - -GVariant *dbus_method_sync_with_reply_var(const char *dest, const char *path, const char *iface, const char *method, GVariant *var); - -/* fd */ -gint* dbus_handle_get_unix_fd_list(GDBusMethodInvocation *invocation, int *size); - -GVariant *dbus_method_with_unix_fd_list_sync_with_reply(const char *dest, const char *path, - const char *iface, const char *method, - const char *signature, const char *param[], - int *in_fdlist, int in_size, - int **out_fdlist, int *out_size); -GVariant *dbus_method_with_unix_fd_list_sync_with_reply_var(const char *dest, const char *path, - const char *iface, const char *method, - GVariant *param, - int *in_fdlist, int in_size, - int **out_fdlist, int *out_size); - -int dbus_method_sync(const char *dest, const char *path, - const char *interface, const char *method, - const char *sig, const char *param[]); - -int dbus_method_sync_var(const char *dest, const char *path, const char *iface, const char *method, GVariant *param); - -int dbus_method_sync_timeout(const char *dest, const char *path, - const char *interface, const char *method, - const char *sig, const char *param[], int timeout); - -int dbus_method_sync_pairs(const char *dest, const char *path, - const char *interface, const char *method, - int num, va_list args); -int dbus_method_async_pairs(const char *dest, const char *path, - const char *interface, const char *method, - int num, va_list args); -int dbus_method_async(const char *dest, const char *path, - const char *interface, const char *method, - const char *sig, const char *param[]); - -int dbus_method_async_var(const char *dest, const char *path, const char *iface, const char *method, GVariant *param); - -typedef void (*dbus_pending_cb)(GVariant *var, void *user_data, GError *err); - -int dbus_method_async_with_reply(const char *dest, - const char *path, - const char *iface, - const char *method, - const char *signature, - const char *param[], - dbus_pending_cb cb, - int timeout_msec, - void *data); - - -int dbus_method_async_with_reply_var(const char *dest, - const char *path, - const char *iface, - const char *method, - GVariant *param, - dbus_pending_cb cb, - int timeout_msec, - void *data); - -int check_systemd_active(void); - -/** - * @brief Dbus handler which is used to register and call methods - - * @since_tizen 4.0 - */ -typedef void *dbus_handle_h; - -/** - * @brief Dbus method handler which is used to unregister dbus methods - * @since_tizen 4.0 - */ -typedef void *dbus_object_handle_h; - -/** - * @brief Structure which contains the dbus method name and callback function. - * @since_tizen 4.0 - */ -typedef struct { - const char *member; - const char *signature_in; - const char *signature_out; - GVariant *(*func)(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data); -} dbus_method_s; - -/** - * @brief Structure which contains the dbus interface information and its methods.i - * @since_tizen 4.0 - */ -typedef struct { - const char *name; - const dbus_method_s *methods; - int nr_methods; -} dbus_interface_u; - -#define dh_get_param_from_var(gvar, signature, ...) ((g_strcmp0(signature, g_variant_get_type_string(gvar)) == 0) ? g_variant_get(gvar, signature, __VA_ARGS__), TRUE : FALSE) - -#define dbus_handle_new_g_variant_tuple() g_variant_new_tuple(NULL, 0) - -/** - * @brief Callback function which is called when the user data needs to be released. - * @since_tizen 4.0 - */ -typedef void (*destroy_notified)(void *data); - -typedef struct { - dbus_pending_cb func; - void *data; -} pending_call_data; - -int dbus_handle_request_bus_name(dbus_handle_h handle, const char *bus_name); - -dbus_handle_h dbus_handle_get_connection(GBusType bus_type, gboolean priv); - -int dbus_handle_register_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface); -int dbus_handle_unregister_dbus_object(dbus_handle_h handle, const char *obj_path); - -int dbus_handle_add_dbus_object(dbus_handle_h handle, const char *obj_path, const dbus_interface_u *iface_u); -int dbus_handle_register_dbus_object_all(dbus_handle_h handle); - -guint subscribe_dbus_signal(dbus_handle_h handle, const char *path, const char *iface, const char *name, GDBusSignalCallback cb, void *data, destroy_notified free_func); -void unsubscribe_dbus_signal(dbus_handle_h handle, guint id); - -GVariant *dbus_handle_make_simple_array(const char *sig, int *param); - -int dbus_handle_broadcast_dbus_signal(const char *path, const char *iface, const char *name, const char *signature, const char *param[]); -int dbus_handle_broadcast_dbus_signal_var(const char *path, const char *iface, const char *name, GVariant *param); - -typedef struct -{ - guint pid; - guint uid; - gchar *unique_name; - gchar *sec_label; -} GDBusCredentials; - -int dbus_connection_get_sender_pid(GDBusConnection *conn, const char * sender); -int dbus_handle_get_sender_pid(dbus_handle_h handle, const char * sender); -int dbus_handle_get_sender_credentials(dbus_handle_h handle, const char *name, GDBusCredentials *creds); -int dbus_handle_watch_name(const char *name, GBusNameAppearedCallback name_appeared_handler, GBusNameVanishedCallback name_vanished_handler, void *user_data); -void dbus_handle_unwatch_name(guint id); -dbus_handle_h dbus_handle_init(GBusType type, const char* bus_name); -char** dbus_handle_get_owner_list(dbus_handle_h handle, const char *bus_name); -void dbush_handle_check_owner_name(dbus_handle_h handle, const char *owner_name); - -#endif diff --git a/src/core/edbus-handler.h b/src/core/edbus-handler.h index b1ec0ed..cdd5571 100644 --- a/src/core/edbus-handler.h +++ b/src/core/edbus-handler.h @@ -21,7 +21,6 @@ #define __FEEDBACKD_EDBUS_HANDLE_H__ #include -#include "core/dbus.h" struct edbus_method { const char *member; diff --git a/src/core/main.c b/src/core/main.c index f2e39cc..213fa10 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -21,10 +21,10 @@ #include #include #include +#include #include "core/log.h" #include "core/common.h" -#include "core/dbus.h" #include "haptic/haptic.h" static GMainLoop *mainloop = NULL; @@ -51,7 +51,7 @@ int main(int argc, char **argv) mainloop = g_main_loop_new(NULL, FALSE); - if (!dbus_handle_init(G_BUS_TYPE_SYSTEM, VIBRATOR_BUS_NAME)) { + if (!dbus_handle_init(G_BUS_TYPE_SYSTEM, VIBRATOR_BUS_NAME, NULL, NULL)) { _E("failed to init dbus connection"); } diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index e1a64e6..a352ec2 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -23,13 +23,14 @@ #include #include #include +#include +#include #include "core/log.h" #include "core/list.h" #include "core/common.h" #include "core/device-idler.h" #include "core/config-parser.h" -#include "core/dbus.h" #include "haptic.h" #define HAPTIC_CONF_PATH "/etc/feedbackd/haptic.conf" @@ -210,7 +211,7 @@ static struct haptic_info *add_haptic_info(const char *sender) info->sender = strdup(sender); DD_LIST_APPEND(haptic_handle_list, info); - info->id_watch = dbus_handle_watch_name(sender, NULL, haptic_name_owner_changed, info); + info->id_watch = dbus_handle_watch_name(sender, NULL, haptic_name_owner_changed, info, NULL); return info; } @@ -223,7 +224,9 @@ static int remove_haptic_info(struct haptic_info *info) DD_LIST_REMOVE(haptic_handle_list, info); DD_LIST_FREE_LIST(info->handle_list); - free(info->sender); + if (info->sender) { + free(info->sender); + } free(info); return 0; -- 2.7.4 From 44bf8b5b63cdb23a8a62daca695b1d277fd80ed6 Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Wed, 4 Apr 2018 21:48:34 +0900 Subject: [PATCH 05/16] Refactor dbus_handle_init into two parts It's to apply a fix in deviced which timing issue happend by telephony. When telephony requests AddPoweroffWait, it fails because dbus in deviced is not ready. Change-Id: I0e0faa9dfe2b56186765903b327ece1018d6b6b0 Signed-off-by: lokilee73 --- src/core/main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/core/main.c diff --git a/src/core/main.c b/src/core/main.c old mode 100644 new mode 100755 index 213fa10..d9adf24 --- a/src/core/main.c +++ b/src/core/main.c @@ -48,12 +48,13 @@ static void sig_usr1(int signo) int main(int argc, char **argv) { int ret; + dbus_handle_h handle = NULL; mainloop = g_main_loop_new(NULL, FALSE); - if (!dbus_handle_init(G_BUS_TYPE_SYSTEM, VIBRATOR_BUS_NAME, NULL, NULL)) { - _E("failed to init dbus connection"); - } + handle = dbus_handle_get_connection(G_BUS_TYPE_SYSTEM, FALSE); + if (!handle) + _E("Fail to get dbus connection");; ret = haptic_probe(); if (ret != 0) { @@ -62,6 +63,12 @@ int main(int argc, char **argv) } haptic_init(); + ret = dbus_handle_request_bus_name(handle, VIBRATOR_BUS_NAME, NULL, NULL); + if (ret <= 0) { + _E("Fail to request bus name"); + dbus_handle_check_owner_name(NULL, VIBRATOR_BUS_NAME); + } + signal(SIGTERM, sig_quit); signal(SIGUSR1, sig_usr1); -- 2.7.4 From d71ff7a4284303eb8195b5e1ec982e7cbffd461f Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Mon, 30 Apr 2018 20:34:27 +0900 Subject: [PATCH 06/16] Fix systemd-assisted dbus activation sequence Change-Id: Ic570da29e8193b56d5c4ab31687743e505d43fe3 Signed-off-by: Hyotaek Shim --- CMakeLists.txt | 1 + packaging/feedbackd.spec | 1 + src/core/main.c | 9 ++++++++- systemd/feedbackd.service | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2c4c8c..8a15676 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ SET(PKG_MODULES gio-unix-2.0 capi-system-info libgdbus + libsystemd ) IF(DRIVER STREQUAL gpio) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index c87d08a..39ff443 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -24,6 +24,7 @@ BuildRequires: pkgconfig(gio-unix-2.0) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-peripheral-io) BuildRequires: pkgconfig(libgdbus) +BuildRequires: pkgconfig(libsystemd) Requires(post): /usr/bin/vconftool diff --git a/src/core/main.c b/src/core/main.c index d9adf24..92fddc8 100755 --- a/src/core/main.c +++ b/src/core/main.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "core/log.h" #include "core/common.h" @@ -45,6 +46,12 @@ static void sig_usr1(int signo) } } +static void dbus_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + _I("sd_notify(READY=1)"); + sd_notify(0, "READY=1"); +} + int main(int argc, char **argv) { int ret; @@ -63,7 +70,7 @@ int main(int argc, char **argv) } haptic_init(); - ret = dbus_handle_request_bus_name(handle, VIBRATOR_BUS_NAME, NULL, NULL); + ret = dbus_handle_request_bus_name(handle, VIBRATOR_BUS_NAME, dbus_name_acquired, NULL); if (ret <= 0) { _E("Fail to request bus name"); dbus_handle_check_owner_name(NULL, VIBRATOR_BUS_NAME); diff --git a/systemd/feedbackd.service b/systemd/feedbackd.service index 8bd1dc9..e8071f7 100644 --- a/systemd/feedbackd.service +++ b/systemd/feedbackd.service @@ -3,7 +3,7 @@ Description=System Vibrator Daemon After=deviced.service [Service] -BusName=org.tizen.system.vibrator +Type=Notify SmackProcessLabel=System ExecStart=/usr/bin/feedbackd Restart=always -- 2.7.4 From 888bce9cc08df301e3c4af5e79c7045f2d97a916 Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Mon, 30 Apr 2018 20:41:30 +0900 Subject: [PATCH 07/16] Add .gitignore Change-Id: I4376ef23bc81e537f4c628cfae66ebd1994f9a7f Signed-off-by: Hyotaek Shim --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9306ae6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +cscope.files +cscope.out +tags -- 2.7.4 From c266e77cde725d1364540bc7f8e09bfb6ba7c295 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 30 Apr 2018 18:39:48 +0900 Subject: [PATCH 08/16] haptic: Remove convert_magnitude_by_conf Change-Id: I47a8cd4049fd9e0b24d3f99bd0267a23854f11e9 Signed-off-by: pr.jung --- CMakeLists.txt | 2 - packaging/feedbackd.spec | 33 ------------ src/haptic/conf/haptic-level3.conf | 15 ------ src/haptic/conf/haptic-level6.conf | 24 --------- src/haptic/haptic.c | 100 +++++++------------------------------ 5 files changed, 18 insertions(+), 156 deletions(-) delete mode 100644 src/haptic/conf/haptic-level3.conf delete mode 100644 src/haptic/conf/haptic-level6.conf diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a15676..273646c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,5 @@ INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/systemd/ DESTINATION lib/systemd/system FILES_MATCHING PATTERN "feedbackd.service") INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.vibrator.service DESTINATION /usr/share/dbus-1/system-services) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/haptic/conf/haptic-level3.conf DESTINATION /etc/feedbackd) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/haptic/conf/haptic-level6.conf DESTINATION /etc/feedbackd) ADD_SUBDIRECTORY(src/auto-test) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index 39ff443..8e38701 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -31,9 +31,6 @@ Requires(post): /usr/bin/vconftool Requires: %{name}-compat = %{version}-%{release} Recommends: %{name}-driver-standard = %{version}-%{release} -Requires: configuration-compat = %{version}-%{release} -Recommends: %{name}-conf-level6 = %{version}-%{release} - %description feedback daemon @@ -95,20 +92,6 @@ Conflicts: %{name}-driver-standard %description driver-circle Feedbackd binaries with circle plugin. Required by main feedbackd package -%package conf-level3 -Summary: Feedbackd configuration file -Provides: configuration-compat = %{version}-%{release} -Conflicts: %{name}-conf-level6 -%description conf-level3 -Feedbackd configuration file. - -%package conf-level6 -Summary: Feedbackd configuration file -Provides: configuration-compat = %{version}-%{release} -Conflicts: %{name}-conf-level3 -%description conf-level6 -Feedbackd configuration file. - %package auto-test Summary: Feedbackd auto test tool Group: System/Utilities @@ -280,12 +263,6 @@ if [ "$1" == "0" ]; then systemctl stop feedbackd.service fi -%post conf-level3 -mv %{_sysconfdir}/feedbackd/haptic-level3.conf %{_sysconfdir}/feedbackd/haptic.conf - -%post conf-level6 -mv %{_sysconfdir}/feedbackd/haptic-level6.conf %{_sysconfdir}/feedbackd/haptic.conf - %files -n feedbackd %manifest %{name}.manifest %license LICENSE.Apache-2.0 @@ -319,16 +296,6 @@ mv %{_sysconfdir}/feedbackd/haptic-level6.conf %{_sysconfdir}/feedbackd/haptic.c %manifest %{name}.manifest %{_bindir}/feedbackd.circle -%files conf-level3 -%license LICENSE.Apache-2.0 -%manifest %{name}.manifest -%config %{_sysconfdir}/feedbackd/haptic-level3.conf - -%files conf-level6 -%license LICENSE.Apache-2.0 -%manifest %{name}.manifest -%config %{_sysconfdir}/feedbackd/haptic-level6.conf - %files auto-test %license LICENSE.Apache-2.0 %manifest %{name}.manifest diff --git a/src/haptic/conf/haptic-level3.conf b/src/haptic/conf/haptic-level3.conf deleted file mode 100644 index 6e52318..0000000 --- a/src/haptic/conf/haptic-level3.conf +++ /dev/null @@ -1,15 +0,0 @@ -[Haptic] -# level -# how much does the vibration level to subdivide. -# The max value of vibration level fixed at 100. -# The min value of vibration level fixed at 0. -level=3 - -[level0] -value=0 - -[level1] -value=58 - -[level2] -value=100 diff --git a/src/haptic/conf/haptic-level6.conf b/src/haptic/conf/haptic-level6.conf deleted file mode 100644 index 84271f1..0000000 --- a/src/haptic/conf/haptic-level6.conf +++ /dev/null @@ -1,24 +0,0 @@ -[Haptic] -# level -# how much does the vibration level to subdivide. -# The max value of vibration level fixed at 100. -# The min value of vibration level fixed at 0. -level=6 - -[level0] -value=0 - -[level1] -value=20 - -[level2] -value=40 - -[level3] -value=60 - -[level4] -value=80 - -[level5] -value=100 diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index a352ec2..505a6de 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -33,7 +33,6 @@ #include "core/config-parser.h" #include "haptic.h" -#define HAPTIC_CONF_PATH "/etc/feedbackd/haptic.conf" #define SIGNAL_CHANGE_HARDKEY "ChangeHardkey" #define SIGNAL_POWEROFF_STATE "ChangeState" #define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator" @@ -45,6 +44,8 @@ #define HARDKEY_VIB_DURATION 30 #define HAPTIC_FEEDBACK_STEP 20 #define DEFAULT_FEEDBACK_LEVEL 3 +#define HIGH_FEEDBACK_LEVEL 100 +#define LOW_FEEDBACK_LEVEL 0 /* power on, power off vibration variable */ #define POWER_ON_VIB_DURATION 300 @@ -85,8 +86,6 @@ static enum haptic_type h_type; static bool haptic_disabled; struct haptic_config { - int level; - int *level_arr; int sound_capture; }; @@ -140,28 +139,9 @@ static int haptic_module_load(void) return 0; } -static int convert_magnitude_by_conf(int level) -{ - int i, step; - - assert(level >= 0 && level <= 100); - - step = 100 / (haptic_conf.level-1); - for (i = 0; i < haptic_conf.level; ++i) { - if (level <= i*step) { - _D("level changed : %d -> %d", level, haptic_conf.level_arr[i]); - return haptic_conf.level_arr[i]; - } - } - - _D("play default level"); - return DEFAULT_FEEDBACK_LEVEL * HAPTIC_FEEDBACK_STEP; -} - GVariant *hdbus_get_count(GDBusConnection *conn, const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) - { int ret, val; @@ -349,12 +329,11 @@ GVariant *hdbus_vibrate_monotone(GDBusConnection *conn, g_variant_get(param, "(uiii)", &handle, &duration, &level, &priority); - /* convert as per conf value */ - level = convert_magnitude_by_conf(level); - if (level < 0) { - ret = -EINVAL; - goto exit; - } + if (level < LOW_FEEDBACK_LEVEL) + level = LOW_FEEDBACK_LEVEL; + else if (level > HIGH_FEEDBACK_LEVEL) + level = HIGH_FEEDBACK_LEVEL; + if (priority < PRIORITY_MIN) priority = PRIORITY_MIN; else if (priority > PRIORITY_TOP) @@ -388,12 +367,10 @@ GVariant *hdbus_vibrate_buffer(GDBusConnection *conn, data = g_variant_get_fixed_array(pvar, &size, sizeof(char)); g_variant_unref(pvar); - /* convert as per conf value */ - level = convert_magnitude_by_conf(level); - if (level < 0) { - ret = -EINVAL; - goto exit; - } + if (level < LOW_FEEDBACK_LEVEL) + level = LOW_FEEDBACK_LEVEL; + else if (level > HIGH_FEEDBACK_LEVEL) + level = HIGH_FEEDBACK_LEVEL; ret = h_ops->vibrate_buffer(handle, data, iteration, level, priority, &e_handle); if (ret >= 0) @@ -430,12 +407,10 @@ GVariant *hdbus_vibrate_effect(GDBusConnection *conn, g_variant_get(param, "(usii)", &handle, &pattern, &level, &priority); - /* convert as per conf value */ - level = convert_magnitude_by_conf(level); - if (level < 0) { - ret = -EINVAL; - goto exit; - } + if (level < LOW_FEEDBACK_LEVEL) + level = LOW_FEEDBACK_LEVEL; + else if (level > HIGH_FEEDBACK_LEVEL) + level = HIGH_FEEDBACK_LEVEL; if (priority < PRIORITY_MIN) priority = PRIORITY_MIN; else if (priority > PRIORITY_TOP) @@ -742,6 +717,7 @@ static void sound_capturing_cb(keynode_t *key, void *data) haptic_start(); } +/* Left for the case of sound_capture in use static int parse_section(struct parse_result *result, void *user_data, int index) { struct haptic_config *conf = (struct haptic_config *)user_data; @@ -754,21 +730,6 @@ static int parse_section(struct parse_result *result, void *user_data, int index if (MATCH(result->name, "sound_capture")) { conf->sound_capture = atoi(result->value); - } else if (MATCH(result->name, "level")) { - conf->level = atoi(result->value); - if (conf->level < 0 || conf->level >= INT_MAX - 1) { - _E("You must set level with positive number in integer range"); - return -EINVAL; - } - conf->level_arr = calloc(sizeof(int), conf->level); - if (!conf->level_arr) { - _E("failed to allocate memory for level"); - return -errno; - } - } else if (MATCH(result->name, "value")) { - if (index < 0) - return -EINVAL; - conf->level_arr[index] = atoi(result->value); } return 0; @@ -776,10 +737,7 @@ static int parse_section(struct parse_result *result, void *user_data, int index static int haptic_load_config(struct parse_result *result, void *user_data) { - struct haptic_config *conf = (struct haptic_config *)user_data; - char name[NAME_MAX]; int ret; - static int index; if (!result) return 0; @@ -787,7 +745,7 @@ static int haptic_load_config(struct parse_result *result, void *user_data) if (!result->section || !result->name || !result->value) return 0; - /* Parsing 'Haptic' section */ + // Parsing 'Haptic' section if (MATCH(result->section, "Haptic")) { ret = parse_section(result, user_data, -1); if (ret < 0) { @@ -797,22 +755,10 @@ static int haptic_load_config(struct parse_result *result, void *user_data) goto out; } - /* Parsing 'Level' section */ - for (index = 0; index < conf->level; ++index) { - snprintf(name, sizeof(name), "level%d", index); - if (MATCH(result->section, name)) { - ret = parse_section(result, user_data, index); - if (ret < 0) { - _E("failed to parse [level] section : %d", ret); - return ret; - } - goto out; - } - } - out: return 0; } +*/ static const dbus_method_s hdbus_methods[] = { { "GetCount", NULL, "i", hdbus_get_count }, @@ -854,13 +800,6 @@ void haptic_init(void) { int r; - /* get haptic data from configuration file */ - r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf); - if (r < 0) { - _E("failed to load configuration file(%s) : %d", HAPTIC_CONF_PATH, r); - safe_free(haptic_conf.level_arr); - } - /* init dbus interface */ r = dbus_handle_register_dbus_object(NULL, VIBRATOR_PATH_HAPTIC, &dbus_interface); if (r < 0) @@ -907,9 +846,6 @@ void haptic_exit(void) unsubscribe_dbus_signal(NULL, id_sig_change_hardkey); unsubscribe_dbus_signal(NULL, id_sig_pwr_off_state); - /* release haptic data memory */ - safe_free(haptic_conf.level_arr); - if (!CHECK_VALID_OPS(h_ops, r)) return; -- 2.7.4 From 65c2f634edc2646d483286e3532af3967710b8ea Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Thu, 17 May 2018 13:47:19 +0900 Subject: [PATCH 09/16] dbus-policy: change to default deny policy Change-Id: I8849c0e73c766e9b11ba004c12b7e0b5fff48fca Signed-off-by: sanghyeok.oh --- scripts/feedbackd.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/feedbackd.conf b/scripts/feedbackd.conf index 05f4ece..2ded9e1 100755 --- a/scripts/feedbackd.conf +++ b/scripts/feedbackd.conf @@ -12,6 +12,7 @@ + Date: Wed, 20 Jun 2018 18:08:57 +0900 Subject: [PATCH 10/16] haptic: Remove unused code - Remove standard_mix.c Change-Id: I8d6a567da78bf472a7a0ca72265a6325b497d733 Signed-off-by: pr.jung --- CMakeLists.txt | 2 - packaging/feedbackd.spec | 2 - src/haptic/standard-mix.c | 1085 --------------------------------------------- 3 files changed, 1089 deletions(-) delete mode 100644 src/haptic/standard-mix.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 273646c..3eeb80b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,6 @@ ELSEIF(DRIVER STREQUAL standard) SET(SRCS ${SRCS} src/haptic/standard.c src/haptic/standard-vibcore.c) ELSEIF(DRIVER STREQUAL circle) SET(SRCS ${SRCS} src/haptic/circle.c src/haptic/standard-vibcore.c) -ELSEIF(DRIVER STREQUAL mix) - SET(SRCS ${SRCS} src/haptic/standard-mix.c) ENDIF() INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index 8e38701..d33ccfb 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -3,8 +3,6 @@ %bcond_with wayland %bcond_with emulator -%define standard_mix off - Name: feedbackd Summary: Feedbackd Version: 1.0.0 diff --git a/src/haptic/standard-mix.c b/src/haptic/standard-mix.c deleted file mode 100644 index 578a700..0000000 --- a/src/haptic/standard-mix.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * feedbackd - * - * Copyright (c) 2016 - 2017 Samsung Electronics Co., Ltd. - * - * 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 - -#include "core/log.h" -#include "core/list.h" -#include "core/config-parser.h" -#include "haptic.h" - -#define MAX_MAGNITUDE 0xFFFF -#define PERIODIC_MAX_MAGNITUDE 0x7FFF /* 0.5 * MAX_MAGNITUDE */ -#define RUMBLE_MAX_MAGNITUDE 0xFFFF - -#define DEV_INPUT "/dev/input" -#define EVENT "event" - -#define BITS_PER_LONG (sizeof(long) * 8) -#define OFF(x) ((x)%BITS_PER_LONG) -#define BIT(x) (1UL<> OFF(bit)) & 1) - -#define MAX_DATA 16 -#define FF_INFO_MAGIC 0xDEADFEED - -#define VIBRATION_CONF_PATH "/usr/share/feedback/vibration_mix.conf" -#define VIBRATION_DURATION_CONF_PATH "/usr/share/feedback/vibration_duration.conf" -#define VIBRATION_WAITING_CONF_PATH "/usr/share/feedback/vibration_waiting.conf" - -struct ff_info_header { - unsigned int magic; - int iteration; - int ff_info_data_count; -}; - -struct ff_info_data { - int type;/* play, stop etc */ - int magnitude; /* strength */ - int length; /* in ms for stop, play*/ -}; - -struct ff_info_buffer { - struct ff_info_header header; - struct ff_info_data data[MAX_DATA]; -}; - -struct ff_info { - int handle; - guint timer; - struct ff_effect effect; - struct ff_info_buffer *ffinfobuffer; - int currentindex; -}; - -struct vibration_table { - char *pattern; - char *duration; - char *waiting; -}; - -struct vibration_config { - char *pattern; - int *data; - int data_len; -}; - -struct haptic_data { - unsigned int handle; - int *duration_config; - int *waiting_config; - int level; - int priority; - int duration_len; - int waiting_len; - int index; - bool stop; -}; - -static int ff_fd; -static dd_list *ff_list; -static dd_list *handle_list; -static dd_list *vib_conf_list; -static dd_list *vib_duration_conf_list; -static dd_list *vib_waiting_conf_list; -static guint duration_timer; -static char ff_path[PATH_MAX]; -static int unique_number; - -struct ff_info *read_from_list(int handle) -{ - struct ff_info *temp; - dd_list *elem; - - DD_LIST_FOREACH(ff_list, elem, temp) { - if (temp->handle == handle) - return temp; - } - return NULL; -} - -static bool check_valid_handle(struct ff_info *info) -{ - struct ff_info *temp; - dd_list *elem; - - DD_LIST_FOREACH(ff_list, elem, temp) { - if (temp == info) - break; - } - - if (!temp) - return false; - return true; -} - -static bool check_fd(int *fd) -{ - int ffd; - - if (*fd > 0) - return true; - - ffd = open(ff_path, O_RDWR); - if (ffd < 0) - return false; - - *fd = ffd; - return true; -} - -static int ff_stop(int fd, struct ff_effect *effect); -static Eina_Bool timer_cb(void *data) -{ - struct ff_info *info = (struct ff_info *)data; - - if (!info) - return G_SOURCE_REMOVE; - - if (!check_valid_handle(info)) - return G_SOURCE_REMOVE; - - _I("stop vibration by timer : id(%d)", info->effect.id); - - /* stop previous vibration */ - ff_stop(ff_fd, &info->effect); - - /* reset timer */ - info->timer = NULL; - - return G_SOURCE_REMOVE; -} - -static int ff_find_device(void) -{ - DIR *dir; - struct dirent *dent; - char ev_path[PATH_MAX]; - unsigned long features[1+FF_MAX/sizeof(unsigned long)]; - int fd, ret; - - dir = opendir(DEV_INPUT); - if (!dir) - return -errno; - - while (1) { - dent = readdir(dir); - if (dent == NULL) - break; - - if (dent->d_type == DT_DIR || - !strstr(dent->d_name, "event")) - continue; - - snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name); - - fd = open(ev_path, O_RDWR); - if (fd < 0) - continue; - - /* get force feedback device */ - memset(features, 0, sizeof(features)); - ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features); - if (ret == -1) { - close(fd); - continue; - } - - if (test_bit(FF_CONSTANT, features)) - _D("%s type : constant", ev_path); - if (test_bit(FF_PERIODIC, features)) - _D("%s type : periodic", ev_path); - if (test_bit(FF_SPRING, features)) - _D("%s type : spring", ev_path); - if (test_bit(FF_FRICTION, features)) - _D("%s type : friction", ev_path); - if (test_bit(FF_RUMBLE, features)) - _D("%s type : rumble", ev_path); - - if (test_bit(FF_RUMBLE, features)) { - memcpy(ff_path, ev_path, strlen(ev_path)); - close(fd); - closedir(dir); - return 0; - } - - close(fd); - } - - closedir(dir); - return -1; -} - -static int ff_init_effect(struct ff_effect *effect) -{ - if (!effect) - return -EINVAL; - - /*Only rumble supported as of now*/ - effect->type = FF_RUMBLE; - effect->replay.length = 0; - effect->replay.delay = 10; - effect->id = -1; - effect->u.rumble.strong_magnitude = 0x8000; - effect->u.rumble.weak_magnitude = 0xc000; - - return 0; -} - -static int ff_set_effect(struct ff_effect *effect, int length, int level) -{ - double magnitude; - - if (!effect) - return -EINVAL; - - magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX; - magnitude *= RUMBLE_MAX_MAGNITUDE; - - _I("info : magnitude(%d) length(%d)", (int)magnitude, length); - - /* set member variables in effect struct */ - effect->u.rumble.strong_magnitude = (int)magnitude; - effect->replay.length = length; /* length millisecond */ - - return 0; -} - -static int ff_play(int fd, struct ff_effect *effect) -{ - struct input_event play; - int ret; - - if (fd < 0 || !effect) { - if (fd < 0) - _E("fail to check fd"); - else - _E("fail to check effect"); - return -EINVAL; - } - - /* upload an effect */ - if (ioctl(fd, EVIOCSFF, effect) == -1) { - _E("fail to ioctl"); - return -errno; - } - - /* play vibration*/ - play.type = EV_FF; - play.code = effect->id; - play.value = 1; /* 1 : PLAY, 0 : STOP */ - - ret = write(fd, (const void *)&play, sizeof(play)); - if (ret == -1) { - _E("fail to write"); - return -errno; - } - - return 0; -} - -static int ff_stop(int fd, struct ff_effect *effect) -{ - struct input_event stop; - int ret; - - if (fd < 0) - return -EINVAL; - - /* Stop vibration */ - stop.type = EV_FF; - stop.code = effect->id; - stop.value = 0; /* 1 : PLAY, 0 : STOP */ - ret = write(fd, (const void *)&stop, sizeof(stop)); - if (ret == -1) - return -errno; - - /* removing an effect from the device */ - if (ioctl(fd, EVIOCRMFF, effect->id) == -1) - return -errno; - - /* reset effect id */ - effect->id = -1; - - return 0; -} - -/* START: Haptic Module APIs */ -static int get_device_count(int *count) -{ - /* suppose there is just one haptic device */ - if (count) - *count = 1; - - return 0; -} - -static int open_device(int device_index, int *device_handle) -{ - struct ff_info *info; - int n; - bool found = false; - dd_list *elem; - - if (!device_handle) - return -EINVAL; - - /* if it is the first element */ - n = DD_LIST_LENGTH(ff_list); - if (n == 0 && !ff_fd) { - _I("First element: open ff driver"); - /* open ff driver */ - ff_fd = open(ff_path, O_RDWR); - if (ff_fd < 0) { - _E("Failed to open %s : %d", ff_path, errno); - return -errno; - } - } - - /* allocate memory */ - info = calloc(sizeof(struct ff_info), 1); - if (!info) { - _E("Failed to allocate memory : %d", errno); - return -errno; - } - - /* initialize ff_effect structure */ - ff_init_effect(&info->effect); - - if (unique_number == INT_MAX) - unique_number = 0; - - while (found != true) { - ++unique_number; - elem = DD_LIST_FIND(handle_list, (gpointer)(long)unique_number); - if (!elem) - found = true; - } - - info->handle = unique_number; - - /* add info to local list */ - DD_LIST_APPEND(ff_list, info); - DD_LIST_APPEND(handle_list, (gpointer)(long)info->handle); - - *device_handle = info->handle; - return 0; -} - -static int close_device(int device_handle) -{ - struct ff_info *info; - int r, n; - - info = read_from_list(device_handle); - if (!info) - return -EINVAL; - - if (!check_valid_handle(info)) - return -EINVAL; - - if (!check_fd(&ff_fd)) - return -ENODEV; - - /* stop vibration */ - r = ff_stop(ff_fd, &info->effect); - if (r < 0) - _I("already stopped or failed to stop effect : %d", r); - - /* unregister existing timer */ - if (r >= 0 && info->timer) { - _D("device handle %d is closed and timer deleted", device_handle); - g_source_remove(info->timer); - info->timer = NULL; - } - - DD_LIST_REMOVE(handle_list, (gpointer)(long)info->handle); - - safe_free(info->ffinfobuffer); - /* remove info from local list */ - DD_LIST_REMOVE(ff_list, info); - safe_free(info); - - /* if it is the last element */ - n = DD_LIST_LENGTH(ff_list); - if (n == 0 && ff_fd) { - _I("Last element: close ff driver"); - /* close ff driver */ - close(ff_fd); - ff_fd = 0; - } - - return 0; -} - -static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) -{ - struct ff_info *info; - int ret; - - info = read_from_list(device_handle); - if (!info) { - _E("fail to check list"); - return -EINVAL; - } - - if (!check_valid_handle(info)) { - _E("fail to check handle"); - return -EINVAL; - } - - if (!check_fd(&ff_fd)) - return -ENODEV; - - /* Zero(0) is the infinitely vibration value */ - if (duration == HAPTIC_MODULE_DURATION_UNLIMITED) - duration = 0; - - /* unregister existing timer */ - if (info->timer) { - ff_stop(ff_fd, &info->effect); - g_source_remove(info->timer); - info->timer = NULL; - } - - /* set effect as per arguments */ - ff_init_effect(&info->effect); - ret = ff_set_effect(&info->effect, duration, feedback); - if (ret < 0) { - _E("failed to set effect(duration:%d, feedback:%d) : %d", - duration, feedback, ret); - return ret; - } - - /* play effect as per arguments */ - ret = ff_play(ff_fd, &info->effect); - if (ret < 0) { - _E("failed to play haptic effect(fd:%d id:%d) : %d", - ff_fd, info->effect.id, ret); - return ret; - } - - /* register timer */ - if (duration) { - info->timer = g_timeout_add(duration, timer_cb, info); - if (!info->timer) - _E("Failed to add timer callback"); - } - - _D("device handle %d effect id : %d %dms", device_handle, info->effect.id, duration); - if (effect_handle) - *effect_handle = info->effect.id; - - return 0; -} - -static gboolean _buffer_play(void *cbdata) -{ - struct ff_info *info = (struct ff_info *)cbdata; - struct ff_info_header *header = &info->ffinfobuffer->header; - struct ff_info_data *data = info->ffinfobuffer->data; - int index = info->currentindex; - int play_type = (index < header->ff_info_data_count) ? data[index].type : 0; - int length = (index < header->ff_info_data_count) ? data[index].length : 1; - int ret; - - ff_set_effect(&info->effect, length, 1); - if (play_type != 0) { - _D("Going to play for %d ms", length); - ret = ff_play(ff_fd, &info->effect); - if (ret < 0) - _D("Failed to play the effect %d", ret); - } else { - _D("Going to stop for %d ms", length); - ret = ff_stop(ff_fd, &info->effect); - if (ret < 0) - _D("Failed to stop the effect %d", ret); - } - - if (info->currentindex < header->ff_info_data_count) { - info->currentindex++; - info->timer = g_timeout_add(length, _buffer_play, info); - } else { - --header->iteration; - if (header->iteration > 0) { - info->currentindex = 0; - info->timer = g_timeout_add(0, _buffer_play, info); - } else - info->timer = NULL; - } - - return G_SOURCE_REMOVE; -} - -static void print_buffer(const unsigned char *vibe_buffer) -{ - struct ff_info_buffer fb; - int i = 0; - memcpy(&fb.header, vibe_buffer, sizeof(struct ff_info_header)); - memcpy(&fb.data, (unsigned char *)vibe_buffer+sizeof(struct ff_info_header), - sizeof(struct ff_info_data) * fb.header.ff_info_data_count); - _D("\nMagic %x\niteration %d\ncount %d\n", fb.header.magic, - fb.header.iteration, fb.header.ff_info_data_count); - - for (i = 0; i < fb.header.ff_info_data_count; i++) - _D("type %d\nmagn 0x%x\nlen %d\n", fb.data[i].type, - fb.data[i].magnitude, fb.data[i].length); -} - -static int vibrate_custom_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - struct ff_info *info; - struct ff_info_header *header; - struct ff_info_data *data; - - info = read_from_list(device_handle); - if (!info) - return -EINVAL; - - if (!check_valid_handle(info)) - return -EINVAL; - - if (!check_fd(&ff_fd)) - return -ENODEV; - - if (!info->ffinfobuffer) - info->ffinfobuffer = (struct ff_info_buffer *)calloc(sizeof(struct ff_info_buffer), 1); - if (!info->ffinfobuffer) - return -ENOMEM; - - header = &info->ffinfobuffer->header; - data = info->ffinfobuffer->data; - - memcpy(header, vibe_buffer, sizeof(struct ff_info_header)); - if (header->ff_info_data_count < 0 || header->ff_info_data_count > MAX_DATA) - return -EINVAL; - - memcpy(data, vibe_buffer+sizeof(struct ff_info_header), sizeof(struct ff_info_data) * header->ff_info_data_count); - - info->currentindex = 0; - if (info->timer) - g_source_remove(info->timer); - - if (header->iteration > 0) - _buffer_play(info); - - return 0; -} - -static gboolean haptic_duration_play(void *data) -{ - struct haptic_data *h_data; - double time; - int ret = 0; - int index; - unsigned int v_handle; - int level; - int priority; - int duration; - - - if (!data) - return G_SOURCE_REMOVE; - - if (duration_timer) { - g_source_remove(duration_timer); - duration_timer = 0; - } - - h_data = (struct haptic_data *)data; - if (h_data->stop) { - h_data->stop = false; - free(h_data); - return G_SOURCE_REMOVE; - } - - index = h_data->index; - v_handle = h_data->handle; - level = h_data->level; - priority = h_data->priority; - - if (!h_data->duration_config[index]) { - free(h_data); - return G_SOURCE_REMOVE; - } - - duration = h_data->duration_config[index]; - - h_data->index++; - if (h_data->index > h_data->duration_len - 1) - free(h_data); - else { - if (h_data->index > h_data->waiting_len - 1) - time = duration; - else - time = duration + h_data->waiting_config[index]; - - /*duration_timer = ecore_timer_add(time/1000.0f, haptic_duration_play, (void *)h_data);*/ - duration_timer = g_timeout_add(time, haptic_duration_play, (void *)h_data); - _D("timer: %d", time); - } - - _D("duration: %d", duration); - - ret = vibrate_monotone(v_handle, duration, level, priority, NULL); - if (ret != 0) { - _D("auto stop vibration"); - if (h_data) - h_data->stop = true; - } - return G_SOURCE_REMOVE; -} - -static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - int magic = 0; - - if (!device_handle) - return -EINVAL; - - if (vibe_buffer) - magic = *(int *)vibe_buffer; - - if (magic == FF_INFO_MAGIC) { - print_buffer(vibe_buffer); - return vibrate_custom_buffer(device_handle, vibe_buffer, iteration, feedback, priority, effect_handle); - } else - return vibrate_monotone(device_handle, 300, feedback, priority, effect_handle); -} - -static int vibrate_effect(int device_handle, const char *pattern, int feedback, int priority) -{ - dd_list *elem1, *elem2; - struct vibration_table *conf_table; - struct vibration_config *conf_duration, *conf_waiting; - struct haptic_data *data; - char *duration = NULL, *waiting = NULL; - int len1, len2; - - if (!device_handle) - return -EINVAL; - - if (!pattern) - return -EINVAL; - - len1 = strlen(pattern) + 1; - DD_LIST_FOREACH(vib_conf_list, elem1, conf_table) { - if (!conf_table->pattern) - continue; - if (strncmp(conf_table->pattern, pattern, len1)) - continue; - duration = conf_table->duration; - waiting = conf_table->waiting; - break; - } - - if (!duration) - return -ENOTSUP; - - len1 = strlen(duration) + 1; - if (!waiting) - len2 = 0; - else - len2 = strlen(waiting) + 1; - DD_LIST_FOREACH(vib_duration_conf_list, elem1, conf_duration) { - if (!conf_duration->pattern) - continue; - if (strncmp(conf_duration->pattern, duration, len1)) - continue; - - data = (struct haptic_data *)malloc(sizeof(struct haptic_data)); - if (!data) { - _E("fail to alloc"); - return -ENOMEM; - } - data->duration_len = 0; - data->waiting_len = 0; - - DD_LIST_FOREACH(vib_waiting_conf_list, elem2, conf_waiting) { - if (!waiting) - break; - if (!conf_waiting->pattern) - continue; - if (strncmp(conf_waiting->pattern, waiting, len2)) - continue; - data->waiting_config = conf_waiting->data; - data->waiting_len = conf_waiting->data_len; - break; - } - data->handle = device_handle; - data->level = feedback; - data->priority = priority; - data->duration_config = conf_duration->data; - data->duration_len = conf_duration->data_len; - data->index = 0; - - haptic_duration_play((void *)data); - break; - } - - return 0; -} - -static int is_supported(const char *pattern) -{ - dd_list *elem; - struct vibration_table *conf; - int ret = 0; - int len; - - if (!pattern) - return -EINVAL; - - len = strlen(pattern) + 1; - DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern) - continue; - if (!strncmp(conf->pattern, pattern, len)) { - ret = true; - break; - } - } - - return ret; -} - -static int stop_device(int device_handle) -{ - struct ff_info *info; - int r; - - info = read_from_list(device_handle); - if (!info) - return -EINVAL; - - if (!check_valid_handle(info)) - return -EINVAL; - - if (!check_fd(&ff_fd)) - return -ENODEV; - - /* stop effect */ - r = ff_stop(ff_fd, &info->effect); - if (r < 0) - _E("failed to stop effect(id:%d) : %d", info->effect.id, r); - - /* unregister existing timer */ - if (r >= 0 && info->timer) { - g_source_remove(info->timer); - info->timer = NULL; - } - - return 0; -} - -static int get_device_state(int device_index, int *effect_state) -{ - struct ff_info *info; - dd_list *elem; - int status = false; - - if (!effect_state) - return -EINVAL; - - /* suppose there is just one haptic device */ - DD_LIST_FOREACH(ff_list, elem, info) { - if (info->effect.id >= 0) { - status = true; - break; - } - } - - *effect_state = status; - return 0; -} - -static int create_effect(unsigned char *vibe_buffer, int max_bufsize, const haptic_module_effect_element *elem_arr, int max_elemcnt) -{ - _E("Not supported feature"); - return -EACCES; -} - -static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) -{ - _E("Not supported feature"); - return -EACCES; -} - -static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) -{ - _E("Not supported feature"); - return -EACCES; -} -/* END: Haptic Module APIs */ - -static const struct haptic_plugin_ops default_plugin = { - .get_device_count = get_device_count, - .open_device = open_device, - .close_device = close_device, - .vibrate_monotone = vibrate_monotone, - .vibrate_buffer = vibrate_buffer, - .vibrate_effect = vibrate_effect, - .is_supported = is_supported, - .stop_device = stop_device, - .get_device_state = get_device_state, - .create_effect = create_effect, - .get_buffer_duration = get_buffer_duration, - .convert_binary = convert_binary, -}; - -static int vibration_duration_load_config(struct parse_result *result, void *user_data) -{ - struct vibration_config *conf; - char *value; - char *check; - int count = 0; - int len; - int i; - - if (!result) - return 0; - - if (!MATCH(result->section, "Vibration")) - return 0; - - - if (!result->name || !result->value) - return 0; - - conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config)); - if (!conf) { - _E("fail to alloc"); - return -ENOMEM; - } - - conf->pattern = strdup(result->name); - if (!conf->pattern) - _E("fail to copy %s pattern data", result->name); - - value = result->value; - - if (!value) - len = 0; - else - len = strlen(value); - - if (len == 0) { - DD_LIST_APPEND(vib_duration_conf_list, conf); - return 0; - } - - check = strchr(value, ','); - while (check != NULL) { - count++; - check = strchr(check + 1, ','); - } - - int *duration = (int *)malloc((count + 1) * sizeof(int)); - for (i = 0; i <= count; i++) { - duration[i] = 0; - check = strchr(value, ','); - if (check) { - *check = '\0'; - duration[i] = strtol(value, NULL, 10); - value = check + 1; - } else { - duration[i] = strtol(value, NULL, 10); - break; - } - if (duration[i] == 0) - break; - } - conf->data = duration; - conf->data_len = count + 1; - - DD_LIST_APPEND(vib_duration_conf_list, conf); - - return 0; -} - -static int vibration_waiting_load_config(struct parse_result *result, void *user_data) -{ - struct vibration_config *conf; - char *value; - char *check; - int count = 0; - int len; - int i; - - if (!result) - return 0; - - if (!MATCH(result->section, "Vibration")) - return 0; - - - if (!result->name || !result->value) - return 0; - - conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config)); - if (!conf) { - _E("fail to alloc"); - return -ENOMEM; - } - - conf->pattern = strdup(result->name); - if (!conf->pattern) - _E("fail to copy %s pattern data", result->name); - - value = result->value; - - if (!value) - len = 0; - else - len = strlen(value); - - if (len == 0) { - DD_LIST_APPEND(vib_waiting_conf_list, conf); - return 0; - } - - check = strchr(value, ','); - while (check != NULL) { - count++; - check = strchr(check + 1, ','); - } - - int *waiting = (int *)malloc((count + 1) * sizeof(int)); - for (i = 0; i <= count; i++) { - waiting[i] = 0; - check = strchr(value, ','); - if (check) { - *check = '\0'; - waiting[i] = strtol(value, NULL, 10); - value = check + 1; - } else { - waiting[i] = strtol(value, NULL, 10); - break; - } - if (waiting[i] == 0) - break; - } - conf->data = waiting; - conf->data_len = count + 1; - - DD_LIST_APPEND(vib_waiting_conf_list, conf); - - return 0; -} - -static int vibration_table_load_config(struct parse_result *result, void *user_data) -{ - struct vibration_table *conf; - char *value; - char *check; - int len; - - if (!result) - return 0; - - if (!MATCH(result->section, "Vibration")) - return 0; - - - if (!result->name || !result->value) - return 0; - - conf = (struct vibration_table *)calloc(1, sizeof(struct vibration_table)); - if (!conf) { - _E("fail to alloc"); - return -ENOMEM; - } - - conf->pattern = strdup(result->name); - if (!conf->pattern) - _E("fail to copy %s pattern data", result->name); - - value = result->value; - - if (!value) - len = 0; - else - len = strlen(value); - - if (len == 0) { - DD_LIST_APPEND(vib_conf_list, conf); - return 0; - } - - check = strchr(value, ','); - - if (check) { - *check = '\0'; - conf->duration = strdup(value); - value = check + 1; - conf->waiting = strdup(value); - } else - conf->duration = strdup(value); - - DD_LIST_APPEND(vib_conf_list, conf); - - return 0; -} - -static bool is_valid(void) -{ - int ret; - - ret = ff_find_device(); - if (ret < 0) { - _E("Do not support standard haptic device"); - return false; - } - ret = config_parse(VIBRATION_CONF_PATH, vibration_table_load_config, NULL); - if (ret < 0) - _E("failed to load configuration file(%s) : %d", VIBRATION_DURATION_CONF_PATH, ret); - ret = config_parse(VIBRATION_DURATION_CONF_PATH, vibration_duration_load_config, NULL); - if (ret < 0) - _E("failed to load configuration file(%s) : %d", VIBRATION_DURATION_CONF_PATH, ret); - ret = config_parse(VIBRATION_WAITING_CONF_PATH, vibration_waiting_load_config, NULL); - if (ret < 0) - _E("failed to load configuration file(%s) : %d", VIBRATION_WAITING_CONF_PATH, ret); - - _I("Support standard haptic device"); - return true; -} - -static const struct haptic_plugin_ops *load(void) -{ - return &default_plugin; -} - -static const struct haptic_ops std_ops = { - .type = HAPTIC_STANDARD, - .is_valid = is_valid, - .load = load, -}; - -HAPTIC_OPS_REGISTER(&std_ops) -- 2.7.4 From d5b1f88b401a759f55000e60529774847742a37f Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Fri, 29 Jun 2018 16:56:45 +0900 Subject: [PATCH 11/16] Minor fix: Type=Notify -> Type=notify Change-Id: I1a9c43235e9d063711ac8561cf01d932d27141cc Signed-off-by: Hyotaek Shim --- systemd/feedbackd.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/feedbackd.service b/systemd/feedbackd.service index e8071f7..5b412e6 100644 --- a/systemd/feedbackd.service +++ b/systemd/feedbackd.service @@ -3,7 +3,7 @@ Description=System Vibrator Daemon After=deviced.service [Service] -Type=Notify +Type=notify SmackProcessLabel=System ExecStart=/usr/bin/feedbackd Restart=always -- 2.7.4 From e2f013146add167d73520066fab1e7f977753ce2 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 9 Jul 2018 17:17:42 +0900 Subject: [PATCH 12/16] Check return value for vconf_notify_key_changed and vconf_ignore_key_changed Change-Id: I1213ecda36a2aa028ef5e7eade6d542309d1a8a2 Signed-off-by: pr.jung --- src/haptic/haptic.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index 505a6de..818210c 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -824,8 +824,11 @@ void haptic_init(void) "", NULL); /* add watch for sound capturing value */ - if (haptic_conf.sound_capture) - vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL); + if (haptic_conf.sound_capture) { + r = vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL); + if (r != 0) + _W("Add watch for VCONFKEY_RECORDER_STATE failed"); + } /* Initialize vibration_handle (Use vibration now) */ cur_h_data.handle = INVALID_HANDLE; @@ -839,8 +842,11 @@ void haptic_exit(void) int r; /* remove watch */ - if (haptic_conf.sound_capture) - vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb); + if (haptic_conf.sound_capture) { + r = vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb); + if (r != 0) + _W("Remove watch for VCONFKEY_RECORDER_STATE failed"); + } /* unregister notifier for below each event */ unsubscribe_dbus_signal(NULL, id_sig_change_hardkey); -- 2.7.4 From b620f8911b6748c805f0f485d5da6ad7ed1693de Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Wed, 28 Nov 2018 15:25:12 +0900 Subject: [PATCH 13/16] haptic: Request power lock before vibration - When device goes suspend mode after vibration started, vibration stops immediately. To prevent this, feedbackd request power lock during vibration time. Change-Id: I04bca81481c979ffaeb8d1676c33ec562841ab69 Signed-off-by: pr.jung --- CMakeLists.txt | 1 + packaging/feedbackd.spec | 1 + src/haptic/standard-vibcore.c | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eeb80b..ad93c9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ SET(PKG_MODULES capi-system-info libgdbus libsystemd + capi-system-device ) IF(DRIVER STREQUAL gpio) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index d33ccfb..0c9fc13 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -23,6 +23,7 @@ BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-peripheral-io) BuildRequires: pkgconfig(libgdbus) BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(capi-system-device) Requires(post): /usr/bin/vconftool diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index f8982c9..528875f 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -19,6 +19,7 @@ #include #include +#include #include "core/log.h" #include "core/list.h" @@ -30,6 +31,7 @@ struct vibration_config { char *pattern; + int pattern_duration; dd_list *data; }; @@ -67,6 +69,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) return -ENOMEM; } + conf->pattern_duration = 0; conf->pattern = strdup(result->name); if (!conf->pattern) { _E("fail to copy %s pattern data", result->name); @@ -111,6 +114,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) data->duration = strtol(value, NULL, 10); len = len - strlen(value) - 1; value = check + 1; + conf->pattern_duration += data->duration; } check = strchr(value, 'W'); @@ -119,6 +123,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) data->wait = strtol(value, NULL, 10); len = len - strlen(value) - 1; value = check + 1; + conf->pattern_duration += data->wait; } DD_LIST_APPEND(conf->data, data); @@ -227,6 +232,7 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback dd_list *elem; struct vibration_config *conf; size_t len; + int ret; if (device_handle < 0) return -EINVAL; @@ -250,6 +256,13 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback cur_h_data.priority = priority; cur_h_data.stop = false; _D("Play %s", conf->pattern); + + if (conf->pattern_duration <= 0) + break; + + ret = device_power_request_lock(POWER_LOCK_CPU, conf->pattern_duration); + if (ret != DEVICE_ERROR_NONE) + _E("Failed to request power lock"); haptic_duration_play((void *)&cur_h_data); break; } -- 2.7.4 From fcaf29164be7f6282671f3e4517cb2cb126ff3e7 Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Thu, 27 Dec 2018 12:03:32 +0900 Subject: [PATCH 14/16] Remove executable flag from non-executable files Change-Id: I68327a8243aa96e13785dbfb7afd5c6a31344900 Signed-off-by: lokilee73 --- src/auto-test/haptic.c | 0 src/core/main.c | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/auto-test/haptic.c mode change 100755 => 100644 src/core/main.c diff --git a/src/auto-test/haptic.c b/src/auto-test/haptic.c old mode 100755 new mode 100644 diff --git a/src/core/main.c b/src/core/main.c old mode 100755 new mode 100644 -- 2.7.4 From 6f163ef5ccf32203c723ffd073088e49e597e4fa Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Fri, 4 Jan 2019 17:45:25 +0900 Subject: [PATCH 15/16] Parse and vibrate using standard pattern - Example) - FEEDBACK_PATTERN_NOTIFICATION_1=1,J_W - FEEDBACK_PATTERN_ALARM_1_STRONG_BUZZ=A,K_WB - 1: one time, A: unlimit(Vibrate until stop) - J_W, K_WB, and so on: standard pattern - Standard pattern is defined under /usr/share/feedback/vibration/xxx - Duration, Intensity, frequency, overdriving - Wait time, intensity(should be 0), frequency(Not used value), overdriving(Not used value) - Standard pattern example) 85,10000,205,0, 90,0,205,0, 105,10000,205,0, 0,end Change-Id: I5b6d6071983c8e8f4eaf9cd6cd9981ed906662de Signed-off-by: pr.jung --- src/haptic/circle.c | 6 +- src/haptic/gpio_haptic.c | 5 +- src/haptic/haptic.h | 1 + src/haptic/standard-vibcore.c | 372 +++++++++++++++++++++++++++++++++++------- src/haptic/standard-vibcore.h | 2 +- src/haptic/standard.c | 4 +- 6 files changed, 321 insertions(+), 69 deletions(-) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index 1b63660..9c756e7 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -320,8 +320,6 @@ static const struct haptic_plugin_ops default_plugin = { static bool is_valid(void) { - int ret; - if ((access(CIRCLE_ON_PATH, R_OK) != 0) || (access(CIRCLE_OFF_PATH, R_OK) != 0)) { _E("Do not support wearable haptic device"); @@ -329,9 +327,7 @@ static bool is_valid(void) return false; } - ret = standard_config_parse(); - if (ret < 0) - _E("failed to load standard vibration configuration file : %d", ret); + standard_config_parse(); state = true; _I("Support wearable haptic device"); diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index 45ffdac..3d91b5a 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -348,7 +348,6 @@ static bool is_valid(void) { uint8_t result; peripheral_i2c_h handle; - int ret; if (peripheral_i2c_open(GPIO_I2C_BUS_INDEX, DRV2605L_DEFAULT_ADDR, &handle) < PERIPHERAL_ERROR_NONE) { _E("Failed to open I2C"); @@ -368,9 +367,7 @@ static bool is_valid(void) return false; } - ret = standard_config_parse(); - if (ret < 0) - _E("failed to load standard vibration configuration file : %d", ret); + standard_config_parse(); state = true; _I("Support gpio haptic device"); diff --git a/src/haptic/haptic.h b/src/haptic/haptic.h index 3f57723..7951d4b 100644 --- a/src/haptic/haptic.h +++ b/src/haptic/haptic.h @@ -60,6 +60,7 @@ struct haptic_data { int level; int priority; bool stop; + int unlimit; }; #define INVALID_HANDLE 0 diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 528875f..358942b 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -16,7 +16,9 @@ * limitations under the License. */ - +#include +#include +#include #include #include #include @@ -27,16 +29,35 @@ #include "haptic.h" #include "standard-vibcore.h" -#define VIBRATION_CONF_PATH "/usr/share/feedback/vibration.conf" +#define FEEDBACK_BASE_PATH "/usr/share/feedback/" +#define STANDARD_FILE_PATH FEEDBACK_BASE_PATH"vibration/" +#define VIBRATION_CONF_PATH FEEDBACK_BASE_PATH"vibration.conf" + +#define VALUE_MAX_LEN 10 +#define VIB_LOCK_TIMEOUT_MAX (300000) /* 5minutes */ + +/* + 1,A_W or A,A_W or 250D250W250D750W + 85,10000,205,0, + 90,0,205,0, + 105,10000,205,0, + 0,end +*/ struct vibration_config { - char *pattern; + char *pattern; /* pattern name */ + char *standard; /* assigned standard pattern name */ + dd_list *data; /* duration_data list */ int pattern_duration; - dd_list *data; + int len; /* string length of pattern */ + int unlimit; }; struct duration_data { int duration; + int intensity; + int frequency; + int overdriving; int wait; }; @@ -45,10 +66,217 @@ static guint duration_timer; static t_vibrate_monotone real_vibrate_monotone; +static int insert_conf_data(dd_list **conf_data, struct duration_data *update) +{ + struct duration_data *data; + + if (update->duration < 0 || update->intensity < 0 || update->frequency < 0 || update->overdriving < 0) + return 0; + + data = (struct duration_data *)calloc(1, sizeof(struct duration_data)); + if (!data) { + _E("not enough memory"); + return -ENOMEM; + } + memcpy(data, update, sizeof(struct duration_data)); + /* insert vibration pattern data */ + // to debug : + // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdriving, data->wait); + DD_LIST_APPEND(*conf_data, data); + memset(update, 0, sizeof(struct duration_data)); + return 0; +} + +/* [A]xxxDxxxIxxxFxxxOxxxW format */ +static int insert_law_data_format(dd_list **conf_data, char *value) +{ + struct duration_data update; + int len = 0; + char *check; + int pattern_duration = 0; + + if (!value) { + memset(&update, 0, sizeof(struct duration_data)); + return insert_conf_data(conf_data, &update); + } + + len = strlen(value); + do { + memset(&update, 0, sizeof(struct duration_data)); + check = strchr(value, 'D'); + if (check) { + *check = '\0'; + update.duration = strtol(value, NULL, 10); + pattern_duration += update.duration; + if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) { + _D("reached max pattern duration"); + pattern_duration = VIB_LOCK_TIMEOUT_MAX; + } + len = len - strlen(value) - 1; + value = check + 1; + check = strchr(value, 'I'); + if (check) { + *check = '\0'; + update.intensity = strtol(value, NULL, 10); + len = len - strlen(value) - 1; + value = check + 1; + } + check = strchr(value, 'F'); + if (check) { + *check = '\0'; + update.frequency = strtol(value, NULL, 10); + len = len - strlen(value) - 1; + value = check + 1; + } + check = strchr(value, 'O'); + if (check) { + *check = '\0'; + update.overdriving = strtol(value, NULL, 10); + len = len - strlen(value) - 1; + value = check + 1; + } + } + + check = strchr(value, 'W'); + if (check) { + *check = '\0'; + update.wait = strtol(value, NULL, 10); + pattern_duration += update.wait; + if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) { + _D("reached max pattern duration"); + pattern_duration = VIB_LOCK_TIMEOUT_MAX; + } + len = len - strlen(value) - 1; + value = check + 1; + } + if (update.duration == 0 && update.wait == 0) + break; + if (insert_conf_data(conf_data, &update) < 0) + return -EINVAL; + } while (len > 0); + + return pattern_duration; +} + +/* + duration, intensity, frequency, overdriving + waiting duration, intensity=0, frequency, overdriving + 85,10000,205,0, + 90,0,205,0, + 105,10000,205,0, + 0,end +*/ +static int load_standard_format(char *pattern) +{ + struct vibration_config *conf; + struct duration_data update = {0, }; + bool packed = false; + int duration = 0, intensity = 0, ret = 0, count = 0, end = 2; + int fd; + char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, }; + + snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern); + fd = open(path, O_RDONLY); + if (fd < 0) + return -ENOENT; + + conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config)); + if (!conf) { + _E("fail to alloc"); + ret = -errno; + goto error_out; + } + + conf->pattern = strdup(pattern); + if (!conf->pattern) { + _E("fail to copy %s pattern data", pattern); + ret = -errno; + goto error_out; + } + conf->len = strlen(conf->pattern) + 1; + + /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */ + while (read(fd, &elem, 1) != 0) { + if (end == 0) { + if (insert_conf_data(&conf->data, &update) < 0) + goto error_out; + break; + } + if (elem == 'e' || elem == 'n' || elem == 'd') { + end--; + continue; + } + if (elem == '\n') { + count = 0; + continue; + } + if (elem == ',') { + count++; + val[ret] = '\0'; + ret = 0; + switch (count) { + case 1: /* D */ + duration = strtol(val, NULL, 10); + conf->pattern_duration += duration; + if (conf->pattern_duration > VIB_LOCK_TIMEOUT_MAX) { + _D("Reached max pattern duration"); + conf->pattern_duration = VIB_LOCK_TIMEOUT_MAX; + } + break; + case 2: /* I or W */ + intensity = strtol(val, NULL, 10); + if (!packed) { + update.duration = duration; + update.intensity = intensity; + break; + } + /* Intensity should be 0 for wait(off) time */ + if (intensity == 0) + update.wait = duration; + else + update.wait = 0; + packed = false; + + if (insert_conf_data(&conf->data, &update) < 0) + goto error_out; + break; + case 3: /* F */ + if (intensity != 0) + update.frequency = strtol(val, NULL, 10); + break; + case 4: /* O */ + count = 0; + if (intensity != 0) { + packed = true; + update.overdriving = strtol(val, NULL, 10); + } + break; + default: + break; + } + } else { + if (ret < (VALUE_MAX_LEN - 2)) + val[ret++] = elem; + } + } + close(fd); + DD_LIST_APPEND(vib_conf_list, conf); + return 0; + +error_out: + if (fd >= 0) + close(fd); + if (conf) { + if (conf->pattern) + free(conf->pattern); + free(conf); + } + return -ENOENT; +} + static int vibration_load_config(struct parse_result *result, void *user_data) { struct vibration_config *conf; - struct duration_data *data; char *value; char *check; int len; @@ -56,7 +284,9 @@ static int vibration_load_config(struct parse_result *result, void *user_data) if (!result) return 0; - if (!MATCH(result->section, "Vibration")) + if (!MATCH(result->section, "vibration") && + !MATCH(result->section, "Vibration") && + !MATCH(result->section, "VIBRATION")) return 0; @@ -73,72 +303,95 @@ static int vibration_load_config(struct parse_result *result, void *user_data) conf->pattern = strdup(result->name); if (!conf->pattern) { _E("fail to copy %s pattern data", result->name); - free(conf); - return -ENOMEM; + goto error_out; } + conf->len = strlen(conf->pattern) + 1; value = result->value; len = strlen(value); if (len == 0) { - data = (struct duration_data *)malloc(sizeof(struct duration_data)); - if (!data) { - _E("not enough memory"); - free(conf->pattern); - free(conf); - return -ENOMEM; - } - data->duration = 0; - data->wait = 0; - - DD_LIST_APPEND(conf->data, data); + if (insert_law_data_format(&conf->data, NULL) < 0) + goto error_out; DD_LIST_APPEND(vib_conf_list, conf); return 0; } - /* value : 100D or 100D0W or 250D250W250D750W*/ - do { - data = (struct duration_data *)malloc(sizeof(struct duration_data)); - if (!data) { - _E("not enough memory"); - free(conf->pattern); - free(conf); - return -ENOMEM; + /* Load Standard Pattern Name */ + /* value: 1,A_W or A,A_W */ + if ((check = strchr(value, ','))) { + *check = '\0'; + if (strncmp(value, "A", 1) == 0) + conf->unlimit = 1; + value = check + 1; + conf->standard = strdup(value); + if (!conf->standard) { + _E("fail to copy standard name"); + goto error_out; } - data->duration = 0; - data->wait = 0; + DD_LIST_APPEND(vib_conf_list, conf); + return 0; + } - check = strchr(value, 'D'); - if (check) { - *check = '\0'; - data->duration = strtol(value, NULL, 10); + /* value : A100D or 100D0W or 250D250W250D750W */ + /* Load Vibration Pattern Data */ + check = strchr(value, 'A'); + if (check) { + *check = '\0'; + conf->unlimit = 1; + if (!value) + len = len - 1; + else len = len - strlen(value) - 1; - value = check + 1; - conf->pattern_duration += data->duration; - } + value = check + 1; + } + conf->pattern_duration = insert_law_data_format(&conf->data, value); + if (conf->pattern_duration < 0) { + conf->pattern_duration = 0; + goto error_out; + } + DD_LIST_APPEND(vib_conf_list, conf); - check = strchr(value, 'W'); - if (check) { - *check = '\0'; - data->wait = strtol(value, NULL, 10); - len = len - strlen(value) - 1; - value = check + 1; - conf->pattern_duration += data->wait; - } + return 0; - DD_LIST_APPEND(conf->data, data); - if (data->duration == 0 && data->wait == 0) - break; - } while (len > 0); +error_out: + if (conf) { + if (conf->pattern) + free(conf->pattern); + if (conf->standard) + free(conf->standard); + } + return -ENOMEM; +} - DD_LIST_APPEND(vib_conf_list, conf); +static void load_standard_vibration_patterns(void) +{ + DIR *dir; + struct dirent *dent; - return 0; + dir = opendir(STANDARD_FILE_PATH); + if (!dir) { + _E("Failed to load %s Use default value!", STANDARD_FILE_PATH); + return; + } + while ((dent = readdir(dir))) { + if (dent->d_type == DT_DIR) + continue; + load_standard_format(dent->d_name); + } + closedir(dir); + _D("Success to load %s", STANDARD_FILE_PATH); } -int standard_config_parse() +void standard_config_parse(void) { - return config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL); + int ret; + + ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL); + if (ret < 0) + _E("Failed to load %s, %d Use default value!", VIBRATION_CONF_PATH, ret); + + load_standard_vibration_patterns(); } int standard_is_supported(const char *pattern) @@ -154,7 +407,7 @@ int standard_is_supported(const char *pattern) len = strlen(pattern) + 1; ret = 0; DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern) + if (!conf->pattern || conf->len != len) continue; if (!strncmp(conf->pattern, pattern, len)) { ret = true; @@ -227,11 +480,12 @@ int standard_set_vib_function(t_vibrate_monotone func) return 0; } -int standard_vibrate_effect(int device_handle, const char *pattern, int feedback, int priority) +int standard_vibrate_effect(int device_handle, const char *requested_pattern, int feedback, int priority) { dd_list *elem; struct vibration_config *conf; size_t len; + char pattern[PATH_MAX]; int ret; if (device_handle < 0) @@ -243,12 +497,18 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback return -EPERM; } + snprintf(pattern, sizeof(pattern), "%s", requested_pattern); len = strlen(pattern) + 1; DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern) + if (!conf->pattern || conf->len != len) continue; if (strncmp(conf->pattern, pattern, len)) continue; + if (conf->standard) { + snprintf(pattern, sizeof(pattern), "%s", conf->standard); + len = strlen(pattern) + 1; + continue; + } cur_h_data.vibration_data = conf->data; cur_h_data.handle = device_handle; @@ -270,7 +530,7 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback return 0; } -int standard_vibrate_close() +int standard_vibrate_close(void) { cur_h_data.handle = INVALID_HANDLE; cur_h_data.priority = PRIORITY_MIN; diff --git a/src/haptic/standard-vibcore.h b/src/haptic/standard-vibcore.h index a55d7d2..0d4f254 100644 --- a/src/haptic/standard-vibcore.h +++ b/src/haptic/standard-vibcore.h @@ -22,7 +22,7 @@ typedef int (*t_vibrate_monotone)(int device_handle, int duration, int feedback, int priority, int *effect_handle); -int standard_config_parse(void); +void standard_config_parse(void); int standard_is_supported(const char *pattern); int standard_vibrate_effect(int device_handle, const char *pattern, int feedback, int priority); int standard_set_vib_function(t_vibrate_monotone func); diff --git a/src/haptic/standard.c b/src/haptic/standard.c index 6a42bd1..c0436fe 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -678,9 +678,7 @@ static bool is_valid(void) return false; } - ret = standard_config_parse(); - if (ret < 0) - _E("failed to load standard vibration configuration file : %d", ret); + standard_config_parse(); _I("Support standard haptic device"); return true; -- 2.7.4 From cdb9263aab9cc1a1d6c9584cbf20185215977214 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Tue, 8 Jan 2019 14:05:15 +0900 Subject: [PATCH 16/16] Check device_handle is the same with current vibration handle on close_device() - Check device_handle - Remove redundant operations Change-Id: If7597c20ace9b43d1bcbfb5017b983c15da00c7d Signed-off-by: pr.jung --- src/haptic/circle.c | 11 ----------- src/haptic/gpio_haptic.c | 11 ----------- src/haptic/standard.c | 16 +++------------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index 9c756e7..aa1b7a5 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -158,17 +158,6 @@ static int close_device(int device_handle) if (r < 0) _I("already stopped or failed to stop effect : %d", r); - /* unregister existing timer */ - if (r >= 0) { - _D("device handle %d is closed and timer deleted", device_handle); - if (stop_timer) { - g_source_remove(stop_timer); - stop_timer = 0; - } - } - - standard_vibrate_close(); - DD_LIST_REMOVE(handle_list, (gpointer)(long)device_handle); /* if it is the last element */ diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index 3d91b5a..c495d6c 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -188,17 +188,6 @@ static int gpio_haptic_close_device(int handle) if (r < 0) _I("already stopped or failed to stop effect : %d", r); - /* unregister existing timer */ - if (r >= 0) { - if (stop_timer) { - //ecore_timer_del(stop_timer); - g_source_remove(stop_timer); - stop_timer = 0; - } - } - - standard_vibrate_close(); - _D("handle %d is closed and timer deleted", handle); DD_LIST_REMOVE(handle_list, (gpointer)(long)handle); diff --git a/src/haptic/standard.c b/src/haptic/standard.c index c0436fe..dd162b2 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -75,6 +75,7 @@ static dd_list *handle_list; static char ff_path[PATH_MAX]; static int unique_number; +static int stop_device(int device_handle); struct ff_info *read_from_list(int handle) { struct ff_info *temp; @@ -358,7 +359,7 @@ static int open_device(int device_index, int *device_handle) static int close_device(int device_handle) { struct ff_info *info; - int r, n; + int n; info = read_from_list(device_handle); if (!info) @@ -371,18 +372,7 @@ static int close_device(int device_handle) return -ENODEV; /* stop vibration */ - r = ff_stop(ff_fd, &info->effect); - if (r < 0) - _I("already stopped or failed to stop effect : %d", r); - - /* unregister existing timer */ - if (r >= 0 && info->timer) { - _D("device handle %d is closed and timer deleted", device_handle); - g_source_remove(info->timer); - info->timer = 0; - } - - standard_vibrate_close(); + stop_device(device_handle); DD_LIST_REMOVE(handle_list, (gpointer)(long)info->handle); -- 2.7.4