blob: 18b1e2913fe845ba1bd31efb25f05be0d2598d4a [file] [log] [blame]
David Sodmanbbcb0522014-09-19 10:34:07 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7#include <stdlib.h>
8#include "dbus.h"
9#include "util.h"
10
11struct _dbus_t {
12 DBusConnection *conn;
13 int terminate;
14 struct {
15 DBusObjectPathVTable vtable;
16 const char* interface;
17 const char* signal;
18 const char* rule;
19 void* user_data;
20 dbus_message_handler_t signal_handler;
21 } signal;
22};
23
24dbus_t* dbus_init()
25{
26 dbus_t* new_dbus;
27 DBusError err;
28
29 dbus_error_init(&err);
30
31 new_dbus = (dbus_t*)calloc(1, sizeof(*new_dbus));
32
33 new_dbus->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
34 if (dbus_error_is_set(&err)) {
35 LOG(ERROR, "Cannot get dbus connection");
36 free(new_dbus);
37 return NULL;
38 }
39
40 dbus_connection_set_exit_on_disconnect(new_dbus->conn, FALSE);
41
42 return new_dbus;
43}
44
45
46bool dbus_method_call(dbus_t* dbus, const char* service_name,
47 const char* service_path, const char* service_interface,
48 const char* method, int* param)
49{
50 DBusMessage *msg = NULL;
51
52 msg = dbus_message_new_method_call(service_name,
53 service_path, service_interface, method);
54
55 if (!msg)
56 return false;
57
58 if (!dbus_message_append_args(msg,
59 DBUS_TYPE_INT32, param, DBUS_TYPE_INVALID)) {
60 dbus_message_unref(msg);
61 return false;
62 }
63
64 if (!dbus_connection_send_with_reply_and_block(dbus->conn,
65 msg, -1, NULL)) {
66 dbus_message_unref(msg);
67 return false;
68 }
69
70 dbus_connection_flush(dbus->conn);
71 dbus_message_unref(msg);
72
73 return true;
74}
75
76static void
77dbus_path_unregister_function(DBusConnection *connection, void *user_data)
78{
79}
80
81static DBusHandlerResult
82dbus_message_function(DBusConnection *connection,
83 DBusMessage *message, void* user_data)
84{
85 dbus_t* dbus = (dbus_t*)user_data;
86
87 if (dbus_message_is_signal(message, dbus->signal.interface,
88 dbus->signal.signal)) {
89 dbus->signal.signal_handler(dbus, dbus->signal.user_data);
90 }
91 return DBUS_HANDLER_RESULT_HANDLED;
92}
93
94bool dbus_signal_match_handler(
95 dbus_t* dbus,
96 const char* signal,
97 const char* path,
98 const char* interface,
99 const char* rule,
100 dbus_message_handler_t handler,
101 void *user_data)
102{
103 DBusError err;
104 dbus->signal.vtable.unregister_function = dbus_path_unregister_function;
105 dbus->signal.vtable.message_function = dbus_message_function;
106 dbus->signal.signal_handler = handler;
107 dbus->signal.signal = signal;
108 dbus->signal.user_data = user_data;
109 dbus->signal.interface = interface;
110
111 if (!dbus_connection_register_object_path(dbus->conn, path,
112 &dbus->signal.vtable, dbus)) {
113 LOG(ERROR, "register_object_path failed");
114 return false;
115 }
116
117 dbus_error_init(&err);
118 dbus_bus_add_match(dbus->conn, rule, &err);
119 if (dbus_error_is_set(&err)) {
120 LOG(ERROR, "add_match failed: %s", err.message);
121 return false;
122 }
123
124 return true;
125}
126
127
128void dbus_wait_for_messages(dbus_t *dbus)
129{
130 while (dbus_connection_read_write_dispatch(dbus->conn, -1)) {
131 if (dbus->terminate)
132 break;
133 }
134}
135
136
137void dbus_stop_wait(dbus_t* dbus)
138{
139 dbus->terminate = true;
140}
141
142
143void dbus_destroy(dbus_t* dbus)
144{
145 /* FIXME - not sure what the right counterpart to
146 dbus_bus_get() is, unref documentation is rather
147 unclear. Not a big issue but it would be nice to
148 clean up properly here */
149 /* dbus_connection_unref(dbus->conn); */
150 free(dbus);
151}