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