6a7e05d551d645455735f5a65ad0644185be88f6
[platform/upstream/enlightenment.git] / src / bin / e_devicemgr_inputgen.c
1 #include "e_devicemgr_private.h"
2 #include "e_input_intern.h"
3
4 #include <glib.h>
5
6 static Ecore_Device_Class
7 _e_devicemgr_inputgen_class_to_ecore_device_class(unsigned int clas)
8 {
9    switch(clas)
10      {
11       case TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE:
12          return ECORE_DEVICE_CLASS_MOUSE;
13       case TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD:
14          return ECORE_DEVICE_CLASS_KEYBOARD;
15       case TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN:
16          return ECORE_DEVICE_CLASS_TOUCH;
17       default:
18          return ECORE_DEVICE_CLASS_NONE;
19      }
20 }
21
22 static Eina_List **
23 _e_devicemgr_inputgen_list_get(Ecore_Device_Class clas)
24 {
25    switch (clas)
26      {
27         case ECORE_DEVICE_CLASS_KEYBOARD:
28           return &e_devicemgr->inputgen.kbd_list;
29           break;
30         case ECORE_DEVICE_CLASS_MOUSE:
31           return &e_devicemgr->inputgen.ptr_list;
32           break;
33         case ECORE_DEVICE_CLASS_TOUCH:
34           return &e_devicemgr->inputgen.touch_list;
35           break;
36         default:
37           return NULL;
38      }
39 }
40
41 static char *
42 _e_devicemgr_inputgen_name_get(struct wl_resource *resource)
43 {
44    Eina_List *l;
45    E_Devicemgr_Inputgen_Resource_Data *rdata;
46
47    EINA_LIST_FOREACH(e_devicemgr->inputgen.resource_list, l, rdata)
48      {
49         if (rdata->resource == resource) return rdata->name;
50      }
51
52    return NULL;
53 }
54
55 static Eina_Bool
56 _e_devicemgr_inputgen_device_check(char *name, Ecore_Device_Class clas)
57 {
58    Eina_List **dev_list, *l;
59    E_Devicemgr_Inputgen_Device_Data *ddata;
60
61    if (!name) return EINA_FALSE;
62    dev_list = _e_devicemgr_inputgen_list_get(clas);
63    EINA_SAFETY_ON_NULL_RETURN_VAL(dev_list, EINA_FALSE);
64
65    EINA_LIST_FOREACH(*dev_list, l, ddata)
66      {
67         if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
68           return EINA_TRUE;
69      }
70
71    return EINA_FALSE;
72 }
73
74 static void
75 _e_devicemgr_inputgen_key_event_free(void *data EINA_UNUSED, void *ev)
76 {
77    Ecore_Event_Key *e = ev;
78
79    eina_stringshare_del(e->keyname);
80    eina_stringshare_del(e->key);
81    eina_stringshare_del(e->compose);
82
83    if (e_input_thread_mode_get())
84      {
85         if (e->dev) g_object_unref(e->dev);
86      }
87    else
88      {
89         if (e->dev) ecore_device_unref(e->dev);
90      }
91
92    if (e->data) E_FREE(e->data);
93
94    free(e);
95 }
96
97 EINTERN int
98 e_devicemgr_inputgen_key_event_add(const char *key, Eina_Bool pressed, char *identifier)
99 {
100    Ecore_Event_Key *e;
101    unsigned int keycode;
102    E_Keyrouter_Event_Data *key_data;
103    E_Device *dev = NULL;
104
105    EINA_SAFETY_ON_NULL_RETURN_VAL(key, TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER);
106
107    e = E_NEW(Ecore_Event_Key, 1);
108    EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
109
110    keycode = e_comp_wl_input_keymap_keyname_to_keycode(key);
111    if (keycode <= 0) goto finish;
112
113    e->keyname = eina_stringshare_add(key);
114    e->key = eina_stringshare_add(key);
115    e->compose = eina_stringshare_add(key);
116    e->string = e->compose;
117
118    e->window = e_comp->ee_win;
119    e->event_window = e_comp->ee_win;
120    e->root_window = e_comp->ee_win;
121    e->timestamp = e_util_timestamp_get();
122    e->same_screen = 1;
123    e->keycode = keycode;
124    key_data = E_NEW(E_Keyrouter_Event_Data, 1);
125    EINA_SAFETY_ON_NULL_GOTO(key_data, finish);
126    e->data = key_data;
127
128    e->modifiers = 0;
129
130    if (e_input_thread_mode_get())
131      {
132         dev = e_input_evdev_get_e_device(identifier, ECORE_DEVICE_CLASS_KEYBOARD);
133         e->dev = (Eo *)g_object_ref(dev);
134      }
135    else
136      {
137         e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_KEYBOARD));
138      }
139
140    DMDBG("Generate key event: key: %s, keycode: %d, iden: %s\n", e->key, e->keycode, identifier);
141
142    if (e_input_thread_mode_get())
143      {
144         E_Input_Event_Source *input_event_source = e_input_event_source_get();
145         e_input_event_add(input_event_source, pressed ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP, e, _e_devicemgr_inputgen_key_event_free, NULL);
146      }
147    else
148      {
149         ecore_event_add(pressed ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP, e, _e_devicemgr_inputgen_key_event_free, NULL);
150      }
151
152    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
153
154 finish:
155     if(e) E_FREE(e);
156     return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
157 }
158
159 static void
160 _e_devicemgr_inputgen_mouse_button_event_free(void *data EINA_UNUSED, void *ev)
161 {
162    Ecore_Event_Mouse_Button *e = ev;
163
164    if (e->dev) ecore_device_unref(e->dev);
165
166    free(e);
167 }
168
169 int
170 _e_devicemgr_inputgen_mouse_button_event(Eina_Bool state, int x, int y, int buttons, char *identifier)
171 {
172    Ecore_Event_Mouse_Button *e;
173
174    e = calloc(1, sizeof(Ecore_Event_Mouse_Button));
175    EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
176
177    e->window = e_comp->ee_win;
178    e->event_window = e_comp->ee_win;
179    e->root_window = e_comp->ee_win;
180    e->timestamp = e_util_timestamp_get();
181    e->same_screen = 1;
182
183    e->x = x;
184    e->y = y;
185    e->root.x = e->x;
186    e->root.y = e->y;
187
188    e->multi.device = 0;
189    e->multi.radius = 1;
190    e->multi.radius_x = 1;
191    e->multi.radius_y = 1;
192    e->multi.pressure = 1.0;
193    e->multi.angle = 0.0;
194
195    e->multi.x = e->x;
196    e->multi.y = e->y;
197    e->multi.root.x = e->x;
198    e->multi.root.y = e->y;
199
200    ecore_thread_main_loop_begin();
201    e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_MOUSE));
202    e->buttons = buttons;
203
204    DMDBG("Generate mouse button event: button: %d (state: %d)\n", buttons, state);
205
206    if (state)
207      ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
208    else
209      ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
210
211    ecore_thread_main_loop_end();
212
213    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
214 }
215
216 static void
217 _e_devicemgr_inputgen_mouse_move_event_free(void *data EINA_UNUSED, void *ev)
218 {
219    Ecore_Event_Mouse_Move *e = ev;
220
221    if (e->dev) ecore_device_unref(e->dev);
222
223    free(e);
224 }
225
226 int
227 _e_devicemgr_inputgen_mouse_move_event(int x, int y, char *identifier)
228 {
229    Ecore_Event_Mouse_Move *e;
230
231    e = calloc(1, sizeof(Ecore_Event_Mouse_Move));
232    if (!e) return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
233
234    e->window = e_comp->ee_win;
235    e->event_window = e_comp->ee_win;
236    e->root_window = e_comp->ee_win;
237    e->timestamp = e_util_timestamp_get();
238    e->same_screen = 1;
239
240    e->x = x;
241    e->y = y;
242    e->root.x = e->x;
243    e->root.y = e->y;
244
245    e->multi.device = 0;
246    e->multi.radius = 1;
247    e->multi.radius_x = 1;
248    e->multi.radius_y = 1;
249    e->multi.pressure = 1.0;
250    e->multi.angle = 0.0;
251
252    e->multi.x = e->x;
253    e->multi.y = e->y;
254    e->multi.root.x = e->x;
255    e->multi.root.y = e->y;
256
257    ecore_thread_main_loop_begin();
258    e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(identifier, ECORE_DEVICE_CLASS_MOUSE));
259
260    DMDBG("Generate mouse move event: (%d, %d)\n", e->x, e->y);
261
262    ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, _e_devicemgr_inputgen_mouse_move_event_free, NULL);
263    ecore_thread_main_loop_end();
264
265    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
266 }
267
268 static void
269 _e_devicemgr_inputgen_mouse_wheel_event_free(void *data EINA_UNUSED, void *ev)
270 {
271    Ecore_Event_Mouse_Wheel *e = ev;
272
273    if (e->dev) ecore_device_unref(e->dev);
274
275    free(e);
276 }
277
278 static int
279 _e_devicemgr_inputgen_mouse_wheel_event(unsigned int type, int value, E_Devicemgr_Inputgen_Device_Data *device)
280 {
281    Ecore_Event_Mouse_Wheel *e;
282    Ecore_Device_Class clas = ECORE_DEVICE_CLASS_NONE;
283
284    e = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
285    if (!e) return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
286
287    e->window = e_comp->ee_win;
288    e->event_window = e_comp->ee_win;
289    e->root_window = e_comp->ee_win;
290    e->timestamp = e_util_timestamp_get();
291    e->same_screen = 1;
292
293    /* FIXME: set current coords */
294    e->x = 0;
295    e->y = 0;
296    e->root.x = e->x;
297    e->root.y = e->y;
298
299    if (type == TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_WHEEL)
300      e->direction = 0;
301    else
302      e->direction = 1;
303    e->z = value;
304
305    ecore_thread_main_loop_begin();
306
307    if (device)
308      {
309         if (!e_devicemgr_detent_is_detent(device->name))
310           clas = device->clas;
311         e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(device->identifier, clas));
312      }
313
314    DMDBG("Generate mouse wheel event: direction: %s, value: %d\n", e->direction?"HWHEEL":"WHEEL", e->z);
315
316    ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, _e_devicemgr_inputgen_mouse_wheel_event_free, NULL);
317
318    ecore_thread_main_loop_end();
319
320    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
321 }
322
323 static void
324 _e_devicemgr_inputgen_touch_axis_store(E_Devicemgr_Inputgen_Device_Data *device, unsigned int type, double value)
325 {
326    EINA_SAFETY_ON_NULL_RETURN(device);
327
328    switch (type)
329      {
330         case TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_RADIUS_X:
331            device->touch.axis_tmp.radius_x = value;
332            break;
333         case TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_RADIUS_Y:
334            device->touch.axis_tmp.radius_y = value;
335            break;
336         case TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_PRESSURE:
337            device->touch.axis_tmp.pressure = value;
338            break;
339         case TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_ANGLE:
340            device->touch.axis_tmp.angle = value;
341            break;
342         case TIZEN_INPUT_DEVICE_MANAGER_AXIS_TYPE_PALM:
343            device->touch.axis_tmp.palm = value;
344            break;
345         default:
346            DMWRN("Invalid type (%d).\n", type);
347            break;
348      }
349 }
350
351 static void
352 _e_devicemgr_inputgen_touch_axis_update(E_Devicemgr_Inputgen_Device_Data *device, int idx)
353 {
354    EINA_SAFETY_ON_NULL_RETURN(device);
355
356    if (device->touch.axis_tmp.radius_x != -1.0)
357      device->touch.axis[idx].radius_x = device->touch.axis_tmp.radius_x;
358
359    if (device->touch.axis_tmp.radius_y != -1.0)
360      device->touch.axis[idx].radius_y = device->touch.axis_tmp.radius_y;
361
362    if (device->touch.axis_tmp.pressure != -1.0)
363      device->touch.axis[idx].pressure = device->touch.axis_tmp.pressure;
364
365    if (device->touch.axis_tmp.angle != -1.0)
366      device->touch.axis[idx].angle = device->touch.axis_tmp.angle;
367
368    if (device->touch.axis_tmp.palm != -1.0)
369      device->touch.axis[idx].palm = device->touch.axis_tmp.palm;
370 }
371
372 static void
373 _e_devicemgr_inputgen_touch_axis_cleanup(E_Devicemgr_Inputgen_Device_Data *device, int idx)
374 {
375    EINA_SAFETY_ON_NULL_RETURN(device);
376
377    if (idx < 0)
378      {
379         device->touch.axis_tmp.radius_x = -1.0;
380         device->touch.axis_tmp.radius_y = -1.0;
381         device->touch.axis_tmp.pressure = -1.0;
382         device->touch.axis_tmp.angle = -1.0;
383         device->touch.axis_tmp.palm = -1.0;
384      }
385    else
386      {
387         device->touch.axis[idx].radius_x = 1.0;
388         device->touch.axis[idx].radius_y = 1.0;
389         device->touch.axis[idx].pressure = 1.0;
390         device->touch.axis[idx].angle = 0.0;
391         device->touch.axis[idx].palm = 0.0;
392      }
393 }
394
395 static int
396 _e_devicemgr_inputgen_touch_event(uint32_t type, uint32_t x, uint32_t y, uint32_t finger, E_Devicemgr_Inputgen_Device_Data *device)
397 {
398    Ecore_Event_Mouse_Button *e;
399
400    e = calloc(1, sizeof(Ecore_Event_Mouse_Button));
401    EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
402
403    e->window = e_comp->ee_win;
404    e->event_window = e_comp->ee_win;
405    e->root_window = e_comp->ee_win;
406    e->timestamp = e_util_timestamp_get();
407    e->same_screen = 1;
408
409    e->x = x;
410    e->y = y;
411    e->root.x = e->x;
412    e->root.y = e->y;
413
414    if (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN)
415      _e_devicemgr_inputgen_touch_axis_update(device, finger);
416    else
417      _e_devicemgr_inputgen_touch_axis_cleanup(device, finger);
418    _e_devicemgr_inputgen_touch_axis_cleanup(device, -1);
419
420    e->multi.device = finger;
421    if (device)
422      {
423         e->multi.radius = device->touch.axis[finger].radius_x;
424         e->multi.radius_x = device->touch.axis[finger].radius_x;
425         e->multi.radius_y = device->touch.axis[finger].radius_y;
426         e->multi.pressure = device->touch.axis[finger].pressure;
427         e->multi.angle = device->touch.axis[finger].angle;
428      }
429    else
430      {
431         e->multi.radius = 1.0;
432         e->multi.radius_x = 1.0;
433         e->multi.radius_y = 1.0;
434         e->multi.pressure = 1.0;
435         e->multi.angle = 0.0;
436      }
437
438    e->multi.x = e->x;
439    e->multi.y = e->y;
440    e->multi.root.x = e->x;
441    e->multi.root.y = e->y;
442
443    ecore_thread_main_loop_begin();
444    e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(device?device->identifier:NULL, ECORE_DEVICE_CLASS_TOUCH));
445    e->buttons = 1;
446
447    DMDBG("Generate touch event: device: %d (%d, %d)\n", e->multi.device, e->x, e->y);
448
449    if (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN)
450      ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
451    else
452      ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, _e_devicemgr_inputgen_mouse_button_event_free, NULL);
453
454    ecore_thread_main_loop_end();
455
456    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
457 }
458
459 static int
460 _e_devicemgr_inputgen_touch_update_event(uint32_t x, uint32_t y, uint32_t finger, E_Devicemgr_Inputgen_Device_Data *device)
461 {
462    Ecore_Event_Mouse_Move *e;
463
464    e = calloc(1, sizeof(Ecore_Event_Mouse_Move));
465    EINA_SAFETY_ON_NULL_RETURN_VAL(e, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
466
467    e->window = e_comp->ee_win;
468    e->event_window = e_comp->ee_win;
469    e->root_window = e_comp->ee_win;
470    e->timestamp = e_util_timestamp_get();
471    e->same_screen = 1;
472
473    e->x = x;
474    e->y = y;
475    e->root.x = e->x;
476    e->root.y = e->y;
477
478    _e_devicemgr_inputgen_touch_axis_update(device, finger);
479    _e_devicemgr_inputgen_touch_axis_cleanup(device, -1);
480
481    e->multi.device = finger;
482    if (device)
483      {
484         e->multi.radius = device->touch.axis[finger].radius_x;
485         e->multi.radius_x = device->touch.axis[finger].radius_x;
486         e->multi.radius_y = device->touch.axis[finger].radius_y;
487         e->multi.pressure = device->touch.axis[finger].pressure;
488         e->multi.angle = device->touch.axis[finger].angle;
489      }
490    else
491      {
492         e->multi.radius = 1.0;
493         e->multi.radius_x = 1.0;
494         e->multi.radius_y = 1.0;
495         e->multi.pressure = 1.0;
496         e->multi.angle = 0.0;
497      }
498
499    e->multi.x = e->x;
500    e->multi.y = e->y;
501    e->multi.root.x = e->x;
502    e->multi.root.y = e->y;
503
504    ecore_thread_main_loop_begin();
505
506    e->dev = ecore_device_ref(e_input_evdev_get_ecore_device(device?device->identifier:NULL, ECORE_DEVICE_CLASS_TOUCH));
507
508    DMDBG("Generate touch move event: device: %d (%d, %d)\n", e->multi.device, e->x, e->y);
509
510    ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, _e_devicemgr_inputgen_mouse_move_event_free, NULL);
511    ecore_thread_main_loop_end();
512
513    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
514 }
515
516 static void
517 _e_devicemgr_inputgen_remove_device(E_Devicemgr_Inputgen_Device_Data *device)
518 {
519    int i = 0, ret;
520    Eina_List *l, *l_next;
521    Eina_Stringshare *str_data;
522
523    if (!device)
524      {
525         DMWRN("There are no devices created for input generation.\n");
526         return;
527      }
528
529    switch (device->clas)
530      {
531         case ECORE_DEVICE_CLASS_TOUCH:
532           while (device->touch.pressed)
533             {
534                if (device->touch.pressed & (1 << i))
535                  {
536                     ret = _e_devicemgr_inputgen_touch_event(
537                             TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END,
538                             device->touch.coords[i].x,
539                             device->touch.coords[i].y,
540                             i, device);
541                     if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
542                       DMWRN("Failed to generate touch up event: %d\n", ret);
543                     device->touch.pressed &= ~(1 << i);
544                  }
545                i++;
546                if (i >= e_input_touch_max_count_get()) break;
547             }
548           if (device->touch.coords)
549             {
550                free(device->touch.coords);
551                device->touch.coords = NULL;
552             }
553           if (device->touch.axis)
554             {
555                free(device->touch.axis);
556                device->touch.axis = NULL;
557             }
558           break;
559         case ECORE_DEVICE_CLASS_MOUSE:
560           while (device->mouse.pressed)
561             {
562                if (device->mouse.pressed & (1 << i))
563                  {
564                     ret = _e_devicemgr_inputgen_mouse_button_event(
565                             EINA_FALSE,
566                             device->mouse.coords.x,
567                             device->mouse.coords.y,
568                             i + 1, device->identifier);
569                     if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
570                       DMWRN("Failed to generate mouse button up event: %d\n", ret);
571                     device->mouse.pressed &= ~(1 << i);
572                  }
573                i++;
574                if (i >= INPUTGEN_MAX_BTN) break;
575             }
576           break;
577         case ECORE_DEVICE_CLASS_KEYBOARD:
578           EINA_LIST_FOREACH_SAFE(device->key.pressed, l, l_next, str_data)
579             {
580                ret = e_devicemgr_inputgen_key_event_add(str_data, EINA_FALSE, device->identifier);
581                if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
582                  DMWRN("Failed to generate key up event: %d\n", ret);
583                eina_stringshare_del(str_data);
584                device->key.pressed = eina_list_remove_list(device->key.pressed, l);
585             }
586           break;
587         default:
588           break;
589      }
590
591    if (device->uinp_fd >= 0)
592      {
593         e_devicemgr_destroy_virtual_device(device->uinp_fd);
594         device->uinp_fd = -1;
595      }
596    E_FREE(device->identifier);
597 }
598
599 static void
600 _e_devicemgr_inputgen_client_device_remove(struct wl_client *client, Ecore_Device_Class clas)
601 {
602    Eina_List **dev_list, *l, *l_next, *ll, *ll_next;
603    E_Devicemgr_Inputgen_Device_Data *ddata;
604    E_Devicemgr_Inputgen_Client_Data *cdata;
605
606    dev_list = _e_devicemgr_inputgen_list_get(clas);
607    EINA_SAFETY_ON_NULL_RETURN(dev_list);
608
609    EINA_LIST_FOREACH_SAFE(*dev_list, l, l_next, ddata)
610      {
611         EINA_LIST_FOREACH_SAFE(ddata->clients, ll, ll_next, cdata)
612           {
613              if (cdata->client == client)
614                {
615                   ddata->clients = eina_list_remove_list(ddata->clients, ll);
616                   E_FREE(cdata);
617                }
618           }
619         if (eina_list_count(ddata->clients) == 0)
620           {
621              _e_devicemgr_inputgen_remove_device(ddata);
622              *dev_list = eina_list_remove_list(*dev_list, l);
623              E_FREE(ddata);
624           }
625      }
626 }
627
628 static void
629 _e_devicemgr_inputgen_client_cb_destroy(struct wl_listener *l, void *data)
630 {
631    struct wl_client *client = (struct wl_client *)data;
632    E_Devicemgr_Inputgen_Resource_Data *rdata;
633    E_Devicemgr_Inputgen_Client_Global_Data *gdata;
634    Eina_List *list, *l_next;
635
636    EINA_SAFETY_ON_NULL_RETURN(l);
637
638    wl_list_remove(&l->link);
639    E_FREE(l);
640
641    EINA_LIST_FOREACH_SAFE(e_devicemgr->watched_clients, list, l_next, gdata)
642      {
643         if (gdata->client == client)
644           {
645              e_devicemgr->watched_clients =
646                eina_list_remove_list(e_devicemgr->watched_clients, list);
647              E_FREE(gdata);
648
649              break;
650           }
651      }
652
653    _e_devicemgr_inputgen_client_device_remove(client, ECORE_DEVICE_CLASS_KEYBOARD);
654    _e_devicemgr_inputgen_client_device_remove(client, ECORE_DEVICE_CLASS_MOUSE);
655    _e_devicemgr_inputgen_client_device_remove(client, ECORE_DEVICE_CLASS_TOUCH);
656
657    EINA_LIST_FOREACH_SAFE(e_devicemgr->inputgen.resource_list, list, l_next, rdata)
658      {
659         if (wl_resource_get_client(rdata->resource) == client)
660           {
661              e_devicemgr->inputgen.resource_list =
662                eina_list_remove_list(e_devicemgr->inputgen.resource_list, list);
663              E_FREE_FUNC(rdata->sync_timer, ecore_timer_del);
664              E_FREE(rdata);
665           }
666      }
667 }
668
669 static void
670 _e_devicemgr_inputgen_client_add(struct wl_client *client, unsigned int clas)
671 {
672    struct wl_listener *destroy_listener;
673    E_Devicemgr_Inputgen_Client_Global_Data *data;
674    Eina_List *l;
675
676    EINA_LIST_FOREACH(e_devicemgr->watched_clients, l, data)
677      {
678         if (data->client == client)
679           {
680              data->clas |= clas;
681              return;
682           }
683      }
684    data = NULL;
685
686    destroy_listener = E_NEW(struct wl_listener, 1);
687    EINA_SAFETY_ON_NULL_GOTO(destroy_listener, failed);
688    destroy_listener->notify = _e_devicemgr_inputgen_client_cb_destroy;
689    wl_client_add_destroy_listener(client, destroy_listener);
690
691    data = E_NEW(E_Devicemgr_Inputgen_Client_Global_Data, 1);
692    EINA_SAFETY_ON_NULL_GOTO(data, failed);
693
694    data->client = client;
695    data->clas = clas;
696
697    e_devicemgr->watched_clients =
698       eina_list_append(e_devicemgr->watched_clients, data);
699
700    return;
701
702 failed:
703    if (destroy_listener)
704      {
705         wl_list_remove(&destroy_listener->link);
706         E_FREE(destroy_listener);
707      }
708 }
709
710 static void
711 _e_devicemgr_inputgen_client_del(struct wl_client *client, unsigned int clas)
712 {
713    E_Devicemgr_Inputgen_Client_Global_Data *data;
714    E_Devicemgr_Inputgen_Client_Data *cdata;
715    E_Devicemgr_Inputgen_Device_Data *ddata;
716    Eina_List *l, *ll, *l_next, *ll_next, **list;
717    Ecore_Device_Class eclas = ECORE_DEVICE_CLASS_NONE;
718
719    eclas = _e_devicemgr_inputgen_class_to_ecore_device_class(clas);
720    list = _e_devicemgr_inputgen_list_get(eclas);
721    EINA_SAFETY_ON_NULL_RETURN(list);
722
723    EINA_LIST_FOREACH_SAFE(*list, l, l_next, ddata)
724      {
725         EINA_LIST_FOREACH_SAFE(ddata->clients, ll, ll_next, cdata)
726           {
727              if (cdata->client == client)
728                {
729                   cdata->ref--;
730                   if (cdata->ref <= 0)
731                     {
732                        ddata->clients = eina_list_remove_list(ddata->clients, ll);
733                        E_FREE(cdata);
734                     }
735                }
736           }
737
738         if (eina_list_count(ddata->clients) == 0)
739           {
740              ddata->clients = NULL;
741              _e_devicemgr_inputgen_remove_device(ddata);
742              *list = eina_list_remove_list(*list, l);
743              E_FREE(ddata);
744           }
745      }
746
747    EINA_LIST_FOREACH(e_devicemgr->watched_clients, l, data)
748      {
749         if (data->client == client)
750           {
751              data->clas &= ~clas;
752           }
753      }
754 }
755
756 static E_Devicemgr_Inputgen_Resource_Data *
757 _e_devicemgr_inputgen_resource_add(struct wl_resource *resource, const char *name)
758 {
759    E_Devicemgr_Inputgen_Resource_Data *rdata;
760    Eina_List *l;
761
762    EINA_LIST_FOREACH(e_devicemgr->inputgen.resource_list, l, rdata)
763      {
764         if (rdata->resource == resource) return rdata;
765      }
766
767    rdata = NULL;
768    rdata = E_NEW(E_Devicemgr_Inputgen_Resource_Data, 1);
769    EINA_SAFETY_ON_NULL_RETURN_VAL(rdata, NULL);
770
771    rdata->resource = resource;
772    strncpy(rdata->name, name, UINPUT_MAX_NAME_SIZE - 1);
773
774    e_devicemgr->inputgen.resource_list = eina_list_append(e_devicemgr->inputgen.resource_list, rdata);
775
776    return rdata;
777 }
778
779 static void
780 _e_devicemgr_inputgen_resource_del(struct wl_resource *resource)
781 {
782    E_Devicemgr_Inputgen_Resource_Data *rdata;
783    Eina_List *l, *l_next;
784
785    EINA_LIST_FOREACH_SAFE(e_devicemgr->inputgen.resource_list, l, l_next, rdata)
786      {
787         if (rdata->resource == resource)
788           {
789              e_devicemgr->inputgen.resource_list =
790                eina_list_remove_list(e_devicemgr->inputgen.resource_list, l);
791              E_FREE_FUNC(rdata->sync_timer, ecore_timer_del);
792              E_FREE(rdata);
793           }
794      }
795 }
796
797 static Eina_Bool
798 _e_devicemgr_inputgen_hw_device_check(E_Devicemgr_Inputgen_Device_Data *device)
799 {
800    Eina_List *l;
801    E_Devicemgr_Input_Device *dev;
802    Ecore_Device_Class clas = ECORE_DEVICE_CLASS_NONE;
803
804    if (!e_devicemgr_detent_is_detent(device->name))
805      clas = device->clas;
806
807    g_rec_mutex_lock(&e_devicemgr->device_list_mutex);
808    EINA_LIST_FOREACH(e_devicemgr->device_list, l, dev)
809      {
810         if ((dev->clas == clas) &&
811             (e_devicemgr_strcmp(dev->name, device->name)))
812           {
813              E_FREE(device->identifier);
814              if (dev->identifier) device->identifier = strdup(dev->identifier);
815              g_rec_mutex_unlock(&e_devicemgr->device_list_mutex);
816              return EINA_TRUE;
817           }
818      }
819    g_rec_mutex_unlock(&e_devicemgr->device_list_mutex);
820
821    return EINA_FALSE;
822 }
823
824 static Eina_Bool
825 _e_devicemgr_init_touch_coords_and_axis(E_Devicemgr_Inputgen_Device_Data *device)
826 {
827    int touch_max = e_input_touch_max_count_get();
828    int i;
829    if (device->touch.coords)
830      free(device->touch.coords);
831
832    if (e_config->configured_max_touch.use)
833      {
834         touch_max = e_config->configured_max_touch.count;
835      }
836    device->touch.coords = calloc(1, sizeof(E_Devicemgr_Coords)*touch_max);
837    if (!device->touch.coords)
838      {
839         DMWRN("Failed to allocate memory for coords ptr ! (finger=%d)\n", touch_max);
840         return EINA_FALSE;
841      }
842
843    for (i = 0; i < touch_max; i++)
844      {
845         device->touch.coords[i].x = -1;
846         device->touch.coords[i].y = -1;
847      }
848
849    if (device->touch.axis)
850      free(device->touch.axis);
851
852    device->touch.axis = calloc(1, sizeof(E_Devicemgr_Inputgen_Touch_Axis)*touch_max);
853    if (!device->touch.axis)
854      {
855         DMWRN("Failed to allocate memory for axis ptr ! (finger=%d)\n", touch_max);
856         free(device->touch.coords);
857         return EINA_FALSE;
858      }
859
860    return EINA_TRUE;
861 }
862
863 int
864 _e_devicemgr_inputgen_create_device(Ecore_Device_Class clas, struct wl_client *client, const char *device_name)
865 {
866    int uinp_fd = -1;
867    Eina_List **dev_list, *l, *ll;
868    E_Devicemgr_Inputgen_Client_Data *cdata;
869    E_Devicemgr_Inputgen_Device_Data *ddata, *device = NULL;
870    Eina_Bool exist_device_flag = EINA_FALSE;
871
872    dev_list = _e_devicemgr_inputgen_list_get(clas);
873    EINA_SAFETY_ON_NULL_RETURN_VAL(dev_list, EINA_FALSE);
874
875    EINA_LIST_FOREACH(*dev_list, l, ddata)
876      {
877         if (!strncmp(ddata->name, device_name, UINPUT_MAX_NAME_SIZE))
878           {
879              EINA_LIST_FOREACH(ddata->clients, ll, cdata)
880                {
881                   if (cdata->client == client)
882                     {
883                        cdata->ref++;
884                        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
885                     }
886                }
887
888              device = ddata;
889              exist_device_flag = EINA_TRUE;
890              break;
891           }
892      }
893
894    if (!device)
895      {
896         device = E_NEW(E_Devicemgr_Inputgen_Device_Data, 1);
897         EINA_SAFETY_ON_NULL_RETURN_VAL(device, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES);
898         strncpy(device->name, device_name, UINPUT_MAX_NAME_SIZE - 1);
899         device->clas = clas;
900      }
901
902    cdata = E_NEW(E_Devicemgr_Inputgen_Client_Data, 1);
903    if(!cdata)
904      {
905         if (!exist_device_flag) E_FREE(device);
906         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
907      }
908
909    cdata->ref = 1;
910    cdata->client = client;
911
912    device->clients = eina_list_append(device->clients, cdata);
913
914    if (exist_device_flag)
915      return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
916
917    if (!_e_devicemgr_inputgen_hw_device_check(device))
918      {
919         uinp_fd = e_devicemgr_create_virtual_device(clas, device_name);
920
921         if (uinp_fd < 0)
922           goto fail_create_device;
923      }
924
925    device->uinp_fd = uinp_fd;
926    *dev_list = eina_list_append(*dev_list, device);
927
928    if (!_e_devicemgr_init_touch_coords_and_axis(device))
929      {
930         DMERR("DEVMGR_TOUCH Failed to init touch coords and axis !\n");
931         goto fail_create_device;
932      }
933
934    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
935
936 fail_create_device:
937    EINA_LIST_FREE(device->clients, cdata)
938      E_FREE(cdata);
939    E_FREE(device);
940    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
941 }
942
943 int
944 e_devicemgr_inputgen_add(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name)
945 {
946    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
947
948    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD)
949      ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_KEYBOARD, client, name);
950    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
951      ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_MOUSE, client, name);
952    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
953      ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_TOUCH, client, name);
954
955    if (ret == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
956      {
957         _e_devicemgr_inputgen_client_add(client, clas);
958         _e_devicemgr_inputgen_resource_add(resource, name);
959      }
960
961    return ret;
962 }
963
964 void
965 e_devicemgr_inputgen_device_ready_send(E_Devicemgr_Input_Device *dev)
966 {
967    E_Devicemgr_Inputgen_Resource_Data *rdata;
968    Eina_List *l;
969    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
970
971    EINA_LIST_FOREACH(e_devicemgr->inputgen.resource_list, l, rdata)
972      {
973         if (e_devicemgr_strcmp(rdata->name, dev->name) == EINA_FALSE) continue;
974         if (rdata->sync_timer)
975           {
976              e_devicemgr_wl_generator_with_sync_send_event(rdata->resource, ret);
977
978              ecore_timer_del(rdata->sync_timer);
979              rdata->sync_timer = NULL;
980           }
981      }
982 }
983
984 Eina_Bool
985 _e_devicemgr_inputgen_sync_timer(void *data)
986 {
987    E_Devicemgr_Inputgen_Resource_Data *rdata = data;
988    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES;
989
990    DMERR("Init Generator with sync. timer expired!!! dev: %s", rdata->name);
991
992    if (!rdata || !rdata->resource) return ECORE_CALLBACK_CANCEL;
993
994    e_devicemgr_wl_generator_with_sync_send_event(rdata->resource, ret);
995
996    rdata->sync_timer = NULL;
997
998    return ECORE_CALLBACK_CANCEL;
999 }
1000
1001 void
1002 e_devicemgr_inputgen_add_with_sync(struct wl_client *client, struct wl_resource *resource, uint32_t clas, const char *name)
1003 {
1004    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
1005    E_Devicemgr_Inputgen_Resource_Data *rdata;
1006
1007    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD)
1008      ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_KEYBOARD, client, name);
1009    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
1010      ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_MOUSE, client, name);
1011    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
1012      ret = _e_devicemgr_inputgen_create_device(ECORE_DEVICE_CLASS_TOUCH, client, name);
1013
1014    if (ret == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
1015      {
1016         _e_devicemgr_inputgen_client_add(client, clas);
1017         rdata = _e_devicemgr_inputgen_resource_add(resource, name);
1018         if (!rdata) return;
1019         rdata->sync_timer = ecore_timer_add(2.0, _e_devicemgr_inputgen_sync_timer, rdata);
1020      }
1021
1022    return;
1023 }
1024
1025 void
1026 e_devicemgr_inputgen_remove(struct wl_client *client, struct wl_resource *resource, uint32_t clas)
1027 {
1028    Eina_List *l, *l_next;
1029    E_Devicemgr_Inputgen_Client_Global_Data *data;
1030    struct wl_listener *listener;
1031
1032    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD)
1033      _e_devicemgr_inputgen_client_del(client, TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD);
1034    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE)
1035      _e_devicemgr_inputgen_client_del(client, TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE);
1036    if (clas & TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN)
1037      _e_devicemgr_inputgen_client_del(client, TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN);
1038
1039    EINA_LIST_FOREACH_SAFE(e_devicemgr->watched_clients, l, l_next, data)
1040      {
1041         if (data && data->client == client && !data->clas)
1042           {
1043              listener = wl_client_get_destroy_listener(client,
1044                         _e_devicemgr_inputgen_client_cb_destroy);
1045              if (listener)
1046                {
1047                   wl_list_remove(&listener->link);
1048                   E_FREE(listener);
1049                }
1050
1051              e_devicemgr->watched_clients =
1052                 eina_list_remove_list(e_devicemgr->watched_clients, l);
1053              E_FREE(data);
1054
1055              break;
1056           }
1057      }
1058
1059    _e_devicemgr_inputgen_resource_del(resource);
1060 }
1061
1062
1063 int
1064 e_devicemgr_inputgen_generate_key(struct wl_client *client, struct wl_resource *resource, const char *keyname, Eina_Bool pressed)
1065 {
1066    Eina_List *l, *l_next;
1067    E_Devicemgr_Inputgen_Device_Data *ddata;
1068    char *name, *identifier = NULL;
1069    Eina_Stringshare *name_data;
1070    int ret;
1071
1072    name = _e_devicemgr_inputgen_name_get(resource);
1073
1074    if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_KEYBOARD))
1075      {
1076         DMWRN("generate is not init\n");
1077         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1078      }
1079
1080    g_mutex_lock(&e_comp_wl->xkb.keymap_mutex);
1081    if (!e_comp_wl->xkb.keymap)
1082      {
1083         DMWRN("keymap is not ready\n");
1084         g_mutex_unlock(&e_comp_wl->xkb.keymap_mutex);
1085         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1086      }
1087    g_mutex_unlock(&e_comp_wl->xkb.keymap_mutex);
1088
1089    EINA_LIST_FOREACH(e_devicemgr->inputgen.kbd_list, l, ddata)
1090      {
1091         if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
1092           {
1093              identifier = ddata->identifier;
1094              break;
1095           }
1096      }
1097
1098    if (!identifier)
1099      {
1100         DMWRN("device is not ready\n");
1101         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1102      }
1103
1104    if (ddata)
1105      {
1106         if (pressed)
1107           {
1108              ddata->key.pressed = eina_list_append(ddata->key.pressed, eina_stringshare_add(keyname));
1109           }
1110         else
1111           {
1112              EINA_LIST_FOREACH_SAFE(ddata->key.pressed, l, l_next, name_data)
1113                {
1114                   if (e_devicemgr_strcmp(name_data, keyname))
1115                     {
1116                        ddata->key.pressed = eina_list_remove_list(ddata->key.pressed, l);
1117                        eina_stringshare_del(name_data);
1118                     }
1119                }
1120           }
1121      }
1122
1123    ret = e_devicemgr_inputgen_key_event_add(keyname, pressed, identifier);
1124    return ret;
1125 }
1126
1127 int
1128 e_devicemgr_inputgen_generate_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t button)
1129 {
1130    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
1131    Eina_Bool state;
1132    Eina_List *l;
1133    E_Devicemgr_Inputgen_Device_Data *ddata = NULL;
1134    char *name, *identifier = NULL;
1135
1136    if (0 >= button || button >= INPUTGEN_MAX_BTN)
1137      {
1138         DMWRN("Invalid button: %d\n", button);
1139         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1140      }
1141
1142    name = _e_devicemgr_inputgen_name_get(resource);
1143
1144    if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_MOUSE))
1145      {
1146         DMWRN("generate is not init\n");
1147         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1148      }
1149
1150    EINA_LIST_FOREACH(e_devicemgr->inputgen.ptr_list, l, ddata)
1151      {
1152         if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
1153           {
1154              identifier = ddata->identifier;
1155              break;
1156           }
1157      }
1158
1159    if (!identifier)
1160      {
1161         DMWRN("device is not ready\n");
1162         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1163      }
1164
1165    if (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE)
1166      {
1167         ret = _e_devicemgr_inputgen_mouse_move_event(x, y, identifier);
1168         if (ddata)
1169           {
1170              ddata->mouse.coords.x = x;
1171              ddata->mouse.coords.y = y;
1172           }
1173      }
1174    else
1175      {
1176         state = (type == TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN) ?
1177                 EINA_TRUE : EINA_FALSE;
1178         if (ddata)
1179           {
1180              if (state)  ddata->mouse.pressed |= 1 << (button - 1);
1181              else ddata->mouse.pressed &= ~(1 << (button - 1));
1182              ddata->mouse.coords.x = x;
1183              ddata->mouse.coords.y = y;
1184           }
1185         ret = _e_devicemgr_inputgen_mouse_button_event(state, x, y, button, identifier);
1186      }
1187
1188    return ret;
1189 }
1190
1191 int
1192 e_devicemgr_inputgen_generate_wheel(struct wl_client *client, struct wl_resource *resource, uint32_t type, int32_t value)
1193 {
1194    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
1195    Eina_List *l;
1196    E_Devicemgr_Inputgen_Device_Data *ddata = NULL, *device = NULL;
1197    char *name, *identifier = NULL;
1198
1199    name = _e_devicemgr_inputgen_name_get(resource);
1200
1201    if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_MOUSE))
1202      {
1203         DMWRN("generate is not init\n");
1204         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1205      }
1206
1207    EINA_LIST_FOREACH(e_devicemgr->inputgen.ptr_list, l, ddata)
1208      {
1209         if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
1210           {
1211              device = ddata;
1212              identifier = ddata->identifier;
1213              break;
1214           }
1215      }
1216
1217    if (!identifier)
1218      {
1219         DMWRN("device is not ready\n");
1220         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1221      }
1222
1223    ret = _e_devicemgr_inputgen_mouse_wheel_event(type, value, device);
1224
1225    return ret;
1226 }
1227
1228
1229 int
1230 e_devicemgr_inputgen_generate_touch(struct wl_client *client, struct wl_resource *resource, uint32_t type, uint32_t x, uint32_t y, uint32_t finger)
1231 {
1232    int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
1233    Eina_List *l;
1234    E_Devicemgr_Inputgen_Device_Data *ddata = NULL, *device = NULL;
1235    char *name, *identifier = NULL;
1236
1237    name = _e_devicemgr_inputgen_name_get(resource);
1238
1239    if (finger >= e_input_touch_max_count_get())
1240      {
1241         DMWRN("Invalid fingers: %d\n", finger);
1242         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1243      }
1244
1245    if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_TOUCH))
1246      {
1247         DMWRN("generate is not init\n");
1248         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1249      }
1250
1251    EINA_LIST_FOREACH(e_devicemgr->inputgen.touch_list, l, ddata)
1252      {
1253         if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
1254           {
1255              device = ddata;
1256              identifier = ddata->identifier;
1257              break;
1258           }
1259      }
1260
1261    if (!identifier)
1262      {
1263         DMWRN("device is not ready\n");
1264         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1265      }
1266
1267    switch(type)
1268      {
1269         case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN:
1270            ret = _e_devicemgr_inputgen_touch_update_event(x, y, finger, device);
1271            ret = _e_devicemgr_inputgen_touch_event(type, x, y, finger, device);
1272            if (ddata)
1273              {
1274                 ddata->touch.pressed |= 1 << finger;
1275                 ddata->touch.coords[finger].x = x;
1276                 ddata->touch.coords[finger].y = y;
1277              }
1278            break;
1279         case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END:
1280            ret = _e_devicemgr_inputgen_touch_event(type, x, y, finger, device);
1281            if (ddata)
1282              {
1283                 ddata->touch.pressed &= ~(1 << finger);
1284                 ddata->touch.coords[finger].x = -1;
1285                 ddata->touch.coords[finger].y = -1;
1286              }
1287            break;
1288         case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE:
1289            ret = _e_devicemgr_inputgen_touch_update_event(x, y, finger, device);
1290            if (ddata)
1291              {
1292                 ddata->touch.coords[finger].x = x;
1293                 ddata->touch.coords[finger].y = y;
1294              }
1295            break;
1296      }
1297
1298    return ret;
1299 }
1300
1301 int
1302 e_devicemgr_inputgen_touch_axis_store(struct wl_client *client, struct wl_resource *resource, uint32_t type, double value)
1303 {
1304    Eina_List *l;
1305    E_Devicemgr_Inputgen_Device_Data *ddata = NULL, *device = NULL;
1306    char *name;
1307
1308    name = _e_devicemgr_inputgen_name_get(resource);
1309
1310    if (!_e_devicemgr_inputgen_device_check(name, ECORE_DEVICE_CLASS_TOUCH))
1311      {
1312         DMWRN("generate is not init\n");
1313         return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
1314      }
1315
1316    EINA_LIST_FOREACH(e_devicemgr->inputgen.touch_list, l, ddata)
1317      {
1318         if (!strncmp(ddata->name, name, UINPUT_MAX_NAME_SIZE))
1319           {
1320              device = ddata;
1321              break;
1322           }
1323      }
1324    _e_devicemgr_inputgen_touch_axis_store(device, type, value);
1325
1326    return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
1327 }
1328
1329 void
1330 e_devicemgr_inputgen_get_device_info(E_Devicemgr_Input_Device *dev)
1331 {
1332    E_Devicemgr_Inputgen_Device_Data *ddata;
1333    Eina_List **dev_list, *l;
1334
1335    if (dev->clas == ECORE_DEVICE_CLASS_NONE ||
1336        dev->clas == ECORE_DEVICE_CLASS_SEAT)
1337      return;
1338
1339    dev_list = _e_devicemgr_inputgen_list_get(dev->clas);
1340    EINA_SAFETY_ON_NULL_RETURN(dev_list);
1341
1342    EINA_LIST_FOREACH(*dev_list, l, ddata)
1343      {
1344         if (e_devicemgr_strcmp(ddata->name, dev->name))
1345           {
1346              E_FREE(ddata->identifier);
1347              if (dev->identifier) ddata->identifier = strdup(dev->identifier);
1348              return;
1349           }
1350      }
1351 }
1352
1353
1354 #define DM_IOCTL_SET_BIT(fd, bit, val) \
1355     ret = ioctl(fd, bit, val); \
1356     if (ret) DMWRN("Failed to set %s to fd(%d) (ret: %d)\n", #val, fd, ret)
1357
1358 int
1359 e_devicemgr_create_virtual_device(Ecore_Device_Class clas, const char *name)
1360 {
1361    int ret;
1362    int uinp_fd = -1;
1363    struct uinput_user_dev uinp;
1364
1365    memset(&uinp, 0, sizeof(uinp));
1366    strncpy(uinp.name, name, UINPUT_MAX_NAME_SIZE - 1);
1367    uinp.id.version = 4;
1368    uinp.id.bustype = BUS_VIRTUAL;
1369
1370    uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
1371    if (uinp_fd < 0)
1372      {
1373         DMWRN("Failed to open /dev/uinput: (%d)\n", uinp_fd);
1374         goto fail_create_device;
1375      }
1376
1377    if (ECORE_DEVICE_CLASS_KEYBOARD == clas)
1378      {
1379        /* key device setup */
1380        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_KEY);
1381        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_SYN);
1382        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_MSC);
1383        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_MSCBIT, MSC_SCAN);
1384        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_KEYBIT, KEY_ESC);
1385      }
1386    else if (ECORE_DEVICE_CLASS_MOUSE == clas)
1387      {
1388        /* mouse device setup */
1389        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_KEY);
1390        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_SYN);
1391        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_MSC);
1392        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_REL);
1393        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_MSCBIT, MSC_SCAN);
1394        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_KEYBIT, BTN_LEFT);
1395        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, BTN_RIGHT);
1396        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, BTN_MIDDLE);
1397        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, REL_X);
1398        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, REL_Y);
1399        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, REL_WHEEL);
1400        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_RELBIT, REL_HWHEEL);
1401      }
1402    else if (ECORE_DEVICE_CLASS_TOUCH == clas)
1403      {
1404        /* touch device setup */
1405        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_KEY);
1406        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_SYN);
1407        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_MSC);
1408        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_EVBIT, EV_ABS);
1409
1410        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_KEYBIT, BTN_TOUCH);
1411        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_X);
1412        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_Y);
1413        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_SLOT);
1414        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);
1415        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MINOR);
1416        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_WIDTH_MAJOR);
1417        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_POSITION_X);
1418        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
1419        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
1420        DM_IOCTL_SET_BIT(uinp_fd, UI_SET_MSCBIT, MSC_SCAN);
1421
1422        uinp.absmin[ABS_X] = 0;
1423        uinp.absmax[ABS_X] = 1000;
1424        uinp.absmin[ABS_Y] = 0;
1425        uinp.absmax[ABS_Y] = 1000;
1426        uinp.absmin[ABS_MT_SLOT] = 0;
1427        if (e_config->configured_max_touch.use)
1428          uinp.absmax[ABS_MT_SLOT] = e_config->configured_max_touch.count - 1;
1429        else
1430          uinp.absmax[ABS_MT_SLOT] = e_input_touch_max_count_get() - 1;
1431        uinp.absmin[ABS_MT_TOUCH_MAJOR] = 0;
1432        uinp.absmax[ABS_MT_TOUCH_MAJOR] = 255;
1433        uinp.absmin[ABS_MT_TOUCH_MINOR] = 0;
1434        uinp.absmax[ABS_MT_TOUCH_MINOR] = 255;
1435        uinp.absmin[ABS_MT_WIDTH_MAJOR] = 0;
1436        uinp.absmax[ABS_MT_WIDTH_MAJOR] = 255;
1437        uinp.absmin[ABS_MT_POSITION_X] = 0;
1438        uinp.absmax[ABS_MT_POSITION_X] = 1000;
1439        uinp.absmin[ABS_MT_POSITION_Y] = 0;
1440        uinp.absmax[ABS_MT_POSITION_Y] = 1000;
1441        uinp.absmin[ABS_MT_TRACKING_ID] = 0;
1442        uinp.absmax[ABS_MT_TRACKING_ID] = 65535;
1443        uinp.absmin[ABS_MT_ORIENTATION] = 0;
1444        uinp.absmax[ABS_MT_ORIENTATION] = 2;
1445      }
1446    else
1447      goto fail_create_device;
1448
1449    ret = write(uinp_fd, &uinp, sizeof(struct uinput_user_dev));
1450
1451    if (ret < 0)
1452      {
1453         DMWRN("Failed to write to uinput fd ! (fd:%d, type:%d, name:%s)\n", uinp_fd, clas, name);
1454         goto fail_create_device;
1455      }
1456
1457    if (ioctl(uinp_fd, UI_DEV_CREATE))
1458      {
1459        DMWRN("Failed to create a virtual device ! (type:%d, name:%s)\n", clas, name);
1460        goto fail_create_device;
1461      }
1462
1463    return uinp_fd;
1464
1465 fail_create_device:
1466
1467    if (uinp_fd >= 0)
1468      close(uinp_fd);
1469
1470    return -1;
1471 }
1472
1473 void
1474 e_devicemgr_destroy_virtual_device(int uinp_fd)
1475 {
1476    int ret;
1477    ret = ioctl(uinp_fd, UI_DEV_DESTROY, NULL);
1478    if (ret) DMWRN("Failed destroy fd: %d (ret: %d)\n", uinp_fd, ret);
1479    close(uinp_fd);
1480 }