e_info: add a touch generation utility 23/231123/6
authorjeon <jhyuni.kang@samsung.com>
Fri, 17 Apr 2020 09:17:38 +0000 (18:17 +0900)
committerjeon <jhyuni.kang@samsung.com>
Wed, 22 Apr 2020 05:53:38 +0000 (14:53 +0900)
Change-Id: I1095be1687cf8141d00ff6c2e589b1eb81623969

src/bin/e_info_client.c
src/bin/e_info_server.c
src/bin/e_info_server_input.c
src/bin/e_info_server_input.h
src/bin/e_info_shared_types.h

index 62c295aac27332a301dc3ddadb1e89c369b88e21..8ce6e134eac0eaa1d3a7596dc7ea75adba0b8a2b 100644 (file)
@@ -5553,6 +5553,16 @@ _e_info_client_inputgen_usage(void)
    printf("  example> enlightenment_info -keygen --name=XF86Back\n");
    printf("           enlightenment_info -keygen --code=166 --state=down\n");
    printf("           enlightenment_info -keygen --name=XF86Back --state=0\n");
+   printf("\n\n");
+   printf("  enlightenment_info -touchgen\n");
+   printf("  \t--idx: touch index want to generate (default: 0)\n");
+   printf("  \t--axis: touch axis want to generate\n");
+   printf("  \t--state: touch event state want to generate [press/down/1] [release/up/0] [motion/move/2] (default: Press/Motion/Release pair)\n");
+   printf("\n");
+   printf("  you need to input axis information to generate touch events\n");
+   printf("  example> enlightenment_info -touchgen --axis=100,200\n");
+   printf("           enlightenment_info -touchgen --idx=1 --axis=200,300\n");
+   printf("           enlightenment_info -touchgen --idx=0 --axis=300,100 --state=down\n");
    printf("\n");
 }
 
@@ -5702,7 +5712,7 @@ void
 _e_info_client_proc_keygen(int argc, char **argv)
 {
    char name[16] = {0, };
-   int state = E_INFO_KEY_STATE_ALL, code = 0, i;
+   int state = E_INFO_EVENT_STATE_ALL, code = 0, i;
    char *tmp = NULL;
 
    if (argc < 3)
@@ -5730,13 +5740,13 @@ _e_info_client_proc_keygen(int argc, char **argv)
                  !strncmp(tmp, "down", sizeof("down")) ||
                  !strncmp(tmp, "1", sizeof("1")))
                {
-                  state = E_INFO_KEY_STATE_PRESS;
+                  state = E_INFO_EVENT_STATE_PRESS;
                }
              else if (!strncmp(tmp, "release", sizeof("release")) ||
                       !strncmp(tmp, "up", sizeof("up")) ||
                       !strncmp(tmp, "0", sizeof("0")))
                {
-                  state = E_INFO_KEY_STATE_RELEASE;
+                  state = E_INFO_EVENT_STATE_RELEASE;
                }
              else
                {
@@ -5766,6 +5776,115 @@ _e_info_client_proc_keygen(int argc, char **argv)
      return;
 }
 
