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, 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 static void on_name_vanished(GDBusConnection *connection,
160 struct proxy_node *node;
162 pthread_mutex_lock(&dmutex);
163 for (elem = proxy_pool, next = g_list_next(elem); elem;
164 elem = next, next = g_list_next(elem)) {
168 proxy_pool = g_list_delete_link(proxy_pool, elem);
169 g_object_unref(node->proxy);
172 free(node->interface);
175 pthread_mutex_unlock(&dmutex);
178 static GDBusConnection *get_dbus_connection(void)
181 static GDBusConnection *conn;
183 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
186 _D("Fail to get dbus connection: %s", err->message);
188 _D("Fail to get dbus connection");
195 static GDBusProxy *get_proxy_from_proxy_pool(const char *dest,
197 const char *interface,
200 GDBusConnection *conn;
202 struct proxy_node *node;
204 if (!dest || !path || !interface) {
206 g_set_error(err, G_IO_ERROR,
207 G_IO_ERROR_INVALID_ARGUMENT,
208 "Cannot determine destination address");
212 /* find matched proxy node in proxy pool */
213 node = find_matched_proxy_node(dest, path, interface);
217 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, err);
223 g_bus_watch_name_on_connection(conn,
225 G_BUS_NAME_WATCHER_FLAGS_NONE,
232 proxy = g_dbus_proxy_new_sync(conn,
233 G_DBUS_PROXY_FLAGS_NONE,
234 NULL, /* GDBusinterfaceinfo */
236 path, /* object path */
237 interface, /* interface name */
238 NULL, /* GCancellable */
243 node = malloc(sizeof(struct proxy_node));
245 g_object_unref(proxy);
247 g_set_error(err, G_IO_ERROR,
249 "Cannot allocate proxy_node memory");
254 node->dest = strdup(dest);
255 node->path = strdup(path);
256 node->interface = strdup(interface);
258 proxy_pool = g_list_append(proxy_pool, node);
263 int dbus_method_sync(const char *dest, const char *path,
264 const char *interface, const char *method,
265 const char *sig, char *param[])
272 #if !GLIB_CHECK_VERSION(2, 35, 0)
276 pthread_mutex_lock(&dmutex);
277 proxy = get_proxy_from_proxy_pool(dest, path, interface, &err);
279 pthread_mutex_unlock(&dmutex);
280 _E("fail to get proxy from proxy pool : %s-%s (%d-%s)",
281 interface, method, err->code, err->message);
282 result = g_dbus_error_to_errno(err->code);
287 output = g_dbus_proxy_call_sync(proxy,
288 method, /* method name */
289 append_g_variant(sig, param), /* parameters */
290 G_DBUS_CALL_FLAGS_NONE,
291 DBUS_REPLY_TIMEOUT, /* timeout */
292 NULL, /* GCancellable */
294 pthread_mutex_unlock(&dmutex);
298 _E("g_dbus_proxy_call_sync error : %s-%s (%d-%s)",
299 interface, method, err->code, err->message);
300 result = g_dbus_error_to_errno(err->code);
303 _E("g_dbus_proxy_call_sync error : %s-%s",
310 /* get output value */
311 g_variant_get(output, "(i)", &result);
313 g_variant_unref(output);
318 static void feedback_signal_callback(GDBusConnection *conn,
326 size_t iface_len, signal_len;
327 struct feedback_restart_callback *callback;
331 if (!params || !sender || !path || !iface || !signal)
334 iface_len = strlen(iface) + 1;
335 signal_len = strlen(signal) + 1;
337 if (strncmp(iface, VIBRATOR_INTERFACE_HAPTIC, iface_len))
340 if (strncmp(signal, SIGNAL_VIBRATOR_INITIATED, signal_len))
343 DD_LIST_FOREACH(callback_list, elem, callback) {
346 ret = callback->func();
348 _E("Failed to call restart callback");
352 int register_signal_handler(feedback_restart_cb func)
354 GDBusConnection *conn;
355 guint feedback_id = 0;
356 struct feedback_restart_callback *callback;
359 DD_LIST_FOREACH(callback_list, elem, callback) {
360 if (callback->func != func)
362 if (callback->feedback_id == 0)
368 callback = (struct feedback_restart_callback *)malloc(sizeof(struct feedback_restart_callback));
370 //LCOV_EXCL_START System Error
371 _E("malloc() failed");
376 conn = get_dbus_connection();
378 //LCOV_EXCL_START System Error
380 _E("Failed to get dbus connection");
385 feedback_id = g_dbus_connection_signal_subscribe(conn,
387 VIBRATOR_INTERFACE_HAPTIC,
391 G_DBUS_SIGNAL_FLAGS_NONE,
392 feedback_signal_callback,
395 if (feedback_id == 0) {
397 _E("Failed to subscrive bus signal");
401 callback->func = func;
402 callback->feedback_id = feedback_id;
404 DD_LIST_APPEND(callback_list, callback);
409 int unregister_signal_handler(feedback_restart_cb func)
411 GDBusConnection *conn;
412 struct feedback_restart_callback *callback;
418 conn = get_dbus_connection();
420 //LCOV_EXCL_START System Error
422 _E("Failed to get dbus connection");
427 DD_LIST_FOREACH(callback_list, elem, callback) {
428 if (callback->func != func)
430 if (callback->feedback_id > 0)
431 g_dbus_connection_signal_unsubscribe(conn, callback->feedback_id);
432 DD_LIST_REMOVE(callback_list, callback);