summaryrefslogtreecommitdiff
path: root/src/lib/elput/elput_logind.c
diff options
context:
space:
mode:
authorChris Michael <cpmichael@osg.samsung.com>2016-03-31 12:34:32 -0400
committerChris Michael <cpmichael@osg.samsung.com>2016-04-13 14:16:17 -0400
commited3a1f39587187c8acf305fd793f92218995c486 (patch)
treeaf2655dafed5e019d6e5085a50e9f1fbc51532aa /src/lib/elput/elput_logind.c
parent08482e1ca4feaff2c631a125b58fda7e57084b97 (diff)
elput: Add input manager interface and APIs to connect & disconnect
This commit adds the start of the Elput Manager & Interface code. This will be used as an inteface to various backend methods of session & device control (ie: systemd, direct interface, etc). This will provide various abstractions for working with libinput when opening/closing input devices. Signed-off-by: Chris Michael <cpmichael@osg.samsung.com>
Diffstat (limited to 'src/lib/elput/elput_logind.c')
-rw-r--r--src/lib/elput/elput_logind.c450
1 files changed, 450 insertions, 0 deletions
diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c
new file mode 100644
index 0000000000..d649bf34ea
--- /dev/null
+++ b/src/lib/elput/elput_logind.c
@@ -0,0 +1,450 @@
1#include "elput_private.h"
2
3#ifdef HAVE_SYSTEMD
4
5static void
6_logind_device_pause_complete(Elput_Manager *em, uint32_t major, uint32_t minor)
7{
8 Eldbus_Proxy *proxy;
9 Eldbus_Message *msg;
10
11 proxy =
12 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
13 if (!proxy)
14 {
15 ERR("Could not get proxy for session");
16 return;
17 }
18
19 msg = eldbus_proxy_method_call_new(proxy, "PauseDeviceComplete");
20 if (!msg)
21 {
22 ERR("Could not create method call for proxy");
23 goto end;
24 }
25
26 eldbus_message_arguments_append(msg, "uu", major, minor);
27
28 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
29
30end:
31 eldbus_message_unref(msg);
32 eldbus_proxy_unref(proxy);
33}
34
35static void
36_cb_session_removed(void *data, const Eldbus_Message *msg)
37{
38 Elput_Manager *em;
39 const char *errname, *errmsg;
40 const char *sid;
41
42 em = data;
43
44 if (eldbus_message_error_get(msg, &errname, &errmsg))
45 {
46 ERR("Eldbus Message Error: %s %s", errname, errmsg);
47 return;
48 }
49
50 if (eldbus_message_arguments_get(msg, "s", &sid))
51 {
52 if (!strcmp(sid, em->sid))
53 {
54 WRN("Logind session removed");
55 /* TODO: call manager restore function */
56 }
57 }
58}
59
60static void
61_cb_device_paused(void *data, const Eldbus_Message *msg)
62{
63 Elput_Manager *em;
64 const char *errname, *errmsg;
65 const char *type;
66 uint32_t maj, min;
67
68 em = data;
69
70 if (eldbus_message_error_get(msg, &errname, &errmsg))
71 {
72 ERR("Eldbus Message Error: %s %s", errname, errmsg);
73 return;
74 }
75
76 if (eldbus_message_arguments_get(msg, "uus", &maj, &min, &type))
77 {
78 if (!strcmp(type, "pause"))
79 _logind_device_pause_complete(em, maj, min);
80
81 /* TODO */
82 /* if ((em->sync) && (maj == DRM_MAJOR)) */
83 /* _ecore_drm2_launcher_activate_send(em, EINA_FALSE); */
84 }
85}
86
87static void
88_cb_device_resumed(void *data, const Eldbus_Message *msg)
89{
90 Elput_Manager *em;
91 const char *errname, *errmsg;
92 uint32_t maj, min;
93 int fd;
94
95 em = data;
96
97 if (eldbus_message_error_get(msg, &errname, &errmsg))
98 {
99 ERR("Eldbus Message Error: %s %s", errname, errmsg);
100 return;
101 }
102
103 if (eldbus_message_arguments_get(msg, "uuh", &maj, &min, &fd))
104 {
105 /* TODO */
106 /* if ((em->sync) && (maj == DRM_MAJOR)) */
107 /* _ecore_drm2_launcher_activate_send(em, EINA_TRUE); */
108 }
109}
110
111static void
112_cb_property_changed(void *data, Eldbus_Proxy *proxy EINA_UNUSED, void *event)
113{
114 Elput_Manager *em;
115 Eldbus_Proxy_Event_Property_Changed *ev;
116 Eina_Bool active = EINA_FALSE;
117
118 em = data;
119 ev = event;
120
121 DBG("DBus Property Changed: %s", ev->name);
122
123 if (!strcmp(ev->name, "Active"))
124 {
125 eina_value_get(ev->value, &active);
126 /* TODO */
127 /* if ((!em->sync) || (!active)) */
128 /* _ecore_drm2_launcher_activate_send(em, active); */
129 }
130}
131
132static Eina_Bool
133_logind_session_vt_get(const char *sid, unsigned int *vt)
134{
135# ifdef HAVE_SYSTEMD_LOGIN_209
136 return (sd_session_get_vt(sid, vt) >= 0);
137# else
138 int ret = 0;
139 char *tty;
140
141 ret = sd_session_get_tty(sid, &tty);
142 if (ret < 0) return ret;
143
144 ret = sscanf(tty, "tty%u", vt);
145 free(tty);
146
147 if (ret != 1) return EINA_FALSE;
148 return EINA_TRUE;
149# endif
150}
151
152static Eina_Bool
153_logind_dbus_open(Eldbus_Connection **conn)
154{
155 if (!eldbus_init()) return EINA_FALSE;
156
157 *conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
158 if (!*conn) return EINA_FALSE;
159
160 return EINA_TRUE;
161}
162
163static void
164_logind_dbus_close(Eldbus_Connection *conn)
165{
166 if (conn) eldbus_connection_unref(conn);
167 eldbus_shutdown();
168}
169
170static Eina_Bool
171_logind_dbus_setup(Elput_Manager *em)
172{
173 Eldbus_Proxy *proxy;
174 int ret = 0;
175
176 ret = asprintf(&em->dbus.path,
177 "/org/freedesktop/login1/session/%s", em->sid);
178 if (ret < 0) return EINA_FALSE;
179
180 em->dbus.obj =
181 eldbus_object_get(em->dbus.conn, "org.freedesktop.login1",
182 em->dbus.path);
183 if (!em->dbus.obj)
184 {
185 ERR("Could not get dbus object");
186 goto obj_err;
187 }
188
189 proxy =
190 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Manager");
191 if (!proxy)
192 {
193 ERR("Could not get dbus proxy");
194 goto proxy_err;
195 }
196
197 eldbus_proxy_signal_handler_add(proxy, "SessionRemoved",
198 _cb_session_removed, em);
199 eldbus_proxy_unref(proxy);
200
201 proxy =
202 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
203 if (!proxy)
204 {
205 ERR("Could not get dbus proxy");
206 goto proxy_err;
207 }
208
209 eldbus_proxy_signal_handler_add(proxy, "PauseDevice",
210 _cb_device_paused, em);
211 eldbus_proxy_signal_handler_add(proxy, "ResumeDevice",
212 _cb_device_resumed, em);
213 eldbus_proxy_unref(proxy);
214
215 proxy =
216 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.DBus.Properties");
217 if (!proxy)
218 {
219 ERR("Could not get dbus proxy");
220 goto proxy_err;
221 }
222
223 eldbus_proxy_properties_monitor(proxy, EINA_TRUE);
224 eldbus_proxy_event_callback_add(proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
225 _cb_property_changed, em);
226 eldbus_proxy_unref(proxy);
227
228 return EINA_TRUE;
229
230proxy_err:
231 eldbus_object_unref(em->dbus.obj);
232obj_err:
233 free(em->dbus.path);
234 return EINA_FALSE;
235}
236
237static Eina_Bool
238_logind_control_take(Elput_Manager *em)
239{
240 Eldbus_Proxy *proxy;
241 Eldbus_Message *msg, *reply;
242 const char *errname, *errmsg;
243
244 proxy =
245 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
246 if (!proxy)
247 {
248 ERR("Could not get proxy for session");
249 return EINA_FALSE;
250 }
251
252 msg = eldbus_proxy_method_call_new(proxy, "TakeControl");
253 if (!msg)
254 {
255 ERR("Could not create method call for proxy");
256 goto msg_err;
257 }
258
259 eldbus_message_arguments_append(msg, "b", EINA_FALSE);
260
261 reply = eldbus_proxy_send_and_block(proxy, msg, -1);
262 if (eldbus_message_error_get(reply, &errname, &errmsg))
263 {
264 ERR("Eldbus Message Error: %s %s", errname, errmsg);
265 goto msg_err;
266 }
267
268 eldbus_message_unref(reply);
269 eldbus_proxy_unref(proxy);
270
271 return EINA_TRUE;
272
273msg_err:
274 eldbus_proxy_unref(proxy);
275 return EINA_FALSE;
276}
277
278static void
279_logind_control_release(Elput_Manager *em)
280{
281 Eldbus_Proxy *proxy;
282 Eldbus_Message *msg;
283
284 proxy =
285 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
286 if (!proxy)
287 {
288 ERR("Could not get proxy for session");
289 return;
290 }
291
292 msg = eldbus_proxy_method_call_new(proxy, "ReleaseControl");
293 if (!msg)
294 {
295 ERR("Could not create method call for proxy");
296 goto end;
297 }
298
299 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
300
301end:
302 eldbus_proxy_unref(proxy);
303}
304
305static Eina_Bool
306_logind_activate(Elput_Manager *em)
307{
308 Eldbus_Proxy *proxy;
309 Eldbus_Message *msg;
310
311 proxy =
312 eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session");
313 if (!proxy)
314 {
315 ERR("Could not get proxy for session");
316 return EINA_FALSE;
317 }
318
319 msg = eldbus_proxy_method_call_new(proxy, "Activate");
320 if (!msg)
321 {
322 ERR("Could not create method call for proxy");
323 goto msg_err;
324 }
325
326 eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
327
328 eldbus_proxy_unref(proxy);
329
330 return EINA_TRUE;
331
332msg_err:
333 eldbus_proxy_unref(proxy);
334 return EINA_FALSE;
335}
336
337static Eina_Bool
338_logind_connect(Elput_Manager **manager, const char *seat, unsigned int tty, Eina_Bool sync)
339{
340 Elput_Manager *em;
341 int ret = 0;
342 char *s;
343
344 em = calloc(1, sizeof(Elput_Manager));
345 if (!em) return EINA_FALSE;
346
347 em->interface = &_logind_interface;
348 em->sync = sync;
349 em->seat = eina_stringshare_add(seat);
350
351 ret = sd_pid_get_session(getpid(), &em->sid);
352 if (ret < 0)
353 {
354 ERR("Could not get systemd session");
355 goto session_err;
356 }
357
358 ret = sd_session_get_seat(em->sid, &s);
359 if (ret < 0)
360 {
361 ERR("Failed to get session seat");
362 free(s);
363 goto seat_err;
364 }
365 else if ((seat) && (strcmp(seat, s)))
366 {
367 ERR("Seat '%s' differs from session seat '%s'", seat, s);
368 free(s);
369 goto seat_err;
370 }
371
372 if (!_logind_session_vt_get(em->sid, &em->vt_num))
373 {
374 ERR("Could not get session vt");
375 goto vt_err;
376 }
377 else if ((tty > 0) && (em->vt_num != tty))
378 {
379 ERR("Requested VT %u differs from session VT %u", tty, em->vt_num);
380 goto vt_err;
381 }
382
383 free(s);
384
385 if (!_logind_dbus_open(&em->dbus.conn))
386 {
387 ERR("Could not connect to dbus");
388 goto vt_err;
389 }
390
391 if (!_logind_dbus_setup(em))
392 {
393 ERR("Could not setup dbus");
394 goto dbus_err;
395 }
396
397 if (!_logind_control_take(em))
398 {
399 ERR("Could not take control of session");
400 goto ctrl_err;
401 }
402
403 if (!_logind_activate(em))
404 {
405 ERR("Could not activate session");
406 goto actv_err;
407 }
408
409 *(Elput_Manager **)manager = em;
410
411 return EINA_TRUE;
412
413actv_err:
414 _logind_control_release(em);
415ctrl_err:
416 eldbus_object_unref(em->dbus.obj);
417 free(em->dbus.path);
418dbus_err:
419 _logind_dbus_close(em->dbus.conn);
420vt_err:
421seat_err:
422 free(em->sid);
423session_err:
424 free(em);
425 return EINA_FALSE;
426}
427
428static void
429_logind_disconnect(Elput_Manager *em)
430{
431 _logind_control_release(em);
432 eldbus_object_unref(em->dbus.obj);
433 free(em->dbus.path);
434 _logind_dbus_close(em->dbus.conn);
435 eina_stringshare_del(em->seat);
436 free(em->sid);
437 free(em);
438}
439
440Elput_Interface _logind_interface =
441{
442 _logind_connect,
443 _logind_disconnect,
444 NULL,
445 NULL,
446 NULL,
447 NULL,
448};
449
450#endif