+static void
+_e_info_client_cb_touchgen(const Eldbus_Message *msg)
+{
+   const char *errname = NULL, *errtext = NULL;
+   char *result = NULL;
+
+   EINA_SAFETY_ON_TRUE_GOTO(eldbus_message_error_get(msg, &errname, &errtext), err);
+
+   EINA_SAFETY_ON_FALSE_GOTO(eldbus_message_arguments_get(msg, "s", &result), err);
+
+   if (strncmp(result, E_INFO_INPUT_RESULT_NONE, sizeof(E_INFO_INPUT_RESULT_NONE)))
+     printf("Touchgen Failed: %s\n", result);
+
+   return;
+
+err:
+   if(errname || errtext)
+     printf("errname : %s, errmsg : %s\n", errname, errtext);
+   else
+     printf("Error occurred in _e_info_client_cb_touchgen\n");
+}
+
+void
+_e_info_client_proc_touchgen(int argc, char **argv)
+{
+   char name[16] = {0, };
+   int state = E_INFO_EVENT_STATE_ALL, idx = 0, x = -1, y = -1, cnt = 0, i;
+   char *tmp = NULL, *buf = NULL, *buf_ptr = NULL;
+
+   if (argc < 3)
+     {
+        _e_info_client_inputgen_usage();
+        return;
+     }
+
+   for (i = 2; i < argc; i++)
+     {
+        if (!strncmp(argv[i], "--idx=", sizeof("--idx=") - 1))
+          {
+             tmp = argv[i] + sizeof("--idx=") - 1;
+             idx = atoi(tmp);
+          }
+        else if (!strncmp(argv[i], "--axis=", sizeof("--axis=") - 1))
+          {
+             tmp = argv[i] + sizeof("--axis=") - 1;
+             buf = strtok_r(tmp, ",", &buf_ptr);
+             if (!buf)
+               {
+                  printf("Please insert correct axis. --axis=100,200\n");
+                  return;
+               }
+             while (buf)
+               {
+                  if (cnt == 0) x = atoi(buf);
+                  else if (cnt == 1) y = atoi(buf);
+                  else
+                    {
+                       printf("Please insert valid axis. --axis=100,200\n");
+                       return;
+                    }
+                  buf = strtok_r(NULL, ",", &buf_ptr);
+                  cnt++;
+               }
+          }
+        else if (!strncmp(argv[i], "--state=", sizeof("--state=") - 1))
+          {
+             tmp = argv[i] + sizeof("--state=") - 1;
+             if (!strncmp(tmp, "press", sizeof("press")) ||
+                 !strncmp(tmp, "down", sizeof("down")) ||
+                 !strncmp(tmp, "1", sizeof("1")))
+               {
+                  state = E_INFO_EVENT_STATE_PRESS;
+               }
+             else if (!strncmp(tmp, "release", sizeof("release")) ||
+                      !strncmp(tmp, "up", sizeof("up")) ||
+                      !strncmp(tmp, "0", sizeof("0")))
+               {
+                  state = E_INFO_EVENT_STATE_RELEASE;
+               }
+             else if (!strncmp(tmp, "motion", sizeof("motion")) ||
+                      !strncmp(tmp, "move", sizeof("move")) ||
+                      !strncmp(tmp, "2", sizeof("2")))
+               {
+                  state = E_INFO_EVENT_STATE_MOTION;
+               }
+             else
+               {
+                  printf("Please input correct key state (press/down/1) or (release/up/0)\n");
+                  return;
+               }
+          }
+        else
+          {
+             _e_info_client_inputgen_usage();
+             return;
+          }
+     }
+
+   if ((x < 0) || (y < 0))
+     {
+        printf("Please insert correct axis values (greater than 0)\n");
+        return;
+     }
+
+   if (!_e_info_client_eldbus_message_with_args("touchgen", _e_info_client_cb_touchgen, "iiii", idx, x, y, state))
+     return;
+}
+
+
 static void
 _e_info_client_cb_filter(const Eldbus_Message *msg)
 {
@@ -6223,6 +6342,12 @@ ProcInfo procs_to_input[] =
       "Generate key events", /* Description */
       _e_info_client_proc_keygen /* func */
    },
+   {
+      "touchgen",      /* Option */
+      NULL,/* Params */
+      "Generate touch events", /* Description */
+      _e_info_client_proc_touchgen /* func */
+   },
 };
 
 static Eina_List *list_tracelogs = NULL;
index bbe1d0ce489b699b608db98ea7b9cc08586b70f3..beb65320cb70b474b2bf95500741063366e14ba6 100644 (file)
@@ -6650,6 +6650,27 @@ _e_info_server_cb_keygen(const Eldbus_Service_Interface *iface EINA_UNUSED, cons
    return reply;
 }
 
