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.
26 #include "dbus-call.h"
29 #define DBUS_REPLY_TIMEOUT (-1)
30 #define DBUS_MAXIMUM_NAME_LENGTH 255
32 struct pending_call_data {
44 static GList *proxy_pool;
45 static pthread_mutex_t dmutex = PTHREAD_MUTEX_INITIALIZER;
47 static guint signal_id = 0;
49 static int g_dbus_error_to_errno(int code)
52 * if device is not supported,
53 * deviced does not register the method call of the device.
54 * in this case, dbus will return UNKNOWN_METHOD error.
56 /* refer to gio/gioenums.h */
57 if (code == G_DBUS_ERROR_ACCESS_DENIED)
59 else if (code == G_DBUS_ERROR_UNKNOWN_METHOD)
64 static GVariant *append_g_variant(const char *sig, char *param[])
66 GVariantBuilder builder;
67 GVariantBuilder *sub_builder;
69 struct dbus_int *array_int;
76 g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
78 for (ch = (char*)sig, i = 0; *ch != '\0'; ++i, ++ch) {
81 g_variant_builder_add(&builder, "i", atoi(param[i]));
84 g_variant_builder_add(&builder, "u", strtoul(param[i], NULL, 10));
87 g_variant_builder_add(&builder, "t", atoll(param[i]));
90 g_variant_builder_add(&builder, "s", param[i]);
96 sub_builder = g_variant_builder_new(G_VARIANT_TYPE("ai"));
97 array_int = (struct dbus_int *)param[i];
98 for (j = 0; j < array_int->size; j++)
99 g_variant_builder_add(sub_builder, "i", array_int->list[j]);
100 var = g_variant_new("ai", sub_builder);
101 g_variant_builder_unref(sub_builder);
102 g_variant_builder_add_value(&builder, var);
113 return g_variant_builder_end(&builder);
116 static struct proxy_node *find_matched_proxy_node(const char *dest,
118 const char *interface)
121 struct proxy_node *node;
124 if (!dest || !path || !interface)
127 plen = strlen(path) + 1;
129 /* find matched proxy object */
130 for (elem = proxy_pool; elem; elem = elem->next) {
134 if (!strncmp(node->dest, dest, DBUS_MAXIMUM_NAME_LENGTH) &&
135 !strncmp(node->path, path, plen) &&
136 !strncmp(node->interface, interface,
137 DBUS_MAXIMUM_NAME_LENGTH))
144 static void on_name_vanished(GDBusConnection *connection,
150 struct proxy_node *node;
152 pthread_mutex_lock(&dmutex);
153 for (elem = proxy_pool, next = g_list_next(elem); elem;
154 elem = next, next = g_list_next(elem)) {
158 proxy_pool = g_list_delete_link(proxy_pool, elem);
159 g_object_unref(node->proxy);
162 free(node->interface);
165 pthread_mutex_unlock(&dmutex);
168 static GDBusProxy *get_proxy_from_proxy_pool(const char *dest,
170 const char *interface,
173 GDBusConnection *conn;
175 struct proxy_node *node;
177 if (!dest || !path || !interface) {
179 g_set_error(err, G_IO_ERROR,
180 G_IO_ERROR_INVALID_ARGUMENT,
181 "Cannot determine destination address");
185 /* find matched proxy node in proxy pool */
186 node = find_matched_proxy_node(dest, path, interface);
190 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, err);
196 g_bus_watch_name_on_connection(conn,
198 G_BUS_NAME_WATCHER_FLAGS_NONE,
205 proxy = g_dbus_proxy_new_sync(conn,
206 G_DBUS_PROXY_FLAGS_NONE,
207 NULL, /* GDBusinterfaceinfo */
209 path, /* object path */
210 interface, /* interface name */
211 NULL, /* GCancellable */
216 node = malloc(sizeof(struct proxy_node));
218 g_object_unref(proxy);
220 g_set_error(err, G_IO_ERROR,
222 "Cannot allocate proxy_node memory");
227 node->dest = strdup(dest);
228 node->path = strdup(path);
229 node->interface = strdup(interface);
231 proxy_pool = g_list_append(proxy_pool, node);
236 int dbus_method_sync(const char *dest, const char *path,
237 const char *interface, const char *method,
238 const char *sig, char *param[])
245 #if !GLIB_CHECK_VERSION(2, 35, 0)
249 pthread_mutex_lock(&dmutex);
250 proxy = get_proxy_from_proxy_pool(dest, path, interface, &err);
252 pthread_mutex_unlock(&dmutex);
253 DMSG_ERR("fail to get proxy from proxy pool : %s-%s (%d-%s)",
254 interface, method, err->code, err->message);
255 result = g_dbus_error_to_errno(err->code);
260 output = g_dbus_proxy_call_sync(proxy,
261 method, /* method name */
262 append_g_variant(sig, param), /* parameters */
263 G_DBUS_CALL_FLAGS_NONE,
264 DBUS_REPLY_TIMEOUT, /* timeout */
265 NULL, /* GCancellable */
267 pthread_mutex_unlock(&dmutex);
271 DMSG_ERR("g_dbus_proxy_call_sync error : %s-%s",
275 DMSG_ERR("g_dbus_proxy_call_sync error : %s-%s (%d-%s)",
276 interface, method, err->code, err->message);
277 result = g_dbus_error_to_errno(err->code);
282 /* get output value */
283 g_variant_get(output, "(i)", &result);
285 g_variant_unref(output);
290 int dbus_method_sync_with_reply(const char *dest,
291 const char *path, const char *interface,
292 const char *method, const char *sig,
293 char *param[], GVariant **info)
300 #if !GLIB_CHECK_VERSION(2, 35, 0)
304 pthread_mutex_lock(&dmutex);
305 proxy = get_proxy_from_proxy_pool(dest, path, interface, &err);
307 pthread_mutex_unlock(&dmutex);
308 _E("fail to get proxy from proxy pool : %s-%s (%d-%s)",
309 interface, method, err->code, err->message);
310 result = g_dbus_error_to_errno(err->code);
315 output = g_dbus_proxy_call_sync(proxy,
316 method, /* method name */
317 append_g_variant(sig, param), /* parameters */
318 G_DBUS_CALL_FLAGS_NONE,
319 DBUS_REPLY_TIMEOUT, /* timeout */
320 NULL, /* GCancellable */
322 pthread_mutex_unlock(&dmutex);
325 _E("g_dbus_proxy_call_sync error : %s-%s",
329 _E("g_dbus_proxy_call_sync error : %s-%s (%d-%s)",
330 interface, method, err->code, err->message);
331 result = g_dbus_error_to_errno(err->code);
340 static void cb_pending(GDBusProxy *proxy,
344 struct pending_call_data *data = user_data;
348 output = g_dbus_proxy_call_finish(proxy,
349 res, /* GAsyncResult */
352 DMSG_ERR("g_dbus_proxy_call_finish error : %d-%s",
353 err->code, err->message);
355 if (data && data->func)
356 data->func(data->data, output, err);
362 g_variant_unref(output);
365 int dbus_method_async_with_reply(const char *dest, const char *path,
366 const char *interface, const char *method,
367 const char *sig, char *param[],
368 dbus_pending_cb cb, int timeout, void *data)
372 struct pending_call_data *pdata;
375 #if !GLIB_CHECK_VERSION(2, 35, 0)
379 pthread_mutex_lock(&dmutex);
380 proxy = get_proxy_from_proxy_pool(dest, path, interface, &err);
382 pthread_mutex_unlock(&dmutex);
383 DMSG_ERR("fail to get proxy from proxy pool : %s-%s (%d-%s)",
384 interface, method, err->code, err->message);
385 result = g_dbus_error_to_errno(err->code);
390 pdata = malloc(sizeof(struct pending_call_data));
392 pthread_mutex_unlock(&dmutex);
393 DMSG_ERR("malloc error : %s-%s",
401 g_dbus_proxy_call(proxy,
402 method, /* method name */
403 append_g_variant(sig, param), /* parameters */
404 G_DBUS_CALL_FLAGS_NONE,
405 timeout, //DBUS_REPLY_TIMEOUT, /* timeout */
406 NULL, /* GCancellable */
407 (GAsyncReadyCallback)cb_pending, /* GAsyncReadyCallback */
408 pdata); /* user data */
409 pthread_mutex_unlock(&dmutex);
414 static GDBusConnection *get_dbus_connection(void)
417 static GDBusConnection *conn;
419 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
422 _D("Fail to get dbus connection: %s", err->message);
424 _D("Fail to get dbus connection");
431 static void storage_signal_callback(GDBusConnection *conn,
439 size_t iface_len, signal_len;
440 appdata_s *ad = (appdata_s *)user_data;
443 if (!params || !sender || !path || !iface || !signal)
446 iface_len = strlen(iface) + 1;
447 signal_len = strlen(signal) + 1;
449 if (strncmp(iface, STORAGED_INTERFACE_BLOCK_MANAGER, iface_len))
452 if (strncmp(signal, "DeviceRemoved", signal_len))
455 g_variant_get(params, "(issssssisibii)", NULL, NULL, NULL, NULL,
456 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &id);
457 if (id == ad->storage_id) {
458 DMSG("Storage is removed");
463 int register_signal_handler(appdata_s *ad)
465 GDBusConnection *conn;
467 conn = get_dbus_connection();
469 _E("Failed to get dbus connection");
473 signal_id = g_dbus_connection_signal_subscribe(conn,
475 STORAGED_INTERFACE_BLOCK_MANAGER,
479 G_DBUS_SIGNAL_FLAGS_NONE,
480 storage_signal_callback,
483 if (signal_id == 0) {
484 _E("Failed to subscrive bus signal");
491 int unregister_signal_handler()
493 GDBusConnection *conn;
495 conn = get_dbus_connection();
497 _E("Failed to get dbus connection");
501 g_dbus_connection_signal_unsubscribe(conn, signal_id);