4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
30 /* -1 is a default timeout value, it's converted to 25*1000 internally. */
31 #define DBUS_REPLY_TIMEOUT (-1)
33 /** extract from dbus/dbus-protocol.h
34 * (GDbus use the same maximum value.)
35 * Max length in bytes of a bus name, interface, or member (not object
36 * path, paths are unlimited). This is limited because lots of stuff
37 * is O(n) in this number, plus it would be obnoxious to type in a
38 * paragraph-long method name so most likely something like that would
41 #define DBUS_MAXIMUM_NAME_LENGTH 255
43 #define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator"
45 struct feedback_restart_callback {
46 feedback_restart_cb func;
57 static GList *proxy_pool;
58 static pthread_mutex_t dmutex = PTHREAD_MUTEX_INITIALIZER;
61 static dd_list *callback_list;
63 static int g_dbus_error_to_errno(int code)
66 * if device is not supported,
67 * deviced does not register the method call of the device.
68 * in this case, dbus will return UNKNOWN_METHOD error.
70 /* refer to gio/gioenums.h */
71 if (code == G_DBUS_ERROR_ACCESS_DENIED)
73 else if (code == G_DBUS_ERROR_UNKNOWN_METHOD)
78 static GVariant *append_g_variant(const char *sig, const char *param[])
80 GVariantBuilder builder;
83 struct dbus_byte *bytes;
88 g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
90 for (ch = (char *)sig, i = 0; *ch != '\0'; ++i, ++ch) {
93 g_variant_builder_add(&builder, "i", atoi(param[i]));
96 g_variant_builder_add(&builder, "u", strtoul(param[i], NULL, 10));
99 g_variant_builder_add(&builder, "t", atoll(param[i]));
102 g_variant_builder_add(&builder, "s", param[i]);
109 bytes = (struct dbus_byte *)param[i];
110 g_variant_builder_add(&builder, "@ay",
111 g_variant_new_from_data(G_VARIANT_TYPE("ay"),
112 bytes->data, bytes->size, TRUE, NULL, NULL));
123 return g_variant_builder_end(&builder);
126 static struct proxy_node *find_matched_proxy_node(const char *dest,
128 const char *interface)
131 struct proxy_node *node;
134 if (!dest || !path || !interface)
137 plen = strlen(path) + 1;
139 /* find matched proxy object */
140 for (elem = proxy_pool; elem; elem = elem->next) {
144 if (!strncmp(node->dest, dest, DBUS_MAXIMUM_NAME_LENGTH) &&
145 !strncmp(node->path, path, plen) &&
146 !strncmp(node->interface, interface,
147 DBUS_MAXIMUM_NAME_LENGTH))
154 //LCOV_EXCL_START Not called Callback
155 static void on_name_vanished(GDBusConnection *connection,
161 struct proxy_node *node;
163 pthread_mutex_lock(&dmutex);
164 for (elem = proxy_pool, next = g_list_next(elem); elem;
165 elem = next, next = g_list_next(elem)) {
169 proxy_pool = g_list_delete_link(proxy_pool, elem);
170 g_object_unref(node->proxy);
173 free(node->interface);
176 pthread_mutex_unlock(&dmutex);
180 static GDBusConnection *get_dbus_connection(void)
183 static GDBusConnection *conn;
185 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
187 //LCOV_EXCL_START System Error
189 _D("Fail to get dbus connection: %s", err->message);
191 _D("Fail to get dbus connection");
199 static GDBusProxy *get_proxy_from_proxy_pool(const char *dest,
201 const char *interface,
204 GDBusConnection *conn;
206 struct proxy_node *node;
208 if (!dest || !path || !interface) {
210 g_set_error(err, G_IO_ERROR,
211 G_IO_ERROR_INVALID_ARGUMENT,
212 "Cannot determine destination address");
216 /* find matched proxy node in proxy pool */
217 node = find_matched_proxy_node(dest, path, interface);
221 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, err);
227 g_bus_watch_name_on_connection(conn,
229 G_BUS_NAME_WATCHER_FLAGS_NONE,
236 proxy = g_dbus_proxy_new_sync(conn,
237 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
238 NULL, /* GDBusinterfaceinfo */
240 path, /* object path */
241 interface, /* interface name */
242 NULL, /* GCancellable */
247 node = malloc(sizeof(struct proxy_node));
249 //LCOV_EXCL_START System Error
250 g_object_unref(proxy);
252 g_set_error(err, G_IO_ERROR,
254 "Cannot allocate proxy_node memory");
260 node->dest = strdup(dest);
261 node->path = strdup(path);
262 node->interface = strdup(interface);
264 proxy_pool = g_list_append(proxy_pool, node);
269 int dbus_method_sync_var(const char *dest, const char *path,
270 const char *interface, const char *method, GVariant *param)
277 #if !GLIB_CHECK_VERSION(2, 35, 0)
281 pthread_mutex_lock(&dmutex);
282 proxy = get_proxy_from_proxy_pool(dest, path, interface, &err);
283 //LCOV_EXCL_START System Error
285 pthread_mutex_unlock(&dmutex);
286 _E("fail to get proxy from proxy pool : %s-%s (%d-%s)",
287 interface, method, err->code, err->message);
288 result = g_dbus_error_to_errno(err->code);
293 output = g_dbus_proxy_call_sync(proxy,
294 method, /* method name */
295 param, /* parameters */
296 G_DBUS_CALL_FLAGS_NONE,
297 DBUS_REPLY_TIMEOUT, /* timeout */
298 NULL, /* GCancellable */
300 pthread_mutex_unlock(&dmutex);
302 //LCOV_EXCL_START System Error
305 _E("g_dbus_proxy_call_sync error : %s-%s",
309 _E("g_dbus_proxy_call_sync error : %s-%s (%d-%s)",
310 interface, method, err->code, err->message);
311 result = g_dbus_error_to_errno(err->code);
317 /* get output value */
318 g_variant_get(output, "(i)", &result);
320 g_variant_unref(output);
325 int dbus_method_sync(const char *dest, const char *path,
326 const char *interface, const char *method,
327 const char *sig, const char *param[])
329 return dbus_method_sync_var(dest,
333 append_g_variant(sig, param));
336 //LCOV_EXCL_START Not called Callback
337 static void feedback_signal_callback(GDBusConnection *conn,
345 size_t iface_len, signal_len;
346 struct feedback_restart_callback *callback;
350 if (!params || !sender || !path || !iface || !signal)
353 iface_len = strlen(iface) + 1;
354 signal_len = strlen(signal) + 1;
356 if (strncmp(iface, VIBRATOR_INTERFACE_HAPTIC, iface_len))
359 if (strncmp(signal, SIGNAL_VIBRATOR_INITIATED, signal_len))
362 DD_LIST_FOREACH(callback_list, elem, callback) {
365 ret = callback->func();
367 _E("Failed to call restart callback");
372 int register_signal_handler(feedback_restart_cb func)
374 GDBusConnection *conn;
375 guint feedback_id = 0;
376 struct feedback_restart_callback *callback;
379 DD_LIST_FOREACH(callback_list, elem, callback) {
380 if (callback->func != func)
382 if (callback->feedback_id == 0)
388 callback = (struct feedback_restart_callback *)malloc(sizeof(struct feedback_restart_callback));
390 //LCOV_EXCL_START System Error
391 _E("malloc() failed");
396 conn = get_dbus_connection();
398 //LCOV_EXCL_START System Error
400 _E("Failed to get dbus connection");
405 feedback_id = g_dbus_connection_signal_subscribe(conn,
407 VIBRATOR_INTERFACE_HAPTIC,
411 G_DBUS_SIGNAL_FLAGS_NONE,
412 feedback_signal_callback,
415 if (feedback_id == 0) {
416 //LCOV_EXCL_START System Error
418 _E("Failed to subscrive bus signal");
423 callback->func = func;
424 callback->feedback_id = feedback_id;
426 DD_LIST_APPEND(callback_list, callback);
431 int unregister_signal_handler(feedback_restart_cb func)
433 GDBusConnection *conn;
434 struct feedback_restart_callback *callback;
440 conn = get_dbus_connection();
442 //LCOV_EXCL_START System Error
443 _E("Failed to get dbus connection");
448 DD_LIST_FOREACH(callback_list, elem, callback) {
449 if (callback->func != func)
451 if (callback->feedback_id > 0)
452 g_dbus_connection_signal_unsubscribe(conn, callback->feedback_id);
453 DD_LIST_REMOVE(callback_list, callback);