+static Eldbus_Message *
+_e_info_server_cb_touchgen(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+   Eldbus_Message *reply;
+   char *result = NULL;
+   int idx = 0, x = -1, y = -1, state = 0;
+
+   if (!eldbus_message_arguments_get(msg, "iiii", &idx, &x, &y, &state))
+     {
+        return eldbus_message_error_new(msg, "TouchgenFailed",
+                                        "toutgen: an attempt to generate touch event from method call message failed");
+     }
+
+   result = e_info_server_input_touchgen(idx, x, y, state);
+   reply = eldbus_message_method_return_new(msg);
+
+   eldbus_message_arguments_append(reply, "s", result);
+
+   return reply;
+}
+
 static Eldbus_Message *
 _e_info_server_cb_filter(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
 {
@@ -6868,6 +6889,7 @@ static const Eldbus_Method methods[] = {
    { "init_device", ELDBUS_ARGS({"us", "device information"}), ELDBUS_ARGS({"s", "result message"}), _e_info_server_cb_init_device, 0},
    { "deinit_device", NULL, NULL, _e_info_server_cb_deinit_device, 0},
    { "keygen", ELDBUS_ARGS({"sii", "key information"}), ELDBUS_ARGS({"s", "result message"}), _e_info_server_cb_keygen, 0},
+   { "touchgen", ELDBUS_ARGS({"iiii", "touch information"}), ELDBUS_ARGS({"s", "result message"}), _e_info_server_cb_touchgen, 0},
    { "filter", ELDBUS_ARGS({"sis", "win_id, on(1)/off(0), filter name"}), ELDBUS_ARGS({"s", "result of request"}), _e_info_server_cb_filter, 0},
    { NULL, NULL, NULL, NULL, 0 }
 };
index 08f73bba5bd12ffe2393baf8508ed472c8061d1f..cd7cd677cded20afb6bcc68011e55eb7e8309b73 100644 (file)
@@ -23,7 +23,7 @@ static E_Info_Server_Input _e_info_input =
 
 
 static int
-_e_info_input_keygen_create_device(const char *dev_name)
+_e_info_input_create_keyboard_device(const char *dev_name)
 {
    int fd_uinput = -1, nwrite = 0, i;
    struct uinput_user_dev dev_uinput = {0, };
@@ -59,7 +59,82 @@ _e_info_input_keygen_create_device(const char *dev_name)
 }
 
 static int
-_e_info_input_keygen_open_device(char *identifier)
+_e_info_input_create_touch_device(const char *dev_name)
+{
+   int fd_uinput = -1, nwrite = 0;
+   struct uinput_user_dev dev_uinput = {0, };
+   E_Output *output;
+   int w = 0, h = 0;
+
+   fd_uinput = open("/dev/uinput", O_WRONLY | O_NDELAY);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(fd_uinput >= 0, -1);
+
+   output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+   e_output_size_get(output, &w, &h);
+
+   if (w <= 0) w = 4096;
+   if (h <= 0) h = 4096;
+
+   WRN("Failed to get output size for creating touch device in e_info. So set arbitrary output size [%d x %d]\n", w, h);
+
+   strncpy(dev_uinput.name, dev_name, UINPUT_MAX_NAME_SIZE - 1);
+   dev_uinput.id.version = 4;
+   dev_uinput.id.bustype = BUS_VIRTUAL;
+
+   ioctl(fd_uinput, UI_SET_EVBIT, EV_KEY);
+   ioctl(fd_uinput, UI_SET_EVBIT, EV_SYN);
+   ioctl(fd_uinput, UI_SET_EVBIT, EV_MSC);
+   ioctl(fd_uinput, UI_SET_EVBIT, EV_ABS);
+
+   ioctl(fd_uinput, UI_SET_KEYBIT, BTN_TOUCH);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_X);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_Y);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_MT_SLOT);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_MT_TOUCH_MINOR);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_MT_WIDTH_MAJOR);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_MT_POSITION_X);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
+   ioctl(fd_uinput, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
+   ioctl(fd_uinput, UI_SET_MSCBIT, MSC_SCAN);
+
+   dev_uinput.absmin[ABS_X] = 0;
+   dev_uinput.absmax[ABS_X] = w - 1;
+   dev_uinput.absmin[ABS_Y] = 0;
+   dev_uinput.absmax[ABS_Y] = h - 1;
+   dev_uinput.absmin[ABS_MT_SLOT] = 0;
+   dev_uinput.absmax[ABS_MT_SLOT] = 9;
+   dev_uinput.absmin[ABS_MT_TOUCH_MAJOR] = 0;
+   dev_uinput.absmax[ABS_MT_TOUCH_MAJOR] = 255;
+   dev_uinput.absmin[ABS_MT_TOUCH_MINOR] = 0;
+   dev_uinput.absmax[ABS_MT_TOUCH_MINOR] = 255;
+   dev_uinput.absmin[ABS_MT_WIDTH_MAJOR] = 0;
+   dev_uinput.absmax[ABS_MT_WIDTH_MAJOR] = 255;
+   dev_uinput.absmin[ABS_MT_POSITION_X] = 0;
+   dev_uinput.absmax[ABS_MT_POSITION_X] = w - 1;
+   dev_uinput.absmin[ABS_MT_POSITION_Y] = 0;
+   dev_uinput.absmax[ABS_MT_POSITION_Y] = h - 1;
+   dev_uinput.absmin[ABS_MT_TRACKING_ID] = 0;
+   dev_uinput.absmax[ABS_MT_TRACKING_ID] = 65535;
+   dev_uinput.absmin[ABS_MT_ORIENTATION] = 0;
+   dev_uinput.absmax[ABS_MT_ORIENTATION] = 2;
+
+   /* Create input device into input sub-system */
+   nwrite = write(fd_uinput, &dev_uinput, sizeof(dev_uinput));
+   if (nwrite < 0) WRN("Failed to write for create device using uinput\n");
+
+   if (ioctl(fd_uinput, UI_DEV_CREATE))
+     {
+        WRN("Failed to create device(%s).", dev_name);
+        close (fd_uinput);
+        return -1;
+     }
+
+   return fd_uinput;
+}
+
+static int
+_e_info_input_open_device(char *identifier)
 {
    int fd = -1;
 
@@ -115,18 +190,90 @@ _key_gen_up(int key_code)
    _sync_gen();
 }
 
