summaryrefslogtreecommitdiff
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
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>
-rw-r--r--src/Makefile_Elput.am2
-rw-r--r--src/lib/elput/Elput.h36
-rw-r--r--src/lib/elput/elput_logind.c450
-rw-r--r--src/lib/elput/elput_manager.c39
-rw-r--r--src/lib/elput/elput_private.h32
5 files changed, 559 insertions, 0 deletions
diff --git a/src/Makefile_Elput.am b/src/Makefile_Elput.am
index 851d4ee260..3e1ed58861 100644
--- a/src/Makefile_Elput.am
+++ b/src/Makefile_Elput.am
@@ -9,6 +9,8 @@ dist_installed_elputmainheaders_DATA = \
9 lib/elput/Elput.h 9 lib/elput/Elput.h
10 10
11lib_elput_libelput_la_SOURCES = \ 11lib_elput_libelput_la_SOURCES = \
12lib/elput/elput_logind.c \
13lib/elput/elput_manager.c \
12lib/elput/elput.c \ 14lib/elput/elput.c \
13lib/elput/elput_private.h 15lib/elput/elput_private.h
14 16
diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h
index 7c88e4bed6..e098b138e8 100644
--- a/src/lib/elput/Elput.h
+++ b/src/lib/elput/Elput.h
@@ -25,6 +25,9 @@
25 25
26# ifdef EFL_BETA_API_SUPPORT 26# ifdef EFL_BETA_API_SUPPORT
27 27
28/* opaque structure to represent an input manager */
29typedef struct _Elput_Manager Elput_Manager;
30
28/** 31/**
29 * @file 32 * @file
30 * @brief Ecore functions for dealing with libinput 33 * @brief Ecore functions for dealing with libinput
@@ -35,6 +38,7 @@
35 * Elput provides a wrapper and functions for using libinput 38 * Elput provides a wrapper and functions for using libinput
36 * 39 *
37 * @li @ref Elput_Init_Group 40 * @li @ref Elput_Init_Group
41 * @li @ref Elput_Manager_Group
38 * 42 *
39 */ 43 */
40 44
@@ -66,6 +70,38 @@ EAPI int elput_init(void);
66 */ 70 */
67EAPI int elput_shutdown(void); 71EAPI int elput_shutdown(void);
68 72
73/**
74 * @defgroup Elput_Manager_Group
75 *
76 * Functions that deal with connecting, disconnecting, opening, closing
77 * of input devices.
78 *
79 */
80
81/**
82 * Create an input manager on the specified seat
83 *
84 * @param seat
85 * @param tty
86 * @param sync
87 *
88 * @return A Elput_Manager on success, NULL on failure
89 *
90 * @ingroup Elput_Manager_Group
91 * @since 1.18
92 */
93EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty, Eina_Bool sync);
94
95/**
96 * Disconnect an input manager
97 *
98 * @param manager
99 *
100 * @ingroup Elput_Manager_Group
101 * @since 1.18
102 */
103EAPI void elput_manager_disconnect(Elput_Manager *manager);
104
69# endif 105# endif
70 106
71# undef EAPI 107# undef EAPI
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
diff --git a/src/lib/elput/elput_manager.c b/src/lib/elput/elput_manager.c
new file mode 100644
index 0000000000..2073ff78f9
--- /dev/null
+++ b/src/lib/elput/elput_manager.c
@@ -0,0 +1,39 @@
1#include "elput_private.h"
2
3static Elput_Interface *_ifaces[] =
4{
5#ifdef HAVE_SYSTEMD
6 &_logind_interface,
7#endif
8 NULL, // launcher
9 NULL, // direct
10 NULL,
11};
12
13EAPI Elput_Manager *
14elput_manager_connect(const char *seat, unsigned int tty, Eina_Bool sync)
15{
16 Elput_Interface **it;
17
18 for (it = _ifaces; *it != NULL; it++)
19 {
20 Elput_Interface *iface;
21 Elput_Manager *em;
22
23 iface = *it;
24 if (iface->connect(&em, seat, tty, sync))
25 return em;
26 }
27
28 return NULL;
29}
30
31EAPI void
32elput_manager_disconnect(Elput_Manager *manager)
33{
34 EINA_SAFETY_ON_NULL_RETURN(manager);
35 EINA_SAFETY_ON_NULL_RETURN(manager->interface);
36
37 if (manager->interface->disconnect)
38 manager->interface->disconnect(manager);
39}
diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h
index 62b7395c29..07e147bcf5 100644
--- a/src/lib/elput/elput_private.h
+++ b/src/lib/elput/elput_private.h
@@ -12,6 +12,7 @@
12# include "Eldbus.h" 12# include "Eldbus.h"
13# include <Elput.h> 13# include <Elput.h>
14 14
15# include <unistd.h>
15# include <linux/vt.h> 16# include <linux/vt.h>
16# include <linux/kd.h> 17# include <linux/kd.h>
17# include <linux/major.h> 18# include <linux/major.h>
@@ -54,4 +55,35 @@ extern int _elput_log_dom;
54# endif 55# endif
55# define CRIT(...) EINA_LOG_DOM_CRIT(_elput_log_dom, __VA_ARGS__) 56# define CRIT(...) EINA_LOG_DOM_CRIT(_elput_log_dom, __VA_ARGS__)
56 57
58typedef struct _Elput_Interface
59{
60 Eina_Bool (*connect)(Elput_Manager **manager, const char *seat, unsigned int tty, Eina_Bool sync);
61 void (*disconnect)(Elput_Manager *manager);
62 int (*open)(Elput_Manager *manager, const char *path, int flags);
63 void (*close)(Elput_Manager *manager, int fd);
64 int (*activate)(Elput_Manager *manager, int vt);
65 void (*restore)(Elput_Manager *manager);
66} Elput_Interface;
67
68struct _Elput_Manager
69{
70 Elput_Interface *interface;
71
72 int fd;
73 char *sid;
74 const char *seat;
75 unsigned int vt_num;
76
77 struct
78 {
79 char *path;
80 Eldbus_Object *obj;
81 Eldbus_Connection *conn;
82 } dbus;
83
84 Eina_Bool sync : 1;
85};
86
87extern Elput_Interface _logind_interface;
88
57#endif 89#endif