--- /dev/null
+/*
+ * lbs-server
+ *
+ * Copyright (c) 2019 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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+
+#include "lbs_dbus.h"
+#include "battery-monitor_log.h"
+
+/* 10 seconds */
+#define DBUS_REPLY_TIMEOUT (10000)
+
+static GBusType g_default_bus_type = G_BUS_TYPE_SYSTEM;
+static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static 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;
+}
+
+/* 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;
+} dbus_handle_s;
+
+/* path + interfaces */
+typedef struct {
+ dbus_handle_s *dh; /* dbus handle */
+ const char *path; /* object path */
+ GList *list_ifaces; /* dbus_interface_s */
+} dbus_object_handle_s;
+
+typedef struct {
+ dbus_object_handle_s *oh; /* object handle */
+ const char *name; /* interface 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
+
+/* global shared bus : system, session */
+static dbus_handle_s g_dh[2];
+
+static dbus_handle_s *_dbus_handle_get_connection(GBusType bus_type);
+
+static 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;
+
+static dbus_object_handle_s * _dbus_handle_lookup_object(GList *list_obj, const char *obj_path);
+static dbus_interface_s * _dbus_handle_lookup_interface(GList *list_iface, const char *iface_name);
+static dbus_method_s * _dbus_handle_lookup_method(GList *list_methods, const char *method_name);
+
+static 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;
+}
+
+/* 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);
+ if (!dh->conn) {
+ dbus_handle_unlock(dh);
+ return NULL;
+ }
+ dh->priv = FALSE;
+ dh->bus_type = bus_type;
+ }
+
+ dbus_handle_unlock(dh);
+
+ return dh;
+}
+
+#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);
+
+/* cal index of end of brace */
+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;
+}
+
+/*
+in : interface_s
+out : xml format
+*/
+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), "<node>""\n""\t""<interface name='%s'>""\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""<method name='%s'/>""\n", pmethod->member);
+ continue;
+ }
+
+ /* <method name='###'> */
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""<method name='%s'>""\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""<arg type='%s' name='arg%d' direction='in'/>""\n", tmp, m);
+ m += ei;
+ continue;
+ } else {
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='in'/>""\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""<arg type='%c' name='arg%d' direction='in'/>""\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""<arg type='%s' name='arg%d' direction='out'/>""\n", tmp, m);
+ m += ei;
+ continue;
+ } else {
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t\t""<arg type='%c%c' name='arg%d' direction='out'/>""\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""<arg type='%c' name='arg%d' direction='out'/>""\n", pmethod->signature_out[m], m);
+ }
+
+ /* </method> */
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t\t""</method>""\n");
+ }
+
+ nwrite += snprintf(buf + nwrite, buf_cal_free_space(buf_len, nwrite), "\t""</interface>""\n""</node>""");
+
+ *xml = buf;
+
+ /* todo: delete log */
+#if 0
+ if (nwrite <= 512)
+ _E("%s", buf);
+ else
+ _E("%s", buf + nwrite - 512);
+#endif
+ 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_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);
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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 ;
+ }
+
+ _E("unregister interface %s", ih->name);
+
+ /* 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;
+}
+
+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 *reply = NULL;
+
+ /* todo: ghash ? */
+ methods = _dbus_handle_lookup_method(iface_s->list_methods, name);
+ if (methods) {
+ reply = methods->func(conn, sender, path, iface, name, param, invocation, get_dh_from_oh(iface_s->oh));
+
+ /* async, maybe they will reply...maybe.. */
+ if (!reply)
+ return;
+ } else {
+ _E("no methods");
+ }
+
+ g_dbus_method_invocation_return_value(invocation, reply);
+}
+
+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;
+}
+
+int lbs_dbus_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.
+lbs_dbus_register_dbus_object_all register every objects on connection.
+
+return registered method count
+*/
+int lbs_dbus_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 lbs_dbus_register_dbus_object_all(dbus_handle_h handle)
+{
+ dcl_dbus_handle();
+ dbus_object_handle_s *oh = NULL;
+ dbus_interface_s *ih = NULL;
+ int ret_dbus = 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 = _dbus_handle_register_dbus_object(dh, oh->path, ih);
+ if (ret_dbus <= 0)
+ _E("failed to register dbus object%d", ret_dbus);
+
+ }
+ }
+ return 0;
+err:
+
+ // todo: delete all updates
+
+ return -1;
+}