+static void
+_touch_gen_mt_slot(int value)
+{
+   _write_event_to_device_node(EV_ABS, ABS_MT_SLOT, value);
+}
+
+static void
+_touch_gen_mt_tracking_id(int value)
+{
+   _write_event_to_device_node(EV_ABS, ABS_MT_TRACKING_ID, value);
+}
+
+static void
+_touch_gen_mt_touch_major(int value)
+{
+   _write_event_to_device_node(EV_ABS, ABS_MT_TOUCH_MAJOR, value);
+}
+
+static void
+_touch_gen_mt_touch_minor(int value)
+{
+   _write_event_to_device_node(EV_ABS, ABS_MT_TOUCH_MINOR, value);
+}
+
+static void
+_touch_gen_mt_position_x(int value)
+{
+   _write_event_to_device_node(EV_ABS, ABS_MT_POSITION_X, value);
+}
+
+static void
+_touch_gen_mt_position_y(int value)
+{
+   _write_event_to_device_node(EV_ABS, ABS_MT_POSITION_Y, value);
+}
+
+static void
+_touch_gen_down(int idx, int x, int y)
+{
+#define MAX_TRACKING_ID 65535
+   static int tracking_id = 0;
+
+   _touch_gen_mt_slot(idx);
+   _touch_gen_mt_tracking_id(tracking_id);
+   tracking_id++;
+   if (tracking_id > MAX_TRACKING_ID)
+     tracking_id = 0;
+
+   _touch_gen_mt_touch_major(10);
+   _touch_gen_mt_touch_minor(5);
+   _touch_gen_mt_position_x(x);
+   _touch_gen_mt_position_y(y);
+   _sync_gen();
+}
+
+static void
+_touch_gen_move(int idx, int x, int y)
+{
+   _touch_gen_mt_slot(idx);
+   _touch_gen_mt_position_x(x);
+   _touch_gen_mt_position_y(y);
+   _sync_gen();
+}
+
+static void
+_touch_gen_up(int idx)
+{
+   _touch_gen_mt_slot(idx);
+   _touch_gen_mt_tracking_id(-1);
+   _sync_gen();
+}
+
 static void
 _e_info_input_keygen(int key_code, int key_state)
 {
    switch (key_state)
      {
-        case E_INFO_KEY_STATE_PRESS:
+        case E_INFO_EVENT_STATE_PRESS:
           _key_gen_down(key_code);
           break;
-        case E_INFO_KEY_STATE_RELEASE:
+        case E_INFO_EVENT_STATE_RELEASE:
           _key_gen_up(key_code);
           break;
-        case E_INFO_KEY_STATE_ALL:
+        case E_INFO_EVENT_STATE_ALL:
           _key_gen_down(key_code);
           _key_gen_up(key_code);
           break;
@@ -136,7 +283,32 @@ _e_info_input_keygen(int key_code, int key_state)
 }
 
 static void
-_e_info_input_keygen_close_device(void)
+_e_info_input_touchgen(int idx, int x, int y, int touch_state)
+{
+   switch (touch_state)
+     {
+        case E_INFO_EVENT_STATE_PRESS:
+          _touch_gen_down(idx, x, y);
+          break;
+        case E_INFO_EVENT_STATE_RELEASE:
+          _touch_gen_up(idx);
+          break;
+        case E_INFO_EVENT_STATE_MOTION:
+          _touch_gen_move(idx, x, y);
+          break;
+        case E_INFO_EVENT_STATE_ALL:
+          _touch_gen_down(idx, x, y);
+          _touch_gen_move(idx, x, y);
+          _touch_gen_up(idx);
+          break;
+        default:
+          return;
+     }
+}
+
+
+static void
+_e_info_input_close_device(void)
 {
    int ret;
 
@@ -163,13 +335,15 @@ e_info_server_input_init_device(unsigned int type, char *name)
      {
         if (type & E_INPUT_SEAT_KEYBOARD)
           {
-             fd = _e_info_input_keygen_create_device(name);
+             fd = _e_info_input_create_keyboard_device(name);
              _e_info_input.gen.virtual_dev = EINA_TRUE;
              _e_info_input.gen.fd = fd;
           }
-        else
+        if (type & E_INPUT_SEAT_TOUCH)
           {
-             WRN("Currently only keyboard is supported.\n");
+             fd = _e_info_input_create_touch_device(name);
+             _e_info_input.gen.virtual_dev = EINA_TRUE;
+             _e_info_input.gen.fd = fd;
           }
      }
    else
@@ -179,11 +353,9 @@ e_info_server_input_init_device(unsigned int type, char *name)
 
         EINA_LIST_FOREACH(device_list, l, dev)
           {
-             if (ecore_device_class_get(dev) != ECORE_DEVICE_CLASS_KEYBOARD)
-               continue;
              if (!e_util_strcmp(name, ecore_device_identifier_get(dev)))
                {
-                  fd = _e_info_input_keygen_open_device(name);
+                  fd = _e_info_input_open_device(name);
                   _e_info_input.gen.virtual_dev = EINA_FALSE;
                   _e_info_input.gen.fd = fd;
                }
@@ -206,7 +378,7 @@ e_info_server_input_deinit_device(void)
    if (_e_info_input.gen.fd < 0) return;
 
    if (_e_info_input.gen.virtual_dev)
-     _e_info_input_keygen_close_device();
+     _e_info_input_close_device();
    else
      {
         close(_e_info_input.gen.fd);
@@ -218,8 +390,8 @@ e_info_server_input_deinit_device(void)
    return;
 }
 
-char 
-*e_info_server_input_keygen(char *name, int code, int state)
+char *
+e_info_server_input_keygen(char *name, int code, int state)
 {
    if (_e_info_input.gen.fd < 0) return "Initialize device first";
 
@@ -234,3 +406,14 @@ char
 
    return E_INFO_INPUT_RESULT_NONE;
 }
+
+char *
+e_info_server_input_touchgen(int idx, int x, int y, int state)
+{
+   if (_e_info_input.gen.fd < 0) return "Initialize device first";
+
+   _e_info_input_touchgen(idx, x, y, state);
+
+   return E_INFO_INPUT_RESULT_NONE;
+}
+
index 0a0484bd9d7e385a3483ea1eff0276f16791f5f3..3cc8ea140a098e4d94cd0e89d4b754b5856072a8 100644 (file)
@@ -6,5 +6,6 @@
 char *e_info_server_input_init_device(unsigned int type, char *name);
 void e_info_server_input_deinit_device(void);
 char *e_info_server_input_keygen(char *name, int code, int state);
+char *e_info_server_input_touchgen(int idx, int x, int y, int state);
 
 #endif
index bd662f077a1b1baaaa41b0194b4d6b2662bf0067..0349a5bb824b5eb5289cea2808c9cc9aca14aa87 100644 (file)
@@ -285,12 +285,17 @@ typedef enum
    "Example:\n"                                                                \
    "\twinfo -screen_info\n"
 
+/* -------------------------------------------------------------------------- */
+/* INPUT GENERATION                                                           */
+/* -------------------------------------------------------------------------- */
+
 typedef enum
 {
-   E_INFO_KEY_STATE_RELEASE = 0,
-   E_INFO_KEY_STATE_PRESS,
-   E_INFO_KEY_STATE_ALL
-} E_Info_Key_State;
+   E_INFO_EVENT_STATE_RELEASE = 0,
+   E_INFO_EVENT_STATE_PRESS,
+   E_INFO_EVENT_STATE_MOTION,
+   E_INFO_EVENT_STATE_ALL
+} E_Info_Event_State;
 
 #define E_INFO_INPUT_RESULT_NONE "None"