rearrange the directories of git repository
[platform/core/uifw/libds-tizen.git] / src / input-devicemgr / input-devicemgr.c
1 #include <stdlib.h>
2 #include <time.h> // gettimeofday()
3 #include <libds/backend.h>
4 #include <libds/log.h>
5 #include <libds-tizen/input-devicemgr.h>
6 #include <libds/interfaces/backend.h>
7 #include <libds/interfaces/keyboard.h>
8 #include <libds/seat.h>
9
10 #include "util.h"
11 #include "input-devicemgr.h"
12 #include "src/libds/seat.h"
13
14 #define TIZEN_INPUT_DEVICEMGR_VERSION 4
15 #define TIZEN_PRIV_INPUT_GENERATOR "http://tizen.org/privilege/inputgenerator"
16 #define TIZEN_PRIV_INPUT_BLOCK "http://tizen.org/privilege/internal/inputdevice.block"
17
18 static const struct ds_keyboard_grab_interface devicemgr_keyboard_grab_iface;
19
20 //listeners
21 static void
22 backend_handle_destroy(struct wl_listener *listener, void *data);
23 static void
24 backend_handle_input_device_add(struct wl_listener *listener, void *data);
25 static void
26 seat_handle_destroy(struct wl_listener *listener, void *data);
27
28 //tizen_input_device_manager bind/unbind
29 static void
30 device_manager_handle_bind(struct wl_client *client, void *data,
31         uint32_t version, uint32_t id);
32 static void
33 device_manager_client_handle_resource_destroy(struct wl_resource *resource);
34
35 //tizen_input_device_manager's handlers for requests
36 static void
37 device_manager_handle_block_events(struct wl_client *client,
38         struct wl_resource *resource, uint32_t serial,
39         uint32_t clas, uint32_t duration);
40 static void
41 device_manager_handle_unblock_events(struct wl_client *client,
42         struct wl_resource *resource, uint32_t serial);
43 static void
44 device_manager_handle_init_generator(struct wl_client *client,
45         struct wl_resource *resource, uint32_t clas);
46 static void
47 device_manager_handle_init_generator_with_name(struct wl_client *client,
48         struct wl_resource *resource, uint32_t clas, const char *name);
49 static void
50 device_manager_handle_deinit_generator(struct wl_client *client,
51         struct wl_resource *resource, uint32_t clas);
52 static void
53 device_manager_handle_generate_key(struct wl_client *client,
54         struct wl_resource *resource,
55         const char *keyname, uint32_t pressed);
56 static void
57 device_manager_handle_destroy(struct wl_client *client,
58         struct wl_resource *resource);
59
60 //
61 static void tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr);
62 static int
63 tz_devicemgr_init_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
64         struct wl_resource *resource, const char *name);
65 static int
66 tz_devicemgr_deinit_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
67         struct wl_resource *resource);
68 static bool
69 tz_devicemgr_generate_key(struct ds_input_device *device, int keycode,
70         int pressed);
71 static bool
72 tz_devicemgr_pressed_keys_update(struct ds_tizen_input_devicemgr *tz_devicemgr,
73         int keycode, bool pressed);
74 static void
75 tz_devicemgr_pressed_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr);
76 static void
77 tz_devicemgr_keymap_list_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr);
78 static int
79 tz_devicemgr_keyname_to_keycode(struct wl_list *list, const char *name);
80
81 static bool
82 tz_devicemgr_check_privilege(struct ds_tizen_input_devicemgr *tz_devicemgr,
83         struct wl_client *client, const char *rule);
84
85 static void
86 tz_devicemgr_grab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr);
87 static void
88 tz_devicemgr_ungrab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr);
89 static void
90 tz_devicemgr_ungrab_keyboard_check(struct ds_tizen_input_devicemgr *tz_devicemgr);
91 static void
92 tz_devicemgr_blocked_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr);
93
94 WL_EXPORT struct ds_tizen_input_devicemgr *
95 ds_tizen_input_devicemgr_create(struct ds_backend *backend,
96         struct ds_seat *seat)
97 {
98     struct ds_tizen_input_devicemgr *tz_devicemgr;
99
100     tz_devicemgr = calloc(1, sizeof *tz_devicemgr);
101     if (!tz_devicemgr) {
102         ds_err("Fail to allocate ds_tizen_input_devicemgr");
103         return NULL;
104     }
105
106     tz_devicemgr->backend = backend;
107     tz_devicemgr->backend_destroy.notify = backend_handle_destroy;
108     ds_backend_add_destroy_listener(backend, &tz_devicemgr->backend_destroy);
109
110     tz_devicemgr->seat = seat;
111     tz_devicemgr->seat_destroy.notify = seat_handle_destroy;
112     ds_seat_add_destroy_listener(seat, &tz_devicemgr->seat_destroy);
113
114     tz_devicemgr->new_input.notify = backend_handle_input_device_add;
115     ds_backend_add_new_input_listener(backend, &tz_devicemgr->new_input);
116
117     tz_devicemgr->global = wl_global_create(backend->display,
118             &tizen_input_device_manager_interface,
119             TIZEN_INPUT_DEVICEMGR_VERSION,
120             tz_devicemgr, device_manager_handle_bind);
121     if (!tz_devicemgr->global) {
122         goto err_global;
123     }
124
125     tz_devicemgr->devices.kbd = calloc(1,
126             sizeof(struct ds_tizen_input_devicemgr_device));
127     if (!tz_devicemgr->devices.kbd) {
128         goto err_kbd;
129     }
130
131     tz_devicemgr->grab = calloc(1, sizeof(struct ds_seat_keyboard_grab));
132     if (!tz_devicemgr->grab)
133     {
134         goto err_grab;
135     }
136
137     tz_devicemgr->grab->iface = &devicemgr_keyboard_grab_iface;
138     tz_devicemgr->grab->seat = tz_devicemgr->seat;
139     tz_devicemgr->grab->data = tz_devicemgr;
140
141     wl_signal_init(&tz_devicemgr->events.destroy);
142     wl_list_init(&tz_devicemgr->clients);
143     wl_list_init(&tz_devicemgr->pressed_keys);
144     wl_list_init(&tz_devicemgr->keymap_list);
145     wl_list_init(&tz_devicemgr->blocked_keys);
146
147     if (!tizen_security_init()) {
148         ds_inf("tizen_security_init() is failed. go on without security");
149     }
150
151     ds_inf("Global created: ds_tizen_input_devicemgr(%p) ", tz_devicemgr);
152     return tz_devicemgr;
153 err_grab:
154     free(tz_devicemgr->devices.kbd);
155 err_kbd:
156     wl_global_destroy(tz_devicemgr->global);
157 err_global:
158     wl_list_remove(&tz_devicemgr->backend_destroy.link);
159     wl_list_remove(&tz_devicemgr->seat_destroy.link);
160     wl_list_remove(&tz_devicemgr->new_input.link);
161     free(tz_devicemgr);
162     return NULL;
163 }
164
165 WL_EXPORT void
166 ds_tizen_input_devicemgr_add_destroy_listener(
167         struct ds_tizen_input_devicemgr *tz_devicemgr,
168         struct wl_listener *listener)
169 {
170     wl_signal_add(&tz_devicemgr->events.destroy, listener);
171 }
172
173 WL_EXPORT bool
174 ds_tizen_input_devicemgr_set_keymap_list(
175         struct ds_tizen_input_devicemgr *tz_devicemgr, struct wl_list *list)
176 {
177     struct ds_tizen_input_devicemgr_keymap_data *data, *new_data;
178
179     if (!tz_devicemgr || !list) {
180         ds_err("Please insert correct data\n");
181         return false;
182     }
183
184     wl_list_for_each(data, list, link) {
185         new_data = calloc(1, sizeof *data);
186         if (!new_data) {
187             ds_err("Failed to alloc memory");
188             return false;
189         }
190         new_data->name = strdup(data->name);
191         new_data->keycode = data->keycode;
192         wl_list_insert(&tz_devicemgr->keymap_list, &new_data->link);
193     }
194     ds_inf("keymap set. length:%d",
195             wl_list_length(&tz_devicemgr->keymap_list));
196
197     return true;
198 }
199
200 static void
201 tz_devicemgr_destroy(struct ds_tizen_input_devicemgr *tz_devicemgr)
202 {
203     struct ds_tizen_input_devicemgr_client *client_data, *tmp;
204
205     tizen_security_finish();
206
207     tz_devicemgr_keymap_list_cleanup(tz_devicemgr);
208     tz_devicemgr_blocked_keys_cleanup(tz_devicemgr);
209     tz_devicemgr_ungrab_keyboard(tz_devicemgr);
210
211     wl_signal_emit(&tz_devicemgr->events.destroy, tz_devicemgr);
212     wl_list_remove(&tz_devicemgr->backend_destroy.link);
213     wl_list_remove(&tz_devicemgr->seat_destroy.link);
214     wl_list_remove(&tz_devicemgr->new_input.link);
215
216     wl_global_destroy(tz_devicemgr->global);
217
218     wl_list_for_each_safe(client_data, tmp, &tz_devicemgr->clients, link) {
219         wl_list_remove(&client_data->link);
220         tz_devicemgr_deinit_generator(tz_devicemgr, client_data->resource);
221
222         wl_resource_set_user_data(client_data->resource, NULL);
223         free(client_data);
224     }
225
226     free(tz_devicemgr->devices.kbd);
227     free(tz_devicemgr->grab);
228     free(tz_devicemgr);
229 }
230
231 static void
232 backend_handle_destroy(struct wl_listener *listener, void *data)
233 {
234     struct ds_tizen_input_devicemgr *tz_devicemgr;
235
236     tz_devicemgr = wl_container_of(listener, tz_devicemgr, backend_destroy);
237
238     ds_inf("Global destroy: ds_tizen_input_devicemgr(%p)", tz_devicemgr);
239
240     tz_devicemgr_destroy(tz_devicemgr);
241 }
242
243 static void
244 seat_handle_destroy(struct wl_listener *listener, void *data)
245 {
246     struct ds_tizen_input_devicemgr *tz_devicemgr;
247
248     tz_devicemgr = wl_container_of(listener, tz_devicemgr, backend_destroy);
249
250     wl_list_remove(&tz_devicemgr->seat_destroy.link);
251     wl_list_init(&tz_devicemgr->seat_destroy.link);
252     tz_devicemgr->seat = NULL;
253 }
254
255 static void
256 backend_handle_input_device_add(struct wl_listener *listener, void *data)
257 {
258     struct ds_input_device *dev = data;
259     struct ds_tizen_input_devicemgr *tz_devicemgr;
260     enum ds_input_device_type dev_type;
261
262     tz_devicemgr = wl_container_of(listener, tz_devicemgr, new_input);
263
264     dev_type = ds_input_device_get_type(dev);
265     if (dev_type == DS_INPUT_DEVICE_KEYBOARD) {
266         if (tz_devicemgr->devices.kbd->input_device) return;
267         ds_inf("devicemgr's kbd device is set");
268         tz_devicemgr->devices.kbd->input_device = dev;
269     }
270     else if (dev_type == DS_INPUT_DEVICE_POINTER) {
271         //TODO: assign input_device 'dev' to devices.ptr
272     }
273     else if (dev_type == DS_INPUT_DEVICE_TOUCH) {
274         //TODO: assign input_device 'dev' to devices.ptr
275     }
276 }
277
278 static const struct tizen_input_device_manager_interface _devicemgr_impl = {
279     .block_events = device_manager_handle_block_events,
280     .unblock_events = device_manager_handle_unblock_events,
281     .init_generator = device_manager_handle_init_generator,
282     .deinit_generator = device_manager_handle_deinit_generator,
283     .generate_key = device_manager_handle_generate_key,
284     .generate_pointer = NULL,
285     .generate_touch = NULL,
286     .pointer_warp = NULL,
287     .init_generator_with_name =
288             device_manager_handle_init_generator_with_name, // v2
289     .destroy = device_manager_handle_destroy, // v3
290     .generate_axis = NULL, // v3
291     .set_touch_count = NULL, // v4
292 };
293
294 static void
295 device_manager_client_handle_resource_destroy(struct wl_resource *resource)
296 {
297     struct ds_tizen_input_devicemgr *tz_devicemgr;
298     struct ds_tizen_input_devicemgr_client *client_data, *tmp;
299
300     tz_devicemgr = wl_resource_get_user_data(resource);
301
302     tz_devicemgr_deinit_generator(tz_devicemgr, resource);
303
304     if (resource == tz_devicemgr->block_resource) {
305         tz_devicemgr_ungrab_keyboard_check(tz_devicemgr);
306         if (tz_devicemgr->timer) {
307             wl_event_source_remove(tz_devicemgr->timer);
308             tz_devicemgr->timer = NULL;
309         }
310     }
311
312     wl_list_for_each_safe(client_data, tmp, &tz_devicemgr->clients, link) {
313         if (client_data->resource == resource) {
314             wl_list_remove(&client_data->link);
315             free(client_data);
316         }
317     }
318 }
319
320 static void
321 device_manager_handle_bind(struct wl_client *client, void *data,
322         uint32_t version, uint32_t id)
323 {
324     struct ds_tizen_input_devicemgr *tz_devicemgr = data;
325     struct ds_tizen_input_devicemgr_client *client_data;
326
327     client_data = calloc(1, sizeof *client_data);
328     if (!client_data) {
329         ds_err("Failed to allocate memory !\n");
330         wl_client_post_no_memory(client);
331         return;
332     }
333
334     client_data->resource = wl_resource_create(client,
335             &tizen_input_device_manager_interface, MIN(version,4), id);
336     if (!client_data->resource) {
337         ds_err("Failed to create resource! (ver. :%d, id:%d)", version, id);
338         free(client_data);
339         wl_client_post_no_memory(client);
340         return;
341     }
342
343     client_data->init = false;
344     wl_list_init(&client_data->link);
345     wl_list_insert(&tz_devicemgr->clients, &client_data->link);
346
347     wl_resource_set_implementation(client_data->resource, &_devicemgr_impl,
348             tz_devicemgr, device_manager_client_handle_resource_destroy);
349 }
350
351 static void
352 device_manager_handle_init_generator(struct wl_client *client,
353         struct wl_resource *resource, uint32_t clas)
354 {
355     struct ds_tizen_input_devicemgr *tz_devicemgr;
356     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
357
358     tz_devicemgr = wl_resource_get_user_data(resource);
359
360     if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
361             TIZEN_PRIV_INPUT_GENERATOR)) {
362         ds_err("No permission to input generate");
363         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
364         goto finish;
365     }
366
367     if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) {
368         ds_err("only support keyboard device. (requested: 0x%x)\n", clas);
369         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
370         goto finish;
371     }
372
373     ret = tz_devicemgr_init_generator(tz_devicemgr, resource,
374             "Input Generator");
375     if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
376         ds_err("Failed to init input generator\n");
377         goto finish;
378     }
379
380 finish:
381     tizen_input_device_manager_send_error(resource, ret);
382 }
383
384 static void
385 device_manager_handle_init_generator_with_name(struct wl_client *client,
386         struct wl_resource *resource, uint32_t clas, const char *name)
387 {
388     struct ds_tizen_input_devicemgr *tz_devicemgr;
389     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
390
391     tz_devicemgr = wl_resource_get_user_data(resource);
392
393     if (!name) {
394         ds_err("no name for device");
395         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
396         goto finish;
397     }
398
399     if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
400             TIZEN_PRIV_INPUT_GENERATOR)) {
401         ds_err("No permission to input generate");
402         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
403         goto finish;
404     }
405
406     if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) {
407         ds_err("only support keyboard device. (requested: 0x%x)\n", clas);
408         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
409         goto finish;
410     }
411
412     ret = tz_devicemgr_init_generator(tz_devicemgr, resource,
413             name);
414     if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
415         ds_err("Failed to init input generator\n");
416         goto finish;
417     }
418
419 finish:
420     tizen_input_device_manager_send_error(resource, ret);
421 }
422
423 static void
424 device_manager_handle_deinit_generator(struct wl_client *client,
425         struct wl_resource *resource, uint32_t clas)
426 {
427     struct ds_tizen_input_devicemgr *tz_devicemgr;
428     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
429
430     tz_devicemgr = wl_resource_get_user_data(resource);
431
432     if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
433             TIZEN_PRIV_INPUT_GENERATOR)) {
434         ds_err("No permission to input generate");
435         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
436         goto finish;
437     }
438
439     if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) {
440         ds_err("only support keyboard device. (requested: 0x%x)\n", clas);
441         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
442         goto finish;
443     }
444
445     ret = tz_devicemgr_deinit_generator(tz_devicemgr, resource);
446     if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
447         ds_err("Failed to deinit input generator\n");
448         goto finish;
449     }
450
451 finish:
452     tizen_input_device_manager_send_error(resource, ret);
453 }
454
455 struct keycode_map{
456     xkb_keysym_t keysym;
457     xkb_keycode_t keycode;
458 };
459
460 static void
461 find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
462 {
463     struct keycode_map *found_keycodes = (struct keycode_map *)data;
464     xkb_keysym_t keysym = found_keycodes->keysym;
465     int nsyms = 0;
466     const xkb_keysym_t *syms_out = NULL;
467
468     if (found_keycodes->keycode) return;
469
470     nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
471     if (nsyms && syms_out) {
472         if (*syms_out == keysym) {
473             found_keycodes->keycode = key;
474         }
475     }
476 }
477
478 static void
479 tz_devicemgr_xkb_keycode_from_keysym(struct xkb_keymap *keymap,
480         xkb_keysym_t keysym, xkb_keycode_t *keycode)
481 {
482     struct keycode_map found_keycodes = {0,};
483     found_keycodes.keysym = keysym;
484     xkb_keymap_key_for_each(keymap, find_keycode, &found_keycodes);
485
486     *keycode = found_keycodes.keycode;
487 }
488
489 static int
490 tz_devicemgr_xkb_keyname_to_keycode(struct xkb_keymap *keymap,
491         const char *name)
492 {
493     xkb_keysym_t keysym = 0x0;
494     xkb_keycode_t keycode = 0;
495
496     if (!strncmp(name, "Keycode-", sizeof("Keycode-")-1)) {
497         keycode = atoi(name + 8);
498     } else {
499         keysym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
500         tz_devicemgr_xkb_keycode_from_keysym(keymap, keysym, &keycode);
501     }
502
503     return keycode;
504 }
505
506 static void
507 device_manager_handle_generate_key(struct wl_client *client,
508         struct wl_resource *resource, const char *keyname, uint32_t pressed)
509 {
510     struct ds_tizen_input_devicemgr *tz_devicemgr;
511     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
512     int keycode = 0;
513     bool res;
514     struct ds_keyboard *kbd;
515
516     tz_devicemgr = wl_resource_get_user_data(resource);
517
518     if (!tz_devicemgr->devices.kbd ||
519         !tz_devicemgr->devices.kbd->input_device) {
520         ds_err("Keyboard device is not initialized\n");
521         goto finish;
522     }
523
524     if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
525             TIZEN_PRIV_INPUT_GENERATOR)) {
526         ds_err("No permission to input generate");
527         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
528         goto finish;
529     }
530
531     // keyname to keycode using xkb_info
532     kbd = ds_input_device_get_keyboard(
533             tz_devicemgr->devices.kbd->input_device);
534     if (kbd->keymap) {
535         keycode = tz_devicemgr_xkb_keyname_to_keycode(kbd->keymap, keyname);
536     }
537
538     if (keycode <= 0) {
539         keycode = tz_devicemgr_keyname_to_keycode(&tz_devicemgr->keymap_list,
540                 keyname);
541     }
542     if (keycode <= 0)
543         goto finish;
544
545     res = tz_devicemgr_generate_key(tz_devicemgr->devices.kbd->input_device,
546             keycode, pressed);
547     if (!res) {
548         ds_err("Generating key is failed. key: %s, pressed: %d",
549                 keyname, pressed);
550         goto finish;
551     }
552     res = tz_devicemgr_pressed_keys_update(tz_devicemgr, keycode, pressed);
553     if (!res) {
554         ds_err("Updating pressed keys is failed. key: %s, pressed: %d",
555                 keyname, pressed);
556         goto finish;
557     }
558     ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
559
560 finish:
561     tizen_input_device_manager_send_error(resource, ret);
562 }
563
564 static void
565 device_manager_handle_destroy(struct wl_client *client,
566         struct wl_resource *resource)
567 {
568         wl_resource_destroy(resource);
569 }
570
571 static bool
572 tz_devicemgr_check_privilege(struct ds_tizen_input_devicemgr *tz_devicemgr,
573         struct wl_client *client, const char *rule)
574 {
575     pid_t pid = 0;
576     uid_t uid = 0;
577     gid_t gid = 0;
578
579     if (!client) return false;
580
581     wl_client_get_credentials(client, &pid, &uid, &gid);
582
583     return tizen_security_check_privilege(pid, uid, rule);
584 }
585
586 static const struct ds_input_device_interface input_device_iface =
587 {
588     .destroy = NULL,
589 };
590
591 static struct ds_keyboard *
592 create_ds_keyboard()
593 {
594     struct ds_keyboard *kbd;
595     kbd = calloc(1, sizeof *kbd);
596     if (!kbd) {
597         ds_err("Could not allocate memory");
598         return NULL;
599     }
600     ds_keyboard_init(kbd, NULL);
601
602     return kbd;
603 }
604
605 static int
606 tz_devicemgr_init_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
607         struct wl_resource *resource, const char *name)
608 {
609     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
610     struct ds_tizen_input_devicemgr_client *client_data;
611     struct ds_tizen_input_devicemgr_device *kbd;
612
613     ds_inf("Init generator. name:%s", name);
614
615     kbd = tz_devicemgr->devices.kbd;
616     if (strlen(kbd->name) > 0) {
617         ds_inf("devices.kbd already has name. name:%s", kbd->name);
618         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
619     }
620
621     if (kbd->input_device) {
622         ds_inf("devices.kbd is already set. name:%s",
623                 ds_input_device_get_name(kbd->input_device));
624         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
625     }
626
627     //input_device create
628     kbd->input_device = calloc(1, sizeof(struct ds_input_device));
629     if(!kbd->input_device) {
630         ds_err("Failed to create input device !\n");
631         return ret;
632     }
633
634     ds_input_device_init(kbd->input_device, DS_INPUT_DEVICE_KEYBOARD,
635             &input_device_iface, name, -1, -1);
636     kbd->input_device->keyboard = create_ds_keyboard();
637
638     wl_signal_emit(&tz_devicemgr->backend->events.new_input,
639             kbd->input_device);
640
641     kbd->created = true;
642     strncpy(kbd->name, name, UINPUT_MAX_NAME_SIZE);
643
644     wl_list_for_each(client_data, &tz_devicemgr->clients, link) {
645         if (client_data->resource == resource) {
646             if (client_data->init == false) {
647                 client_data->init = true;
648                 tz_devicemgr->ref++;
649             }
650             break;
651         }
652     }
653
654     ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
655
656     return ret;
657 }
658
659 static int
660 tz_devicemgr_keyname_to_keycode(struct wl_list *list, const char *name)
661 {
662     struct ds_tizen_input_devicemgr_keymap_data *data;
663
664     if (!wl_list_empty(list)) {
665         wl_list_for_each(data, list, link) {
666             if (!strcmp(data->name, name)) {
667                 return data->keycode;
668             }
669         }
670     }
671
672     return 0;
673 }
674
675 static bool
676 tz_devicemgr_generate_key(struct ds_input_device *device, int keycode,
677         int pressed)
678 {
679     struct ds_event_keyboard_key ds_event;
680     struct timeval time;
681     unsigned int timestamp;
682     struct ds_keyboard *kbd;
683
684     kbd = ds_input_device_get_keyboard(device);
685     if (!kbd) {
686         ds_err("No ds_keyboard to notify event");
687         return false;
688     }
689
690     gettimeofday(&time, NULL);
691     timestamp = time.tv_sec * 1000 + time.tv_usec / 1000;
692
693     ds_event.time_msec = timestamp;
694     ds_event.keycode = keycode - 8;
695     if (pressed)
696         ds_event.state = WL_KEYBOARD_KEY_STATE_PRESSED;
697     else
698         ds_event.state = WL_KEYBOARD_KEY_STATE_RELEASED;
699
700     ds_inf("Generate key. kbd:%p, key:%d, state:%s", kbd, ds_event.keycode,
701             (ds_event.state == WL_KEYBOARD_KEY_STATE_PRESSED) ?
702             "PRESSED" : "RELEASED");
703
704     ds_keyboard_notify_key(kbd, &ds_event);
705
706     return true;
707 }
708
709 static bool
710 tz_devicemgr_pressed_keys_update(struct ds_tizen_input_devicemgr *tz_devicemgr,
711         int keycode, bool pressed)
712 {
713     struct ds_tizen_input_devicemgr_key_info *key, *tmp;
714
715     if (pressed) {
716         key = calloc(1, sizeof(*key));
717         if (!key) {
718             ds_err("Failed to alloc keydata memory.\n");
719             return false;
720         }
721         key->keycode = keycode;
722         wl_list_init(&key->link);
723         wl_list_insert(&tz_devicemgr->pressed_keys, &key->link);
724     }
725     else {
726         wl_list_for_each_safe(key, tmp, &tz_devicemgr->pressed_keys, link) {
727             if (key->keycode == keycode) {
728                 wl_list_remove(&key->link);
729                 free(key);
730                 break;
731             }
732         }
733     }
734
735     ds_inf("Update pressed keys. length: %d, keycode:%d, pressed:%d",
736             wl_list_length(&tz_devicemgr->pressed_keys), keycode, pressed);
737
738     return true;
739 }
740
741 static void
742 tz_devicemgr_pressed_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr)
743 {
744     struct ds_tizen_input_devicemgr_key_info *keydata, *tmp;
745
746     ds_inf("Clean up the pressed_keys. length: %d",
747             wl_list_length(&tz_devicemgr->pressed_keys));
748
749     wl_list_for_each_safe(keydata, tmp, &tz_devicemgr->pressed_keys, link) {
750         if (tz_devicemgr->devices.kbd)
751             tz_devicemgr_generate_key(tz_devicemgr->devices.kbd->input_device,
752                     keydata->keycode, false);
753         wl_list_remove(&keydata->link);
754         free(keydata);
755     }
756 }
757
758 static void
759 tz_devicemgr_keymap_list_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr)
760 {
761     struct ds_tizen_input_devicemgr_keymap_data *keymap, *tmp;
762
763     ds_inf("Clean up the keymap_list. length: %d",
764             wl_list_length(&tz_devicemgr->keymap_list));
765
766     wl_list_for_each_safe(keymap, tmp, &tz_devicemgr->keymap_list, link) {
767         free(keymap->name);
768         wl_list_remove(&keymap->link);
769         free(keymap);
770     }
771 }
772
773 static void
774 tz_devicemgr_keyboard_close(struct ds_tizen_input_devicemgr *tz_devicemgr)
775 {
776     if (!tz_devicemgr->devices.kbd->input_device) return;
777     ds_input_device_destroy(tz_devicemgr->devices.kbd->input_device);
778     tz_devicemgr->devices.kbd->input_device = NULL;
779     tz_devicemgr->devices.kbd->created = false;
780 }
781
782 static int
783 tz_devicemgr_deinit_generator(struct ds_tizen_input_devicemgr *tz_devicemgr,
784         struct wl_resource *resource)
785 {
786     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
787     struct ds_tizen_input_devicemgr_client *client_data;
788
789     ds_inf("Deinit generator.");
790     wl_list_for_each(client_data, &tz_devicemgr->clients, link) {
791         if (client_data->resource == resource) {
792             if (client_data->init == true) {
793                 client_data->init = false;
794                 tz_devicemgr->ref--;
795                 if (tz_devicemgr->ref < 0) tz_devicemgr->ref = 0;
796                 break;
797             } else {
798                 return ret;
799             }
800         }
801     }
802
803     if (tz_devicemgr->ref <= 0) {
804         tz_devicemgr_pressed_keys_cleanup(tz_devicemgr);
805
806         if (!tz_devicemgr->devices.kbd)
807             return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
808
809         if (tz_devicemgr->devices.kbd->created)
810             tz_devicemgr_keyboard_close(tz_devicemgr);
811         memset(tz_devicemgr->devices.kbd->name, 0, UINPUT_MAX_NAME_SIZE);
812     }
813
814     return ret;
815 }
816
817 static void
818 devicemgr_keyboard_grab_iface_enter(struct ds_seat_keyboard_grab *grab,
819             struct ds_surface *surface, uint32_t keycodes[],
820             size_t num_keycodes, struct ds_keyboard_modifiers *modifiers)
821 {
822     ds_inf("devicemgr. keyboard_grab_iface_enter");
823 }
824
825 static void
826 devicemgr_keyboard_grab_iface_clear_focus(struct ds_seat_keyboard_grab *grab)
827 {
828     ds_inf("devicemgr. keyboard_grab_iface_clear_focus");
829 }
830
831 static void
832 tz_devicemgr_blocked_keys_cleanup(struct ds_tizen_input_devicemgr *tz_devicemgr)
833 {
834     struct ds_tizen_input_devicemgr_key_info *keydata, *tmp;
835
836     ds_inf("Clean up the blocked keys. length: %d",
837             wl_list_length(&tz_devicemgr->blocked_keys));
838
839     wl_list_for_each_safe(keydata, tmp, &tz_devicemgr->blocked_keys, link) {
840         wl_list_remove(&keydata->link);
841         free(keydata);
842     }
843 }
844
845 static void
846 devicemgr_keyboard_grab_iface_key(struct ds_seat_keyboard_grab *grab,
847         uint32_t time_msec, uint32_t key, uint32_t state)
848 {
849     struct ds_tizen_input_devicemgr *devicemgr = grab->data;
850     struct ds_tizen_input_devicemgr_key_info *keydata, *tmp;
851     bool key_blocked = false;
852
853     ds_inf("devicemgr. keyboard_grab_iface_key");
854
855     if (!devicemgr->block_resource) {
856         if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
857             goto finish;
858         }
859         else {
860             wl_list_for_each_safe(keydata, tmp, &devicemgr->blocked_keys, link) {
861                 if (keydata->keycode == (int)key) {
862                     wl_list_remove(&keydata->link);
863                     free(keydata);
864                     key_blocked = true;
865                     break;
866                 }
867             }
868             if (wl_list_empty(&devicemgr->blocked_keys)) {
869                 tz_devicemgr_ungrab_keyboard(devicemgr);
870             }
871             if (key_blocked) {
872                 goto finish;
873             }
874         }
875     }
876
877     if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
878         keydata = calloc(1, sizeof (*keydata));
879         if (!keydata)
880             goto finish;
881         keydata->keycode = key;
882         wl_list_init(&keydata->link);
883         wl_list_insert(&devicemgr->blocked_keys, &keydata->link);
884         key_blocked = true;
885     }
886     else {
887         if (wl_list_empty(&devicemgr->blocked_keys))
888             goto finish;
889         wl_list_for_each_safe(keydata, tmp, &devicemgr->blocked_keys, link) {
890             if (keydata->keycode == (int)key) {
891                 wl_list_remove(&keydata->link);
892                 free(keydata);
893                 key_blocked = true;
894             }
895         }
896     }
897
898 finish:
899     if (!key_blocked)
900         ds_inf("block key event: (%d %s)\n", key, (state ? "press" : "release"));
901 }
902
903 static void
904 devicemgr_modifiers_grab_iface_key(struct ds_seat_keyboard_grab *grab,
905         struct ds_keyboard_modifiers *modifiers)
906 {
907     ds_inf("devicemgr. modifiers_grab_iface_key");
908 }
909
910 static void
911 devicemgr_cancel_grab_iface_key(struct ds_seat_keyboard_grab *grab)
912 {
913     ds_inf("devicemgr. cancel_grab_iface_key");
914 }
915
916 static const struct ds_keyboard_grab_interface devicemgr_keyboard_grab_iface = {
917     .enter = devicemgr_keyboard_grab_iface_enter,
918     .clear_focus = devicemgr_keyboard_grab_iface_clear_focus,
919     .key = devicemgr_keyboard_grab_iface_key,
920     .modifiers = devicemgr_modifiers_grab_iface_key,
921     .cancel = devicemgr_cancel_grab_iface_key,
922 };
923
924 static void
925 tz_devicemgr_grab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr)
926 {
927     ds_seat_keyboard_start_grab(tz_devicemgr->seat, tz_devicemgr->grab);
928 }
929
930 static void
931 tz_devicemgr_ungrab_keyboard(struct ds_tizen_input_devicemgr *tz_devicemgr)
932 {
933         ds_seat_keyboard_end_grab(tz_devicemgr->seat);
934 }
935
936 static void
937 tz_devicemgr_ungrab_keyboard_check(struct ds_tizen_input_devicemgr *tz_devicemgr)
938 {
939     if (wl_list_empty(&tz_devicemgr->blocked_keys))
940         tz_devicemgr_ungrab_keyboard(tz_devicemgr);
941
942     tz_devicemgr->block_resource = NULL;
943 }
944
945 static bool
946 devicemgr_add_timer(struct ds_tizen_input_devicemgr *tz_devicemgr,
947         wl_event_loop_timer_func_t func, int time)
948 {
949     struct wl_event_loop *event_loop;
950
951     event_loop = wl_display_get_event_loop(tz_devicemgr->backend->display);
952     if (!event_loop) {
953         ds_err("Failed to get event_loop from display: %p",
954                 tz_devicemgr->backend->display);
955         return false;
956     }
957
958     tz_devicemgr->timer = wl_event_loop_add_timer(event_loop, func,
959             tz_devicemgr);
960     if (!tz_devicemgr->timer) {
961         ds_err("Failed to timer");
962         return false;
963     }
964     wl_event_source_timer_update(tz_devicemgr->timer, time);
965
966     return true;
967 }
968
969 static int
970 devicemgr_block_timer(void *data)
971 {
972         struct ds_tizen_input_devicemgr *devicemgr = data;
973
974         tizen_input_device_manager_send_block_expired(devicemgr->block_resource);
975
976         tz_devicemgr_ungrab_keyboard_check(devicemgr);
977
978         wl_event_source_remove(devicemgr->timer);
979         devicemgr->timer = NULL;
980
981         return 1;
982 }
983
984 static void
985 device_manager_handle_block_events(struct wl_client *client,
986         struct wl_resource *resource, uint32_t serial, uint32_t clas,
987         uint32_t duration)
988 {
989     struct ds_tizen_input_devicemgr *tz_devicemgr;
990     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
991     bool res;
992
993     tz_devicemgr = wl_resource_get_user_data(resource);
994
995     if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
996             TIZEN_PRIV_INPUT_BLOCK)) {
997         ds_err("No permission to input generate");
998         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
999         goto finish;
1000     }
1001
1002     if (clas != TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD) {
1003         ds_err("only support keyboard device. (requested: 0x%x)\n", clas);
1004         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1005         goto finish;
1006     }
1007
1008     if(tz_devicemgr->block_resource) {
1009         ds_err("currently the input system is already blocked\n");
1010         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1011         goto finish;
1012     }
1013
1014     res = devicemgr_add_timer(tz_devicemgr, devicemgr_block_timer, duration);
1015     if (!res) {
1016         ds_err("Failed to add a timer\n");
1017         goto finish;
1018     }
1019
1020     tz_devicemgr_grab_keyboard(tz_devicemgr);
1021     tz_devicemgr->block_resource = resource;
1022     ds_inf("Block events. clas: %d, duration:%d", clas, duration);
1023     ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
1024
1025 finish:
1026     tizen_input_device_manager_send_error(resource, ret);
1027 }
1028
1029 static void
1030 device_manager_handle_unblock_events(struct wl_client *client,
1031         struct wl_resource *resource, uint32_t serial)
1032 {
1033     struct ds_tizen_input_devicemgr *tz_devicemgr;
1034     int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
1035
1036     tz_devicemgr = wl_resource_get_user_data(resource);
1037
1038     if (!tz_devicemgr_check_privilege(tz_devicemgr, client,
1039             TIZEN_PRIV_INPUT_BLOCK)) {
1040         ds_err("No permission to input generate");
1041         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION;
1042         goto finish;
1043     }
1044
1045     if (tz_devicemgr->block_resource != resource) {
1046         ds_err("currently the input system is blocked by another resource");
1047         ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1048         goto finish;
1049     }
1050
1051     tz_devicemgr_ungrab_keyboard_check(tz_devicemgr);
1052     tz_devicemgr->block_resource = NULL;
1053     ds_inf("Unblock events.");
1054     ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
1055
1056     if (tz_devicemgr->timer) {
1057                 wl_event_source_remove(tz_devicemgr->timer);
1058                 tz_devicemgr->timer = NULL;
1059         }
1060
1061 finish:
1062     tizen_input_device_manager_send_error(resource, ret);
1063 }