summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2014-09-22 15:57:12 -0400
committerChris Michael <cp.michael@samsung.com>2014-09-22 15:57:12 -0400
commit8490f5d2828d9aa48126e8c032d2e7bd2d6ad14c (patch)
tree41a26c53e4543bc7a5bcd2743e7ffd279f0743ec
parent500491069fa3bfb05b73de3b424b31b1d1441f8c (diff)
ecore-drm: Rework internal dbus code to use Eldbus
Summary: This changes all of our internal dbus code for ecore-drm to work with async Eldbus calls. This adds a potential delay to startup in that input devices may not be immediately available for use, but is unavoidable due to Eldbus not having a dbus function call to block for a reply. @fix Signed-off-by: Chris Michael <cp.michael@samsung.com>
-rw-r--r--src/lib/ecore_drm/ecore_drm_dbus.c887
1 files changed, 204 insertions, 683 deletions
diff --git a/src/lib/ecore_drm/ecore_drm_dbus.c b/src/lib/ecore_drm/ecore_drm_dbus.c
index 61a0f6c..631a437 100644
--- a/src/lib/ecore_drm/ecore_drm_dbus.c
+++ b/src/lib/ecore_drm/ecore_drm_dbus.c
@@ -1,840 +1,361 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include "ecore_drm_private.h" 1#include "ecore_drm_private.h"
6#include <sys/eventfd.h>
7 2
8static DBusConnection *dconn; 3static int _dbus_init_count = 0;
9static DBusPendingCall *dpending; 4
10static Ecore_Fd_Handler *_dbus_hdlr; 5static const char *dsession;
11static Ecore_Fd_Handler *_watch_hdlr; 6static Eldbus_Connection *dconn;
12static char *dpath; 7static Eldbus_Object *dobj;
13static const char *sid;
14 8
15static void 9static void
16_dbus_session_removed(DBusMessage *msg) 10_ecore_drm_dbus_device_pause_done(uint32_t major, uint32_t minor)
17{ 11{
18 const char *n, *o; 12 Eldbus_Proxy *proxy;
19 dbus_bool_t ret; 13 Eldbus_Message *msg;
20 14
21 ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &n, 15 /* try to get the Session proxy */
22 DBUS_TYPE_OBJECT_PATH, &o, DBUS_TYPE_INVALID); 16 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
23 if (!ret) return;
24
25 if (!strcmp(n, sid))
26 { 17 {
27 ERR("DBus Session Closed"); 18 ERR("Could not get eldbus session proxy");
28// ecore_main_loop_quit(); 19 return;
29 } 20 }
30}
31
32static void
33_dbus_cb_notify(DBusPendingCall *pending, void *data EINA_UNUSED)
34{
35 DBusMessage *msg;
36 DBusMessageIter iter, s;
37 dbus_bool_t ret;
38 int type = 0;
39 21
40 dbus_pending_call_unref(dpending); 22 if (!(msg = eldbus_proxy_method_call_new(proxy, "PauseDeviceComplete")))
41 dpending = NULL;
42
43 msg = dbus_pending_call_steal_reply(pending);
44 if (!msg) return;
45
46 type = dbus_message_get_type(msg);
47 if (type != DBUS_MESSAGE_TYPE_METHOD_RETURN) goto err;
48
49 if ((!dbus_message_iter_init(msg, &iter)) ||
50 (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT))
51 goto err;
52
53 dbus_message_iter_recurse(&iter, &s);
54
55 if (dbus_message_iter_get_arg_type(&s) != DBUS_TYPE_BOOLEAN)
56 goto err;
57
58 dbus_message_iter_get_basic(&s, &ret);
59 if (!ret)
60 { 23 {
61 /* TODO: emit paused signal to compositor ? */ 24 ERR("Could not create method call for proxy");
25 return;
62 } 26 }
63 27
64err: 28 eldbus_message_arguments_append(msg, "uu", major, minor);
65 dbus_message_unref(msg); 29 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
66} 30}
67 31
68static void 32static void
69_dbus_active_get(void) 33_cb_session_removed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
70{ 34{
71 DBusPendingCall *pend; 35 const char *errname, *errmsg;
72 DBusMessage *msg; 36 const char *sid;
73 dbus_bool_t ret;
74 const char *iface, *n;
75
76 msg =
77 dbus_message_new_method_call("org.freedesktop.login1", dpath,
78 "org.freedesktop.DBus.Properties", "Get");
79 if (!msg) return;
80 37
81 iface = "org.freedesktop.login1.Session"; 38 DBG("Session Removed");
82 n = "Active";
83 39
84 ret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &iface, 40 if (eldbus_message_error_get(msg, &errname, &errmsg))
85 DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID);
86 if (!ret) goto err;
87
88 ret = dbus_connection_send_with_reply(dconn, msg, &pend, -1);
89 if (!ret) goto err;
90
91 ret = dbus_pending_call_set_notify(pend, _dbus_cb_notify, NULL, NULL);
92 if (!ret)
93 { 41 {
94 dbus_pending_call_cancel(pend); 42 ERR("Eldbus Message Error: %s %s", errname, errmsg);
95 dbus_pending_call_unref(pend); 43 return;
96 goto err;
97 } 44 }
98 45
99 if (dpending) 46 if (eldbus_message_arguments_get(msg, "s", &sid))
100 { 47 {
101 dbus_pending_call_cancel(dpending); 48 if (!strcmp(sid, dsession))
102 dbus_pending_call_unref(dpending); 49 ERR("\tCurrent Session Removed!!");
103 } 50 }
104
105 dpending = pend;
106
107 return;
108
109err:
110 dbus_message_unref(msg);
111} 51}
112 52
113static void 53static void
114_dbus_property_changed(DBusMessage *msg) 54_cb_device_paused(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
115{ 55{
116 DBusMessageIter iter, s, ent; 56 const char *errname, *errmsg;
117 const char *iface, *n; 57 const char *type;
118 dbus_bool_t ret; 58 uint32_t maj, min;
119
120 if ((!dbus_message_iter_init(msg, &iter)) ||
121 (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING))
122 return;
123
124 dbus_message_iter_get_basic(&iter, &iface);
125
126 if ((!dbus_message_iter_next(&iter)) ||
127 (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY))
128 return;
129 59
130 dbus_message_iter_recurse(&iter, &s); 60 if (eldbus_message_error_get(msg, &errname, &errmsg))
131 while (dbus_message_iter_get_arg_type(&s) == DBUS_TYPE_DICT_ENTRY)
132 { 61 {
133 dbus_message_iter_recurse(&s, &ent); 62 ERR("Eldbus Message Error: %s %s", errname, errmsg);
134 if (dbus_message_iter_get_arg_type(&ent) != DBUS_TYPE_STRING) 63 return;
135 return;
136
137 dbus_message_iter_get_basic(&ent, &n);
138 if (!dbus_message_iter_next(&ent)) return;
139
140 if (!strcmp(n, "Active"))
141 {
142 if (dbus_message_iter_get_arg_type(&ent) == DBUS_TYPE_BOOLEAN)
143 {
144 dbus_message_iter_get_basic(&ent, &ret);
145 if (!ret)
146 {
147 /* TODO: emit paused signal to compositor ? */
148 }
149 return;
150 }
151 }
152
153 dbus_message_iter_next(&s);
154 } 64 }
155 65
156 if ((!dbus_message_iter_next(&iter)) || 66 if (eldbus_message_arguments_get(msg, "uus", &maj, &min, &type))
157 (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY))
158 return;
159
160 dbus_message_iter_recurse(&iter, &s);
161 while (dbus_message_iter_get_arg_type(&s) == DBUS_TYPE_STRING)
162 { 67 {
163 dbus_message_iter_get_basic(&s, &n); 68 if (!strcmp(type, "pause"))
164 if (!strcmp(n, "Active"))
165 { 69 {
166 _dbus_active_get(); 70 /* TODO: device pause done */
167 return; 71 _ecore_drm_dbus_device_pause_done(maj, min);
168 } 72 }
169 73
170 dbus_message_iter_next(&s); 74 /* if (maj == DRM_MAJOR) */
171 } 75 /* { */
172} 76 /* // emit paused to compositor */
173 77 /* } */
174static void
175_dbus_device_pause_done(uint32_t major, uint32_t minor)
176{
177 DBusMessage *msg;
178 dbus_bool_t ret;
179
180 msg = dbus_message_new_method_call("org.freedesktop.login1", dpath,
181 "org.freedesktop.login1.Session",
182 "PauseDeviceComplete");
183 if (msg)
184 {
185 ret = dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
186 DBUS_TYPE_UINT32, &minor,
187 DBUS_TYPE_INVALID);
188 if (ret)
189 dbus_connection_send(dconn, msg, NULL);
190
191 dbus_message_unref(msg);
192 } 78 }
193} 79}
194 80
195static void 81static void
196_dbus_device_paused(DBusMessage *msg) 82_cb_device_resumed(void *ctxt EINA_UNUSED, const Eldbus_Message *msg)
197{ 83{
198 dbus_bool_t ret; 84 const char *errname, *errmsg;
199 const char *type;
200 uint32_t maj, min;
201
202 ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &maj,
203 DBUS_TYPE_UINT32, &min,
204 DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID);
205 if (!ret) return;
206
207 if (!strcmp(type, "pause"))
208 _dbus_device_pause_done(maj, min);
209
210 if (maj == DRM_MAJOR)
211 {
212 /* TODO: emit paused signal to compositor ? */
213 DBG("Emit Paused Signal To Compositor");
214 }
215}
216
217static void
218_dbus_device_resumed(DBusMessage *msg)
219{
220 dbus_bool_t ret;
221 uint32_t maj; 85 uint32_t maj;
222 86
223 ret = dbus_message_get_args(msg, NULL, 87 if (eldbus_message_error_get(msg, &errname, &errmsg))
224 DBUS_TYPE_UINT32, &maj, DBUS_TYPE_INVALID);
225 if (!ret) return;
226
227 if (maj == DRM_MAJOR)
228 { 88 {
229 /* TODO: emit active signal to compositor ? */ 89 ERR("Eldbus Message Error: %s %s", errname, errmsg);
230 DBG("Emit Active Signal To Compositor"); 90 return;
231 } 91 }
232}
233
234static void
235_dbus_device_release(uint32_t major, uint32_t minor)
236{
237 DBusMessage *msg;
238 92
239 msg = dbus_message_new_method_call("org.freedesktop.login1", dpath, 93 if (eldbus_message_arguments_get(msg, "u", &maj))
240 "org.freedesktop.login1.Session",
241 "ReleaseDevice");
242 if (msg)
243 { 94 {
244 dbus_bool_t ret; 95 /* if (maj == DRM_MAJOR) */
245 96 /* { */
246 ret = dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major, 97 /* // emit active to compositor */
247 DBUS_TYPE_UINT32, &minor, 98 /* } */
248 DBUS_TYPE_INVALID);
249 if (ret) dbus_connection_send(dconn, msg, NULL);
250 dbus_message_unref(msg);
251 } 99 }
252} 100}
253 101
254static int 102static void
255_dbus_device_take(uint32_t major, uint32_t minor) 103_cb_properties_changed(void *data EINA_UNUSED, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
256{ 104{
257 DBusMessage *msg, *rep; 105 Eldbus_Proxy_Event_Property_Changed *ev;
258 DBusError err; 106 /* const Eina_Value *val; */
259 dbus_bool_t p, ret;
260 int fd = -1;
261 107
262 msg = dbus_message_new_method_call("org.freedesktop.login1", dpath, 108 ev = event;
263 "org.freedesktop.login1.Session", 109 /* val = ev->value; */
264 "TakeDevice");
265 if (!msg) return -1;
266 110
267 ret = dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major, 111 DBG("Properties Changed: %s", ev->name);
268 DBUS_TYPE_UINT32, &minor, DBUS_TYPE_INVALID);
269 if (!ret) goto err;
270 112
271 dbus_error_init(&err); 113 if (!strcmp(ev->name, "Active"))
272
273 rep =
274 dbus_connection_send_with_reply_and_block(dconn, msg, -1, &err);
275 if (!rep)
276 { 114 {
277 if (dbus_error_has_name(&err, DBUS_ERROR_UNKNOWN_METHOD)) 115 /* TODO: Send 'Active' to login1.Session */
278 ERR("Old Systemd Version detected");
279 else if (dbus_error_is_set(&err))
280 ERR("DBusError: %s %s", err.name, err.message);
281 dbus_error_free(&err);
282 goto err;
283 }
284
285 ret = dbus_message_get_args(rep, &err, DBUS_TYPE_UNIX_FD, &fd,
286 DBUS_TYPE_BOOLEAN, &p, DBUS_TYPE_INVALID);
287 if (!ret)
288 {
289 if (dbus_error_is_set(&err))
290 ERR("DBusError: %s %s", err.name, err.message);
291
292 dbus_error_free(&err);
293 goto err_rep;
294 } 116 }
295
296 return fd;
297
298err_rep:
299 dbus_message_unref(rep);
300err:
301 dbus_message_unref(msg);
302 return -1;
303} 117}
304 118
305static int 119static Eina_Bool
306_dbus_device_open(const char *path) 120_ecore_drm_dbus_session_take(const char *session)
307{ 121{
308 struct stat st; 122 Eldbus_Proxy *proxy;
309 int ret, fl, fd = -1;
310 /* char name[256] = "unknown"; */
311
312 if ((ret = stat(path, &st)) < 0) return -1;
313 if (!S_ISCHR(st.st_mode)) return -1;
314
315 fd = _dbus_device_take(major(st.st_rdev), minor(st.st_rdev));
316 if (fd < 0)
317 {
318 ERR("Failed to take device: %s", path);
319 return -1;
320 }
321
322 if ((fl = fcntl(fd, F_GETFL)) < 0)
323 {
324 ERR("Failed to get file flags: %m");
325 goto flag_err;
326 }
327
328 fl = (O_RDWR | O_NONBLOCK);
329 123
330 if ((ret = fcntl(fd, F_SETFL, fl)) < 0) 124 if ((session) && (strcmp(session, dsession)))
331 { 125 {
332 ERR("Failed to set file flags: %m"); 126 ERR("Invalid session: %s", session);
333 goto flag_err; 127 return EINA_FALSE;
334 } 128 }
335 129
336 if ((fl = fcntl(fd, F_GETFD)) < 0) 130 /* try to get the Session proxy */
131 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
337 { 132 {
338 ERR("Failed to get file fd: %m"); 133 ERR("Could not get eldbus session proxy");
339 goto flag_err; 134 return EINA_FALSE;
340 } 135 }
341 136
342 fl &= ~FD_CLOEXEC; 137 /* send call to take control */
343 138 if (eldbus_proxy_call(proxy, "TakeControl", NULL, NULL, -1, "b", EINA_FALSE))
344 if ((ret = fcntl(fd, F_SETFD, fl)) < 0)
345 { 139 {
346 ERR("Failed to set file fds: %m"); 140 ERR("Could not send message to proxy");
347 goto flag_err; 141 return EINA_FALSE;
348 } 142 }
349 143
350 /* if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) */ 144 return EINA_TRUE;
351 /* { */
352 /* ERR("Could not get device name: %m"); */
353 /* goto flag_err; */
354 /* } */
355 /* else */
356 /* { */
357 /* name[sizeof(name) - 1] = '\0'; */
358 /* DBG("%s Opened", name); */
359 /* } */
360
361 return fd;
362
363flag_err:
364 close(fd);
365 _dbus_device_release(major(st.st_rdev), minor(st.st_rdev));
366 return -1;
367}
368
369static void
370_dbus_device_close(const char *path)
371{
372 struct stat st;
373 int ret;
374
375 if ((ret = stat(path, &st)) < 0) return;
376 if (!S_ISCHR(st.st_mode)) return;
377
378 _dbus_device_release(major(st.st_rdev), minor(st.st_rdev));
379}
380
381static DBusHandlerResult
382_dbus_cb_filter(DBusConnection *conn EINA_UNUSED, DBusMessage *msg, void *data EINA_UNUSED)
383{
384 if (dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
385 {
386 ERR("DBus Disconnected");
387 }
388 else if (dbus_message_is_signal(msg, "org.freedesktop.login1.Manager",
389 "SessionRemoved"))
390 _dbus_session_removed(msg);
391 else if (dbus_message_is_signal(msg, "org.freedesktop.DBus.Properties",
392 "PropertiesChanged"))
393 _dbus_property_changed(msg);
394 else if (dbus_message_is_signal(msg, "org.freedesktop.login1.Session",
395 "PauseDevice"))
396 _dbus_device_paused(msg);
397 else if (dbus_message_is_signal(msg, "org.freedesktop.login1.Sesion",
398 "ResumeDevice"))
399 _dbus_device_resumed(msg);
400
401 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
402} 145}
403 146
404static Eina_Bool 147static Eina_Bool
405_dbus_cb_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) 148_ecore_drm_dbus_session_release(const char *session)
406{ 149{
407 DBusConnection *conn; 150 Eldbus_Proxy *proxy;
408 int ret = 0;
409
410 if (!(conn = data)) return ECORE_CALLBACK_CANCEL;
411 151
412 do 152 if ((session) && (strcmp(session, dsession)))
413 { 153 {
414 ret = dbus_connection_dispatch(conn); 154 ERR("Invalid session: %s", session);
415 switch (ret) 155 return EINA_FALSE;
416 {
417 case DBUS_DISPATCH_COMPLETE:
418 ret = 0;
419 break;
420 case DBUS_DISPATCH_DATA_REMAINS:
421 ret = -EAGAIN;
422 break;
423 case DBUS_DISPATCH_NEED_MEMORY:
424 ret = -ENOMEM;
425 break;
426 default:
427 ret = -EIO;
428 break;
429 }
430 } while (ret == -EAGAIN);
431
432 return ECORE_CALLBACK_RENEW;
433}
434
435static Eina_Bool
436_dbus_cb_watch(void *data, Ecore_Fd_Handler *hdlr)
437{
438 DBusWatch *watch;
439 uint32_t flags = 0;
440
441 if (!(watch = data)) return ECORE_CALLBACK_RENEW;
442
443 if (dbus_watch_get_enabled(watch))
444 {
445 if (ecore_main_fd_handler_active_get(hdlr, ECORE_FD_READ))
446 flags |= DBUS_WATCH_READABLE;
447 if (ecore_main_fd_handler_active_get(hdlr, ECORE_FD_WRITE))
448 flags |= DBUS_WATCH_WRITABLE;
449 if (ecore_main_fd_handler_active_get(hdlr, ECORE_FD_ERROR))
450 flags |= DBUS_WATCH_ERROR;
451
452 dbus_watch_handle(watch, flags);
453 } 156 }
454 157
455 return ECORE_CALLBACK_RENEW; 158 /* try to get the Session proxy */
456} 159 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
457
458static dbus_bool_t
459_dbus_watch_add(DBusWatch *watch, void *data EINA_UNUSED)
460{
461 uint32_t msk = 0, flags = 0;
462 int fd = -1;
463
464 msk |= ECORE_FD_ERROR;
465 if (dbus_watch_get_enabled(watch))
466 { 160 {
467 flags = dbus_watch_get_flags(watch); 161 ERR("Could not get eldbus session proxy");
468 if (flags & DBUS_WATCH_READABLE) 162 return EINA_FALSE;
469 msk |= ECORE_FD_READ;
470 if (flags & DBUS_WATCH_WRITABLE)
471 msk |= ECORE_FD_WRITE;
472 } 163 }
473 164
474 fd = dbus_watch_get_unix_fd(watch); 165 /* send call to release control */
475 166 if (!eldbus_proxy_call(proxy, "ReleaseControl", NULL, NULL, -1, ""))
476 _watch_hdlr = 167 ERR("Could not send ReleaseControl message to proxy");
477 ecore_main_fd_handler_add(fd, msk, _dbus_cb_watch, watch, NULL, NULL);
478
479 dbus_watch_set_data(watch, _watch_hdlr, NULL);
480
481 return TRUE;
482}
483
484static void
485_dbus_watch_del(DBusWatch *watch, void *data EINA_UNUSED)
486{
487 Ecore_Fd_Handler *hdlr;
488 168
489 if (!(hdlr = dbus_watch_get_data(watch))) return; 169 return EINA_TRUE;
490 ecore_main_fd_handler_del(hdlr);
491 _watch_hdlr = NULL;
492} 170}
493 171
494static void 172static void
495_dbus_watch_toggle(DBusWatch *watch, void *data EINA_UNUSED) 173_ecore_drm_dbus_device_release(uint32_t major, uint32_t minor)
496{ 174{
497 uint32_t flags = 0, mask = 0; 175 Eldbus_Proxy *proxy;
498 Ecore_Fd_Handler *hdlr; 176 Eldbus_Message *msg;
499 177
500 if (!(hdlr = dbus_watch_get_data(watch))) return; 178 /* try to get the Session proxy */
501 179 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
502 if (dbus_watch_get_enabled(watch))
503 { 180 {
504 flags = dbus_watch_get_flags(watch); 181 ERR("Could not get eldbus session proxy");
505 if (flags & DBUS_WATCH_READABLE) 182 return;
506 mask |= ECORE_FD_READ;
507 if (flags & DBUS_WATCH_WRITABLE)
508 mask |= ECORE_FD_WRITE;
509 } 183 }
510 184
511 ecore_main_fd_handler_active_set(hdlr, mask); 185 if (!(msg = eldbus_proxy_method_call_new(proxy, "ReleaseDevice")))
512}
513
514static Eina_Bool
515_dbus_cb_timeout(void *data)
516{
517 DBusTimeout *timeout;
518
519 if (!(timeout = data)) return ECORE_CALLBACK_RENEW;
520
521 if (dbus_timeout_get_enabled(timeout))
522 dbus_timeout_handle(timeout);
523
524 return ECORE_CALLBACK_RENEW;
525}
526
527static dbus_bool_t
528_dbus_timeout_add(DBusTimeout *timeout, void *data EINA_UNUSED)
529{
530 if (dbus_timeout_get_enabled(timeout))
531 { 186 {
532 Ecore_Timer *tmr = NULL; 187 ERR("Could not create method call for proxy");
533 int tme; 188 return;
534
535 tme = dbus_timeout_get_interval(timeout);
536 if (!(tmr = ecore_timer_loop_add(tme, _dbus_cb_timeout, timeout)))
537 return EINA_FALSE;
538
539 dbus_timeout_set_data(timeout, tmr, NULL);
540 } 189 }
541 190
542 return EINA_TRUE; 191 eldbus_message_arguments_append(msg, "uu", major, minor);
543}
544 192
545static void 193 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
546_dbus_timeout_del(DBusTimeout *timeout, void *data EINA_UNUSED)
547{
548 Ecore_Timer *tmr = NULL;
549
550 if (!(tmr = dbus_timeout_get_data(timeout))) return;
551 ecore_timer_del(tmr);
552} 194}
553 195
554static void 196static int
555_dbus_timeout_toggle(DBusTimeout *timeout, void *data EINA_UNUSED) 197_ecore_drm_dbus_device_take(uint32_t major, uint32_t minor, Eldbus_Message_Cb callback, const void *data)
556{
557 Ecore_Timer *tmr = NULL;
558
559 if (!(tmr = dbus_timeout_get_data(timeout))) return;
560
561 if (dbus_timeout_get_enabled(timeout))
562 ecore_timer_thaw(tmr);
563 else
564 ecore_timer_freeze(tmr);
565}
566
567static Eina_Bool
568_dbus_match_add(DBusConnection *conn, const char *format, ...)
569{ 198{
570 DBusError err; 199 Eldbus_Proxy *proxy;
571 va_list lst; 200 Eldbus_Message *msg;
572 char *tmp;
573 int ret;
574 201
575 va_start(lst, format); 202 /* try to get the Session proxy */
576 ret = vasprintf(&tmp, format, lst); 203 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
577 va_end(lst);
578
579 if (ret < 0) return EINA_FALSE;
580
581 dbus_error_init(&err);
582 dbus_bus_add_match(conn, tmp, &err);
583 free(tmp);
584
585 if (dbus_error_is_set(&err))
586 { 204 {
587 dbus_error_free(&err); 205 ERR("Could not get eldbus session proxy");
588 return EINA_FALSE; 206 return -1;
589 } 207 }
590 208
591 return EINA_TRUE; 209 if (!(msg = eldbus_proxy_method_call_new(proxy, "TakeDevice")))
592}
593
594static Eina_Bool
595_dbus_signal_add(DBusConnection *conn, const char *sender, const char *iface, const char *mem, const char *path)
596{
597 return _dbus_match_add(conn, "type='signal',sender='%s',"
598 "interface='%s',member='%s',path='%s'",
599 sender, iface, mem, path);
600}
601
602static Eina_Bool
603_dbus_setup(void)
604{
605 int ret = 0;
606 dbus_bool_t res;
607
608 ret = asprintf(&dpath, "/org/freedesktop/login1/session/%s", sid);
609 if (ret < 0) return EINA_FALSE;
610
611 res = dbus_connection_add_filter(dconn, _dbus_cb_filter, NULL, NULL);
612 if (!res)
613 { 210 {
614 ERR("Could not setup dbus filter: %m\n"); 211 ERR("Could not create method call for proxy");
615 goto err; 212 return -1;
616 } 213 }
617 214
618 res = _dbus_signal_add(dconn, "org.freedesktop.login1", 215 eldbus_message_arguments_append(msg, "uu", major, minor);
619 "org.freedesktop.login1.Manager", 216 eldbus_proxy_send(proxy, msg, callback, data, -1);
620 "SessionRemoved", "/org/freedesktop/login1");
621 if (!res) goto err;
622
623 res = _dbus_signal_add(dconn, "org.freedesktop.login1",
624 "org.freedesktop.login1.Session",
625 "PauseDevice", dpath);
626 if (!res) goto err;
627
628 res = _dbus_signal_add(dconn, "org.freedesktop.login1",
629 "org.freedesktop.login1.Session",
630 "ResumeDevice", dpath);
631 if (!res) goto err;
632 217
633 res = _dbus_signal_add(dconn, "org.freedesktop.login1", 218 return 1;
634 "org.freedesktop.DBus.Properties",
635 "PropertiesChanged", dpath);
636 if (!res) goto err;
637
638 return EINA_TRUE;
639
640err:
641 free(dpath);
642 return EINA_FALSE;
643} 219}
644 220
645static Eina_Bool 221int
646_dbus_control_take(void) 222_ecore_drm_dbus_init(const char *session)
647{ 223{
648 DBusError err; 224 Eldbus_Proxy *proxy;
649 DBusMessage *msg, *rep; 225 int ret = 0;
650 dbus_bool_t f = EINA_FALSE; 226 char *dpath;
651
652 dbus_error_init(&err);
653 227
654 msg = 228 if (++_dbus_init_count != 1) return _dbus_init_count;
655 dbus_message_new_method_call("org.freedesktop.login1", dpath,
656 "org.freedesktop.login1.Session",
657 "TakeControl");
658 if (!msg) goto err;
659 229
660 if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &f, DBUS_TYPE_INVALID)) 230 if (!session) return --_dbus_init_count;
661 goto msg_err;
662 231
663 rep = dbus_connection_send_with_reply_and_block(dconn, msg, -1, &err); 232 /* try to init eldbus */
664 if (!rep) 233 if (!eldbus_init())
665 { 234 {
666 if (dbus_error_has_name(&err, DBUS_ERROR_UNKNOWN_METHOD)) 235 ERR("Could not init eldbus library");
667 ERR("Old Systemd Version detected\n"); 236 return --_dbus_init_count;
668 goto msg_err;
669 } 237 }
670 238
671 dbus_message_unref(rep); 239 dsession = eina_stringshare_add(session);
672 dbus_message_unref(msg);
673 dbus_error_free(&err);
674
675 return EINA_TRUE;
676
677msg_err:
678 dbus_message_unref(msg);
679err:
680 if (dbus_error_is_set(&err))
681 ERR("DBusError: %s %s", err.name, err.message);
682 dbus_error_free(&err);
683 return EINA_FALSE;
684}
685
686static void
687_dbus_control_release(void)
688{
689 DBusMessage *msg;
690 240
691 msg = 241 /* try to get the dbus connection */
692 dbus_message_new_method_call("org.freedesktop.login1", dpath, 242 if (!(dconn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM)))
693 "org.freedesktop.login1.Session",
694 "ReleaseControl");
695 if (msg)
696 { 243 {
697 dbus_connection_send(dconn, msg, NULL); 244 ERR("Failed to get eldbus system connection");
698 dbus_message_unref(msg); 245 goto conn_err;
699 } 246 }
700}
701
702static Eina_Bool
703_dbus_bind(DBusConnection *conn)
704{
705 int fd = -1;
706 247
707 if ((fd = eventfd(0, EFD_CLOEXEC)) < 0) 248 /* assemble dbus path */
249 ret = asprintf(&dpath, "/org/freedesktop/login1/session/%s", session);
250 if (ret < 0)
708 { 251 {
709 ERR("Could not create eventfd: %m"); 252 ERR("Could not assemble dbus path");
710 return EINA_FALSE; 253 goto path_err;
711 } 254 }
712 255
713 _dbus_hdlr = 256 /* try to get the eldbus object */
714 ecore_main_fd_handler_add(fd, (ECORE_FD_READ | ECORE_FD_WRITE), 257 if (!(dobj = eldbus_object_get(dconn, "org.freedesktop.login1", dpath)))
715 _dbus_cb_dispatch, conn, NULL, NULL);
716 if (!_dbus_hdlr)
717 { 258 {
718 ERR("Failed to create ecore fd handler"); 259 ERR("Could not get eldbus object: %s", dpath);
719 goto hdlr_err; 260 goto obj_err;
720 } 261 }
721 262
722 if (!dbus_connection_set_watch_functions(conn, _dbus_watch_add, 263 /* try to get the Manager proxy */
723 _dbus_watch_del, 264 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Manager")))
724 _dbus_watch_toggle, NULL, NULL))
725 { 265 {
726 ERR("Failed to set dbus watch functions: %m"); 266 ERR("Could not get eldbus proxy");
727 goto watch_err; 267 goto proxy_err;
728 } 268 }
729 269
730 if (!dbus_connection_set_timeout_functions(conn, _dbus_timeout_add, 270 eldbus_proxy_signal_handler_add(proxy, "SessionRemoved",
731 _dbus_timeout_del, 271 _cb_session_removed, NULL);
732 _dbus_timeout_toggle, 272
733 NULL, NULL)) 273 /* try to get the Session proxy */
274 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.login1.Session")))
734 { 275 {
735 ERR("Failed to set dbus timeout functions: %m"); 276 ERR("Could not get eldbus proxy");
736 goto timeout_err; 277 goto proxy_err;
737 } 278 }
738 279
739 dbus_connection_ref(conn); 280 eldbus_proxy_signal_handler_add(proxy, "PauseDevice",
740 281 _cb_device_paused, NULL);
741 return EINA_TRUE; 282 eldbus_proxy_signal_handler_add(proxy, "ResumeDevice",
283 _cb_device_resumed, NULL);
742 284
743timeout_err: 285 /* try to get the Properties proxy */
744 dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); 286 if (!(proxy = eldbus_proxy_get(dobj, "org.freedesktop.DBus.Properties")))
745watch_err:
746 ecore_main_fd_handler_del(_dbus_hdlr);
747 _dbus_hdlr = NULL;
748hdlr_err:
749 close(fd);
750 return EINA_FALSE;
751}
752
753static DBusConnection *
754_dbus_open(void)
755{
756 DBusConnection *conn;
757
758 dbus_connection_set_change_sigpipe(EINA_FALSE);
759
760 conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
761 if (!conn)
762 { 287 {
763 ERR("Failed to get dbus connection: %m"); 288 ERR("Could not get eldbus proxy");
764 goto conn_err; 289 goto proxy_err;
765 } 290 }
766 291
767 dbus_connection_set_exit_on_disconnect(conn, EINA_FALSE); 292 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
293 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
294 _cb_properties_changed, NULL);
768 295
769 if (!_dbus_bind(conn)) 296 if (!_ecore_drm_dbus_session_take(dsession))
770 { 297 {
771 ERR("Failed to bind dbus: %m"); 298 ERR("Failed to take control of session");
772 goto bind_err; 299 goto session_err;
773 } 300 }
774 301
775 return conn; 302 return _dbus_init_count;
776 303
777bind_err: 304session_err:
778 dbus_connection_close(conn); 305 eldbus_proxy_event_callback_del(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
779 dbus_connection_unref(conn); 306 _cb_properties_changed, NULL);
307proxy_err:
308 eldbus_object_unref(dobj);
309obj_err:
310 free(dpath);
311path_err:
312 eldbus_connection_unref(dconn);
780conn_err: 313conn_err:
781 return NULL; 314 eina_stringshare_del(dsession);
782} 315 eldbus_shutdown();
783 316 return --_dbus_init_count;
784static void
785_dbus_close(void)
786{
787 dbus_connection_set_timeout_functions(dconn, NULL, NULL, NULL, NULL, NULL);
788 dbus_connection_set_watch_functions(dconn, NULL, NULL, NULL, NULL, NULL);
789
790 if (_dbus_hdlr) ecore_main_fd_handler_del(_dbus_hdlr);
791 _dbus_hdlr = NULL;
792
793 dbus_connection_close(dconn);
794 dbus_connection_unref(dconn);
795} 317}
796 318
797Eina_Bool 319int
798_ecore_drm_dbus_init(const char *session) 320_ecore_drm_dbus_shutdown(void)
799{ 321{
800 if (dconn) return EINA_TRUE; 322 if (--_dbus_init_count != 0) return _dbus_init_count;
801 323
802 /* try to init dbus */ 324 /* release control of the session */
803 if (!(dconn = _dbus_open())) return EINA_FALSE; 325 _ecore_drm_dbus_session_release(dsession);
804 326
805 sid = eina_stringshare_add(session); 327 /* release dbus object */
328 if (dobj) eldbus_object_unref(dobj);
806 329
807 /* try to setup signal handlers */ 330 /* release the dbus connection */
808 if (!_dbus_setup()) goto setup_err; 331 if (dconn) eldbus_connection_unref(dconn);
809 332
810 /* try to take control of the session */ 333 eina_stringshare_del(dsession);
811 if (!_dbus_control_take()) goto setup_err;
812 334
813 return EINA_TRUE; 335 /* shutdown eldbus library */
336 eldbus_shutdown();
814 337
815setup_err: 338 return _dbus_init_count;
816 _dbus_close();
817 eina_stringshare_del(sid);
818 return EINA_FALSE;
819} 339}
820 340
821void 341void
822_ecore_drm_dbus_shutdown(void) 342_ecore_drm_dbus_device_open(const char *device, Eldbus_Message_Cb callback, const void *data)
823{ 343{
824 _dbus_control_release(); 344 struct stat st;
825 _dbus_close();
826 eina_stringshare_del(sid);
827 free(dpath);
828}
829 345
830int 346 if (stat(device, &st) < 0) return;
831_ecore_drm_dbus_device_open(const char *device) 347 if (!S_ISCHR(st.st_mode)) return;
832{ 348
833 return _dbus_device_open(device); 349 _ecore_drm_dbus_device_take(major(st.st_rdev), minor(st.st_rdev), callback, data);
834} 350}
835 351
836void 352void
837_ecore_drm_dbus_device_close(const char *device) 353_ecore_drm_dbus_device_close(const char *device)
838{ 354{
839 _dbus_device_close(device); 355 struct stat st;
356
357 if (stat(device, &st) < 0) return;
358 if (!S_ISCHR(st.st_mode)) return;
359
360 _ecore_drm_dbus_device_release(major(st.st_rdev), minor(st.st_rdev));
840} 361}