e_devicemgr: create tizen_input_devices only for first bound seat & manager
[platform/upstream/enlightenment.git] / src / bin / e_devicemgr_wl.c
1 #include "e_devicemgr_private.h"
2
3 #ifdef HAVE_CYNARA
4 #define E_DEVMGR_CYNARA_ERROR_CHECK_GOTO(func_name, ret, label) \
5   do \
6     { \
7        if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret)) \
8           { \
9              _e_devicemgr_util_cynara_log(func_name, ret); \
10              goto label; \
11           } \
12     } \
13   while (0)
14
15 static void
16 _e_devicemgr_util_cynara_log(const char *func_name, int err)
17 {
18 #define CYNARA_BUFSIZE 128
19    char buf[CYNARA_BUFSIZE] = "\0";
20    int ret;
21
22    ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
23    if (ret != CYNARA_API_SUCCESS)
24      {
25         DMDBG("Failed to cynara_strerror: %d (error log about %s: %d)\n", ret, func_name, err);
26         return;
27      }
28    DMDBG("%s is failed: %s\n", func_name, buf);
29 }
30
31 static Eina_Bool
32 _e_devicemgr_util_do_privilege_check(struct wl_client *client, int socket_fd, const char *rule)
33 {
34    int ret, pid;
35    char *clientSmack=NULL, *uid=NULL, *client_session=NULL;
36    Eina_Bool res = EINA_FALSE;
37
38    /* If initialization of cynara has been failed, let's not to do further permission checks. */
39    if (e_devicemgr->wl_data->p_cynara == NULL && e_devicemgr->wl_data->cynara_initialized) return EINA_TRUE;
40    if (socket_fd < 0) return EINA_FALSE;
41
42    ret = cynara_creds_socket_get_client(socket_fd, CLIENT_METHOD_SMACK, &clientSmack);
43    E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_client", ret, finish);
44
45    ret = cynara_creds_socket_get_user(socket_fd, USER_METHOD_UID, &uid);
46    E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_user", ret, finish);
47
48    ret = cynara_creds_socket_get_pid(socket_fd, &pid);
49    E_DEVMGR_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_pid", ret, finish);
50
51    client_session = cynara_session_from_pid(pid);
52
53    ret = cynara_check(e_devicemgr->wl_data->p_cynara, clientSmack, client_session, uid, rule);
54
55    if (CYNARA_API_ACCESS_ALLOWED == ret)
56         res = EINA_TRUE;
57
58 finish:
59    E_FREE(client_session);
60    E_FREE(clientSmack);
61    E_FREE(uid);
62
63    return res;
64 }
65 #endif
66
67 static void
68 _e_devicemgr_wl_device_cb_axes_select(struct wl_client *client, struct wl_resource *resource, struct wl_array *axes)
69 {
70    return;
71 }
72
73 static void
74 _e_devicemgr_wl_device_cb_release(struct wl_client *client, struct wl_resource *resource)
75 {
76    wl_resource_destroy(resource);
77 }
78
79 static const struct tizen_input_device_interface _e_devicemgr_wl_device_interface =
80 {
81    _e_devicemgr_wl_device_cb_axes_select,
82    _e_devicemgr_wl_device_cb_release,
83 };
84
85 static void
86 _e_devicemgr_wl_device_cb_unbind(struct wl_resource *resource)
87 {
88    E_Devicemgr_Input_Device *dev;
89    E_Devicemgr_Input_Device_User_Data *device_user_data;
90    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
91
92    DMDBG("Unbind tizen_input_device: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
93    if (!(device_user_data = wl_resource_get_user_data(resource))) return;
94
95    mgr_data = device_user_data->mgr_data;
96    if (mgr_data)
97      {
98         mgr_data->user_data_list = eina_list_remove(mgr_data->user_data_list, device_user_data);
99      }
100
101    dev = device_user_data->dev;
102
103    device_user_data->dev = NULL;
104    device_user_data->dev_mgr_res = NULL;
105    device_user_data->seat_res = NULL;
106    device_user_data->dev_res = NULL;
107    device_user_data->mgr_data = NULL;
108    E_FREE(device_user_data);
109    wl_resource_set_user_data(resource, NULL);
110
111    if (!dev) return;
112    dev->resources = eina_list_remove(dev->resources, resource);
113 }
114
115 void
116 e_devicemgr_wl_device_update(E_Devicemgr_Input_Device *dev)
117 {
118    struct wl_array axes;
119    Eina_List *l;
120    struct wl_resource *res;
121
122    wl_array_init(&axes);
123
124    EINA_LIST_FOREACH(dev->resources, l, res)
125      {
126         tizen_input_device_send_device_info(res, dev->name, dev->clas, dev->subclas, &axes);
127      }
128 }
129
130 void
131 e_devicemgr_wl_device_add(E_Devicemgr_Input_Device *dev)
132 {
133    struct wl_resource *res, *seat_res, *dev_mgr_res;
134    Eina_List *l, *ll;
135    uint32_t serial;
136    struct wl_client *wc;
137    E_Devicemgr_Input_Device_User_Data *device_user_data;
138    struct wl_array axes;
139    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
140    E_Comp_Wl_Seat *seat_data;
141
142    /* TODO: find the seat corresponding to event */
143    serial = wl_display_next_serial(e_comp_wl->wl.disp);
144    wl_array_init(&axes);
145
146    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
147      {
148         seat_data = wl_resource_get_user_data(seat_res);
149         if (!seat_data->is_first_resource)
150           {
151              DMDBG("The seat (res:%d) is not the first resource bound to client (%p)",
152                    wl_resource_get_id(seat_res), wl_resource_get_client(seat_res));
153              continue;
154           }
155
156         wc = wl_resource_get_client(seat_res);
157
158         EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, ll, mgr_data)
159           {
160              dev_mgr_res = mgr_data->resource;
161              if (wl_resource_get_client(dev_mgr_res) != wc) continue;
162              if (!mgr_data->is_first_resource)
163                {
164                   DMDBG("This device_manager (res:%d) not the first resource bound to client (%p)",
165                         wl_resource_get_id(dev_mgr_res), wc);
166                   continue;
167                }
168              res = wl_resource_create(wc, &tizen_input_device_interface, 1, 0);
169              if (!res)
170                  {
171                   DMERR("Could not create tizen_input_device resource");
172                   wl_client_post_no_memory(wc);
173                   break;
174                 }
175
176              device_user_data = E_NEW(E_Devicemgr_Input_Device_User_Data, 1);
177              if (!device_user_data)
178                {
179                   DMERR("Failed to allocate memory for input device user data\n");
180                   wl_client_post_no_memory(wc);
181                   wl_resource_destroy(res);
182                   break;
183                }
184              device_user_data->dev = dev;
185              device_user_data->dev_mgr_res = dev_mgr_res;
186              device_user_data->seat_res = seat_res;
187              device_user_data->dev_res = res;
188              device_user_data->mgr_data = mgr_data;
189
190              dev->resources = eina_list_append(dev->resources, res);
191              mgr_data->user_data_list = eina_list_append(mgr_data->user_data_list, device_user_data);
192
193              wl_resource_set_implementation(res, &_e_devicemgr_wl_device_interface, device_user_data,
194                                             _e_devicemgr_wl_device_cb_unbind);
195              tizen_input_device_manager_send_device_add(dev_mgr_res, serial, dev->identifier, res, seat_res);
196              tizen_input_device_send_device_info(res, dev->name, dev->clas, dev->subclas, &axes);
197           }
198      }
199 }
200
201 void
202 e_devicemgr_wl_device_del(E_Devicemgr_Input_Device *dev)
203 {
204    struct wl_client *wc;
205    Eina_List *l, *ll, *lll;
206    struct wl_resource *res, *seat_res, *dev_mgr_res;
207    uint32_t serial;
208    E_Devicemgr_Input_Device_User_Data *device_user_data;
209    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
210
211    serial = wl_display_next_serial(e_comp_wl->wl.disp);
212
213    /* TODO: find the seat corresponding to event */
214    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
215      {
216         wc = wl_resource_get_client(seat_res);
217         EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, ll, mgr_data)
218           {
219              dev_mgr_res = mgr_data->resource;
220              if (wl_resource_get_client(dev_mgr_res) != wc) continue;
221              EINA_LIST_FOREACH(dev->resources, lll, res)
222                {
223                   if (wl_resource_get_client(res) != wc) continue;
224                   device_user_data = wl_resource_get_user_data(res);
225                   if (!device_user_data) continue;
226                   if (device_user_data->dev_mgr_res != dev_mgr_res)
227                     continue;
228                   if (device_user_data->seat_res != seat_res)
229                     continue;
230
231                   device_user_data->dev = NULL;
232                   tizen_input_device_manager_send_device_remove(dev_mgr_res, serial, dev->identifier, res, seat_res);
233                }
234           }
235      }
236
237    eina_list_free(dev->resources);
238 }
239
240 void
241 e_devicemgr_wl_detent_send_event(int detent)
242 {
243    E_Devicemgr_Input_Device *input_dev;
244    struct wl_resource *dev_res;
245    struct wl_client *wc;
246    Eina_List *l, *ll;
247    wl_fixed_t f_value;
248    E_Client *ec;
249
250    ec = e_client_focused_get();
251
252    if (!ec) return;
253    if (e_object_is_del(E_OBJECT(ec))) return;
254    if (ec->ignored) return;
255    if (!ec->comp_data || !ec->comp_data->surface) return;
256
257    f_value = wl_fixed_from_double(detent * 1.0);
258    wc = wl_resource_get_client(ec->comp_data->surface);
259
260    EINA_LIST_FOREACH(e_devicemgr->device_list, l, input_dev)
261      {
262         if (!strncmp(input_dev->name, DETENT_DEVICE_NAME, sizeof(DETENT_DEVICE_NAME)))
263           {
264              EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
265                {
266                   if (wl_resource_get_client(dev_res) != wc) continue;
267                   tizen_input_device_send_axis(dev_res, TIZEN_INPUT_DEVICE_AXIS_TYPE_DETENT, f_value);
268
269                   DMINF("DETENT : %d => E_Client: %p (pid: %d) (pname: %s)",
270                          detent, ec, ec->netwm.pid, e_client_util_name_get(ec));
271                }
272           }
273      }
274 }
275
276 void
277 e_devicemgr_wl_block_send_expired(struct wl_resource *resource)
278 {
279    if (!resource) return;
280    tizen_input_device_manager_send_block_expired(resource);
281 }
282
283 void
284 e_devicemgr_wl_touch_max_count_send(int slot, struct wl_resource *res, struct wl_resource *seat_res)
285 {
286    struct wl_resource *seat_resource, *dev_mgr_resource;
287    Eina_List *l, *ll;
288    uint32_t serial;
289    struct wl_client *wc;
290    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
291
292    serial = wl_display_next_serial(e_comp_wl->wl.disp);
293
294    if (res && seat_res)
295      {
296         if (wl_resource_get_version(res) < 4) return;
297         tizen_input_device_manager_send_max_touch_count(res, serial, slot, seat_res);
298      }
299    else
300      {
301         EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_resource)
302           {
303              wc = wl_resource_get_client(seat_resource);
304
305              EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, ll, mgr_data)
306                {
307                   dev_mgr_resource = mgr_data->resource;
308                   if (wl_resource_get_client(dev_mgr_resource) != wc) continue;
309                   if (wl_resource_get_version(dev_mgr_resource) < 4) continue;
310                   tizen_input_device_manager_send_max_touch_count(dev_mgr_resource, serial, slot, seat_resource);
311                }
312           }
313      }
314 }
315
316
317 static void
318 _e_devicemgr_wl_cb_block_events(struct wl_client *client, struct wl_resource *resource, uint32_t serial, uint32_t clas, uint32_t duration)
319 {
320    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
321
322 #ifdef HAVE_CYNARA
323    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
324                                                           "http://tizen.org/privilege/internal/inputdevice.block"))
325      {
326         DMERR("block_events request:priv check failed");
327         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
328         return;
329      }
330 #endif
331
332    ret = e_devicemgr_block_add(client, resource, clas, duration);
333    tizen_input_device_manager_send_error(resource, ret);
334 }
335
336 static void
337 _e_devicemgr_wl_cb_unblock_events(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
338 {
339    int ret;
340
341 #ifdef HAVE_CYNARA
342    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
343                                                           "http://tizen.org/privilege/internal/inputdevice.block"))
344      {
345         DMERR("unblock_events request:priv check failed");
346         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
347         return;
348      }
349 #endif
350
351    ret = e_devicemgr_block_remove(client);
352    tizen_input_device_manager_send_error(resource, ret);
353 }
354
355 static void
356 _e_devicemgr_wl_cb_init_generator(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
357 {
358    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
359
360 #ifdef HAVE_CYNARA
361    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
362                                                           "http://tizen.org/privilege/inputgenerator"))
363      {
364         DMERR("init_generator request:priv check failed");
365         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
366         return;
367      }
368 #endif
369
370    ret = e_devicemgr_inputgen_add(client, resource, clas, INPUT_GENERATOR_DEVICE);
371    tizen_input_device_manager_send_error(resource, ret);
372 }
373
374 static void
375 _e_devicemgr_wl_cb_init_generator_with_name(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name)
376 {
377    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
378
379 #ifdef HAVE_CYNARA
380    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
381                                                           "http://tizen.org/privilege/inputgenerator"))
382      {
383         DMERR("init_generator_with_name request:priv check failed");
384         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
385         return;
386      }
387 #endif
388
389    ret = e_devicemgr_inputgen_add(client, resource, clas, name);
390    tizen_input_device_manager_send_error(resource, ret);
391 }
392
393 static void
394 _e_devicemgr_wl_cb_deinit_generator(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
395 {
396    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
397
398 #ifdef HAVE_CYNARA
399    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
400                                                           "http://tizen.org/privilege/inputgenerator"))
401      {
402         DMERR("deinit_generator request:priv check failed");
403         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
404         return;
405      }
406 #endif
407
408    e_devicemgr_inputgen_remove(client, resource, clas);
409    tizen_input_device_manager_send_error(resource, ret);
410 }
411
412 static void
413 _e_devicemgr_wl_cb_generate_key(struct wl_client *client, struct wl_resource *resource, const char *keyname, uint32_t pressed)
414 {
415    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
416
417 #ifdef HAVE_CYNARA
418    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
419                                                           "http://tizen.org/privilege/inputgenerator"))
420      {
421         DMERR("generate_key request:priv check failed");
422         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
423         return;
424      }
425 #endif
426
427    ret = e_devicemgr_inputgen_generate_key(client, resource, keyname, (Eina_Bool)!!pressed);
428    tizen_input_device_manager_send_error(resource, ret);
429 }
430
431 static void
432 _e_devicemgr_wl_cb_generate_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t button)
433 {
434    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
435
436 #ifdef HAVE_CYNARA
437    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
438                                                           "http://tizen.org/privilege/inputgenerator"))
439      {
440         DMERR("_generate_pointer request:priv check failed");
441         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
442         return;
443      }
444 #endif
445
446    ret = e_devicemgr_inputgen_generate_pointer(client, resource, type, x, y, button);
447    tizen_input_device_manager_send_error(resource, ret);
448 }
449
450 static void
451 _e_devicemgr_wl_cb_generate_touch(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t finger)
452 {
453    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
454
455 #ifdef HAVE_CYNARA
456    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client), "http://tizen.org/privilege/inputgenerator"))
457      {
458         DMERR("_e_input_devmgr_cb_generate_touch:priv check failed");
459         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
460         return;
461      }
462 #endif
463
464    ret = e_devicemgr_inputgen_generate_touch(client, resource, type, x, y, finger);
465    tizen_input_device_manager_send_error(resource, ret);
466 }
467
468 static void
469 _e_devicemgr_wl_cb_pointer_warp(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y)
470 {
471    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
472
473    ret = e_devicemgr_input_pointer_warp(client, resource, surface, x, y);
474
475    tizen_input_device_manager_send_error(resource, ret);
476 }
477
478 static void
479 _e_devicemgr_wl_cb_destroy(struct wl_client *client, struct wl_resource *resource)
480 {
481    wl_resource_destroy(resource);
482 }
483
484 static void
485 _e_devicemgr_wl_cb_generate_axis(struct wl_client *client, struct wl_resource *resource, uint32_t type, wl_fixed_t value)
486 {
487    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
488
489 #ifdef HAVE_CYNARA
490    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
491                                                           "http://tizen.org/privilege/inputgenerator"))
492      {
493         DMERR("_generate_pointer request:priv check failed");
494         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
495         return;
496      }
497 #endif
498
499    if (type == TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_WHEEL ||
500        type == TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_HWHEEL)
501      ret = e_devicemgr_inputgen_generate_wheel(client, resource, type, (int)wl_fixed_to_double(value));
502    else
503      ret = e_devicemgr_inputgen_touch_axis_store(client, resource, type, wl_fixed_to_double(value));
504    tizen_input_device_manager_send_error(resource, ret);
505 }
506
507 static void
508 _e_devicemgr_wl_cb_set_touch_count(struct wl_client *client, struct wl_resource *resource, int32_t max_count)
509 {
510    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
511
512 #ifdef HAVE_CYNARA
513    if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
514                                                           "http://tizen.org/privilege/inputgenerator"))
515      {
516         DMERR("_generate_pointer request:priv check failed");
517         tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
518         return;
519      }
520 #endif
521
522    if (e_config->configured_max_touch.use)
523      {
524         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
525      }
526    else
527      {
528         if (max_count > e_input_touch_max_count_get())
529           {
530              e_input_touch_max_count_set(max_count);
531           }
532      }
533
534    tizen_input_device_manager_send_error(resource, ret);
535 }
536
537
538 static const struct tizen_input_device_manager_interface _e_devicemgr_wl_implementation = {
539    _e_devicemgr_wl_cb_block_events,
540    _e_devicemgr_wl_cb_unblock_events,
541    _e_devicemgr_wl_cb_init_generator,
542    _e_devicemgr_wl_cb_deinit_generator,
543    _e_devicemgr_wl_cb_generate_key,
544    _e_devicemgr_wl_cb_generate_pointer,
545    _e_devicemgr_wl_cb_generate_touch,
546    _e_devicemgr_wl_cb_pointer_warp,
547    _e_devicemgr_wl_cb_init_generator_with_name,
548    _e_devicemgr_wl_cb_destroy,
549    _e_devicemgr_wl_cb_generate_axis,
550    _e_devicemgr_wl_cb_set_touch_count,
551 };
552
553 static void
554 _e_devicemgr_wl_cb_unbind(struct wl_resource *resource)
555 {
556    E_Devicemgr_Input_Device_Mgr_Data *mgr_data;
557    E_Devicemgr_Input_Device_User_Data *device_user_data;
558
559    if(!e_comp_wl) return;
560
561    mgr_data = wl_resource_get_user_data(resource);
562    if (!mgr_data) return;
563
564    DMDBG("Unbind tizen_input_device_manager: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
565
566    EINA_LIST_FREE(mgr_data->user_data_list, device_user_data)
567      {
568         DMDBG("Destroy dev_res:%u", wl_resource_get_id(device_user_data->dev_res));
569         device_user_data->mgr_data = NULL;
570         wl_resource_destroy(device_user_data->dev_res);
571      }
572    e_devicemgr->wl_data->mgr_data_list = eina_list_remove(e_devicemgr->wl_data->mgr_data_list, mgr_data);
573
574    E_FREE(mgr_data);
575 }
576
577 static void
578 _e_devicemgr_wl_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
579 {
580    struct wl_resource *res, *seat_res, *device_res;
581    Eina_List *l;
582    uint32_t serial;
583    E_Devicemgr_Input_Device *dev;
584    struct wl_array axes;
585    E_Devicemgr_Input_Device_User_Data *device_user_data;
586    E_Devicemgr_Input_Device_Mgr_Data *mgr_data, *tmp_data;
587
588    mgr_data = E_NEW(E_Devicemgr_Input_Device_Mgr_Data, 1);
589    if (!mgr_data)
590      {
591         DMERR("Failed to allocate memory for input device mgr data\n");
592         wl_client_post_no_memory(client);
593         return;
594      }
595    mgr_data->is_first_resource = 1;
596
597    EINA_LIST_FOREACH(e_devicemgr->wl_data->mgr_data_list, l, tmp_data)
598      {
599         if (wl_resource_get_client(tmp_data->resource) != client) continue;
600         DMDBG("tizen_input_device_manager (res: %d) is already bound to client (%p)",
601               wl_resource_get_id(tmp_data->resource), client);
602         mgr_data->is_first_resource = 0;
603      }
604
605    if (!(res = wl_resource_create(client, &tizen_input_device_manager_interface, version, id)))
606      {
607         DMERR("Could not create tizen_input_device_manager_interface resource: %m");
608         wl_client_post_no_memory(client);
609         E_FREE(mgr_data);
610         return;
611      }
612
613    DMDBG("Bind tizen_input_device_manager: %u (client: %p)", wl_resource_get_id(res), wl_resource_get_client(res));
614
615    mgr_data->resource = res;
616    mgr_data->user_data_list = NULL;
617    e_devicemgr->wl_data->mgr_data_list = eina_list_append(e_devicemgr->wl_data->mgr_data_list, mgr_data);
618
619    wl_resource_set_implementation(res, &_e_devicemgr_wl_implementation, mgr_data,
620                                   _e_devicemgr_wl_cb_unbind);
621
622    if (!mgr_data->is_first_resource)
623    {
624       DMDBG("This device_manager (res:%d) is not the first resource bound to client (%p)",
625             wl_resource_get_id(res), client);
626       return;
627    }
628
629    EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, seat_res)
630      {
631         if (wl_resource_get_client(seat_res) != client) continue;
632
633         wl_array_init(&axes);
634         serial = wl_display_next_serial(e_comp_wl->wl.disp);
635
636         if (e_devicemgr->max_touch_count > 0)
637           {
638              e_devicemgr_wl_touch_max_count_send(e_devicemgr->max_touch_count, res, seat_res);
639           }
640
641         EINA_LIST_FOREACH(e_devicemgr->device_list, l, dev)
642           {
643              device_res = wl_resource_create(client, &tizen_input_device_interface, 1, 0);
644              if (!device_res)
645                {
646                   DMERR("Could not create tizen_input_device resource: %m");
647                   wl_client_post_no_memory(client);
648                   return;
649                }
650              device_user_data = E_NEW(E_Devicemgr_Input_Device_User_Data, 1);
651              if (!device_user_data)
652                {
653                   DMERR("Failed to allocate memory for input device user data\n");
654                   wl_client_post_no_memory(client);
655                   wl_resource_destroy(device_res);
656                   return;
657                }
658              device_user_data->dev = dev;
659              device_user_data->dev_mgr_res = res;
660              device_user_data->seat_res = seat_res;
661              device_user_data->dev_res = device_res;
662              device_user_data->mgr_data = mgr_data;
663
664              dev->resources = eina_list_append(dev->resources, device_res);
665              mgr_data->user_data_list = eina_list_append(mgr_data->user_data_list, device_user_data);
666
667              wl_resource_set_implementation(device_res, &_e_devicemgr_wl_device_interface, device_user_data,
668                                             _e_devicemgr_wl_device_cb_unbind);
669
670              tizen_input_device_manager_send_device_add(res, serial, dev->identifier, device_res, seat_res);
671              tizen_input_device_send_device_info(device_res, dev->name, dev->clas, dev->subclas, &axes);
672           }
673      }
674 }
675
676 Eina_Bool
677 e_devicemgr_wl_init(void)
678 {
679    if (!e_comp_wl) return EINA_FALSE;
680    if (!e_comp_wl->wl.disp) return EINA_FALSE;
681
682    if (e_devicemgr->wl_data) return EINA_TRUE;
683
684    e_devicemgr->wl_data = E_NEW(E_Devicemgr_Wl_Data, 1);
685    EINA_SAFETY_ON_NULL_RETURN_VAL(e_devicemgr->wl_data, EINA_FALSE);
686
687    /* try to add tizen_input_device_manager to wayland globals */
688    e_devicemgr->wl_data->global = wl_global_create(e_comp_wl->wl.disp,
689                                                    &tizen_input_device_manager_interface, 4,
690                                                    NULL, _e_devicemgr_wl_cb_bind);
691    if (!e_devicemgr->wl_data->global)
692      {
693         DMERR("Could not add tizen_input_device_manager to wayland globals");
694         return EINA_FALSE;
695      }
696    e_devicemgr->wl_data->mgr_data_list = NULL;
697
698    /* initialization of cynara for checking privilege */
699 #ifdef HAVE_CYNARA
700    int ret;
701
702    ret = cynara_initialize(&e_devicemgr->wl_data->p_cynara, NULL);
703    if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
704      {
705         _e_devicemgr_util_cynara_log("cynara_initialize", ret);
706         e_devicemgr->wl_data->p_cynara = NULL;
707      }
708    e_devicemgr->wl_data->cynara_initialized = EINA_TRUE;
709 #endif
710
711    return EINA_TRUE;
712 }
713
714 void
715 e_devicemgr_wl_shutdown(void)
716 {
717    if (!e_devicemgr->wl_data) return;
718    /* destroy the global seat resource */
719    if (e_devicemgr->wl_data->global)
720      wl_global_destroy(e_devicemgr->wl_data->global);
721    e_devicemgr->wl_data->global = NULL;
722    eina_list_free(e_devicemgr->wl_data->mgr_data_list);
723
724    /* deinitialization of cynara if it has been initialized */
725 #ifdef HAVE_CYNARA
726    if (e_devicemgr->wl_data->p_cynara) cynara_finish(e_devicemgr->wl_data->p_cynara);
727    e_devicemgr->wl_data->cynara_initialized = EINA_FALSE;
728 #endif
729
730    E_FREE(e_devicemgr->wl_data);
731 }
732