From: jeon Date: Tue, 7 Apr 2020 07:09:25 +0000 (+0900) Subject: e_info: add a key generation utility X-Git-Tag: submit/tizen/20200410.010241~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=960ba9a06f589b2d9b952541cbd80ced1de6063a;p=platform%2Fupstream%2Fenlightenment.git e_info: add a key generation utility Change-Id: I6a9887c936be84b816eacf655b9b68d703671e70 --- diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index a5a2b795db..5e060b2ace 100644 --- a/src/bin/Makefile.mk +++ b/src/bin/Makefile.mk @@ -96,7 +96,8 @@ src/bin/e_hwc.h \ src/bin/e_hwc_planes.h \ src/bin/e_hwc_windows.h \ src/bin/e_hwc_window.h \ -src/bin/e_hwc_window_queue.h +src/bin/e_hwc_window_queue.h \ +src/bin/e_info_server_input.h if HAVE_WAYLAND_TBM ENLIGHTENMENTHEADERS += \ @@ -218,6 +219,7 @@ src/bin/e_hwc_planes.c \ src/bin/e_hwc_windows.c \ src/bin/e_hwc_window.c \ src/bin/e_hwc_window_queue.c \ +src/bin/e_info_server_input.c \ $(ENLIGHTENMENTHEADERS) if HAVE_WAYLAND_TBM @@ -342,4 +344,4 @@ PHONIES += e enlightenment install-e install-enlightenment e: $(bin_PROGRAMS) enlightenment: e install-e: install-binPROGRAMS -install-enlightenment: install-e +install-enlightenment: install-e diff --git a/src/bin/e_info_client.c b/src/bin/e_info_client.c index 23145c218d..7988d60995 100644 --- a/src/bin/e_info_client.c +++ b/src/bin/e_info_client.c @@ -5393,6 +5393,250 @@ _e_info_client_proc_screen_record(int argc, char **argv) e_info_client_screen_recorder_run(argc, argv); } +static void +_e_info_client_inputgen_usage(void) +{ + printf(" If you want to generate input events, follow below steps\n"); + printf(" \tinit_device -> generate events (keygen) -> deinit_device\n"); + printf("\n\n"); + printf(" enlightenment_info -init_device\n"); + printf(" \t--node: open a device node (ex> /dev/input/event1)\n"); + printf(" \t--type: create a device by given type (keyboard/mouse/touch)\n"); + printf(" \t\tyou can select one or more types, but currently only keyboard type is supported\n"); + printf(" \t--name: device name want to create. used with --type option (default: E_Info_Device)\n"); + printf("\n"); + printf(" you need to choice either node or type to init device\n"); + printf(" example> enlightenment_info -init_device --node=/dev/input/event1\n"); + printf(" enlightenment_info -init_device --type=keyboard/mouse --name=Test_Device\n"); + printf(" enlightenment_info -init_device --type=keyboard\n"); + printf("\n\n"); + printf(" enlightenment_info -deinit_device\n"); + printf(" example> enlightenment_info -deinit_device\n"); + printf("\n\n"); + printf(" enlightenment_info -keygen\n"); + printf(" \t--name: keyname want to generate\n"); + printf(" \t--code: X keycode want to generate\n"); + printf(" \t--state: key event state want to generate [press/down/1] [release/up/0] (default: Press/Release pair)\n"); + printf("\n"); + printf(" you need to choice either name or code to generate key events\n"); + 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"); +} + +static void +_e_info_client_cb_init_device(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("Init_device 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_init_device\n"); +} + +void +_e_info_client_proc_init_device(int argc, char **argv) +{ + char name[80] = {0, }, node[20] = {0, }; + unsigned int type = 0x0; + char *tmp = NULL, *buf = NULL, *buf_ptr = NULL; + int i; + + if (argc < 3) + { + _e_info_client_inputgen_usage(); + return; + } + + for (i = 2; i < argc; i++) + { + if (!strncmp(argv[i], "--node=", sizeof("--node=") - 1)) + { + tmp = argv[i] + sizeof("--node=") - 1; + strncpy(node, tmp, strlen(tmp)); + type = 0x0; + break; + } + else if (!strncmp(argv[i], "--type=", sizeof("--type=") - 1)) + { + tmp = argv[i] + sizeof("--type=") - 1; + buf = strtok_r(tmp, "/", &buf_ptr); + if (!buf) + { + printf("Please insert correct device type. keyboard/mouse/touch.\n"); + return; + } + while (buf) + { + if (!strncmp(buf, "mouse", sizeof("mouse"))) + { + type |= E_INPUT_SEAT_POINTER; + } + else if (!strncmp(buf, "touch", sizeof("touch"))) + { + type |= E_INPUT_SEAT_TOUCH; + } + else if (!strncmp(buf, "keyboard", sizeof("keyboard"))) + { + type |= E_INPUT_SEAT_KEYBOARD; + } + else + { + printf("Please insert valid device type. keyboard/mouse/touch.\n"); + break; + } + buf = strtok_r(NULL, "/", &buf_ptr); + } + } + else if (!strncmp(argv[i], "--name=", sizeof("--name=") - 1)) + { + tmp = argv[i] + sizeof("--name=") - 1; + strncpy(name, tmp, strlen(tmp)); + } + else + { + _e_info_client_inputgen_usage(); + return; + } + } + + if (!type && node[0] == '\0') + { + printf("Please insert either node or type\n"); + return; + } + else if (type && node[0] != '\0') + { + printf("Please insert only one between node and type\n"); + return; + } + + if (type) + { + if (name[0] == '\0') + snprintf(name, sizeof("E_Info_Device"), "E_Info_Device"); + } + else + { + snprintf(name, sizeof(node), "%s", node); + } + + if (!_e_info_client_eldbus_message_with_args("init_device", _e_info_client_cb_init_device, "us", type, name)) + return; +} + +void +_e_info_client_proc_deinit_device(int argc, char **argv) +{ + if (!_e_info_client_eldbus_message("deinit_device", NULL)) + return; +} + +static void +_e_info_client_cb_keygen(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("Keygen 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_keygen\n"); +} + +void +_e_info_client_proc_keygen(int argc, char **argv) +{ + char name[16] = {0, }; + int state = E_INFO_KEY_STATE_ALL, code = 0, i; + char *tmp = NULL; + + if (argc < 3) + { + _e_info_client_inputgen_usage(); + return; + } + + for (i = 2; i < argc; i++) + { + if (!strncmp(argv[i], "--name=", sizeof("--name=") - 1)) + { + tmp = argv[i] + sizeof("--name=") - 1; + strncpy(name, tmp, strlen(tmp)); + } + else if (!strncmp(argv[i], "--code=", sizeof("--code=") - 1)) + { + tmp = argv[i] + sizeof("--code=") - 1; + code = atoi(tmp); + } + 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_KEY_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; + } + else + { + printf("Please input correct key state (press/down/1) or (release/up/0)\n"); + return; + } + } + else + { + _e_info_client_inputgen_usage(); + return; + } + } + + if (!code && name[0] == '\0') + { + printf("Please insert either name or code\n"); + return; + } + else if (code && name[0] != '\0') + { + printf("Please insert only one between name and code\n"); + return; + } + + if (!_e_info_client_eldbus_message_with_args("keygen", _e_info_client_cb_keygen, "sii", name, code, state)) + return; +} + + + typedef struct _ProcInfo { const char *option; @@ -5732,9 +5976,32 @@ static ProcInfo procs_to_execute[] = }, }; +ProcInfo procs_to_input[] = +{ + { + "init_device", /* Option */ + NULL,/* Params */ + "Initialize input device", /* Description */ + _e_info_client_proc_init_device /* func */ + }, + { + "deinit_device", /* Option */ + NULL,/* Params */ + "Deinitialize input device", /* Description */ + _e_info_client_proc_deinit_device /* func */ + }, + { + "keygen", /* Option */ + NULL,/* Params */ + "Generate key events", /* Description */ + _e_info_client_proc_keygen /* func */ + }, +}; + static Eina_List *list_tracelogs = NULL; static Eina_List *list_printinfo = NULL; static Eina_List *list_exec= NULL; +static Eina_List *list_input = NULL; static int _util_sort_string_cb(const void *data1, const void *data2) @@ -5756,13 +6023,14 @@ _e_info_client_shutdown_list(void) list_tracelogs = eina_list_free(list_tracelogs); list_printinfo = eina_list_free(list_printinfo); list_exec = eina_list_free(list_exec); + list_input = eina_list_free(list_input); } static void _e_info_client_init_list(void) { int n_info = 0, i; - list_tracelogs = list_printinfo = list_exec = NULL; + list_tracelogs = list_printinfo = list_exec = list_input = NULL; n_info = sizeof(procs_to_tracelogs) / sizeof(procs_to_tracelogs[0]); for (i = 0; i < n_info; i++) @@ -5783,6 +6051,13 @@ _e_info_client_init_list(void) list_exec = eina_list_append(list_exec, &procs_to_execute[i]); } list_exec = eina_list_sort(list_exec, eina_list_count(list_exec), _util_sort_string_cb); + + n_info = sizeof(procs_to_input) / sizeof(procs_to_input[0]); + for (i = 0; i < n_info; i++) + { + list_input = eina_list_append(list_input, &procs_to_input[i]); + } + list_input = eina_list_sort(list_input, eina_list_count(list_input), _util_sort_string_cb); } static void @@ -5932,6 +6207,19 @@ _e_info_client_process(int argc, char **argv) } } + EINA_LIST_FOREACH(list_input, l, procinfo) + { + proc_option_length = strlen(procinfo->option); + if (argv_len != proc_option_length) continue; + if (!strncmp(argv[1]+1, procinfo->option, proc_option_length)) + { + if (procinfo->func) + procinfo->func(argc, argv); + + return EINA_TRUE; + } + } + return EINA_FALSE; } @@ -5956,6 +6244,11 @@ _e_info_client_print_usage_all(const char *exec) { printf(" %s -%s %s\n", exec, procinfo->option, (procinfo->params)?procinfo->params:""); } + printf("\n\n"); + EINA_LIST_FOREACH(list_input, l, procinfo) + { + printf(" %s -%s %s\n", exec, procinfo->option, (procinfo->params)?procinfo->params:""); + } } static void @@ -6002,6 +6295,18 @@ _e_info_client_print_usage(int argc, char **argv) } } + EINA_LIST_FOREACH(list_input, l, procinfo) + { + optlen = strlen(procinfo->option); + if (arglen != optlen) continue; + if (!strncmp(argv[1]+1, procinfo->option, optlen)) + { + printf(" %s\n\n", (procinfo->description)?procinfo->description:""); + printf(" %s -%s %s\n", argv[0], procinfo->option, (procinfo->params)?procinfo->params:""); + goto end; + } + } + end: printf("\n"); } @@ -6031,6 +6336,12 @@ _e_info_client_print_description(const char *exec) printf(" -%-30s\t", procinfo->option); printf(": %s\n", (procinfo->description)?procinfo->description:""); } + printf("\n"); + EINA_LIST_FOREACH(list_input, l, procinfo) + { + printf(" -%-30s\t", procinfo->option); + printf(": %s\n", (procinfo->description)?procinfo->description:""); + } printf("\n"); } diff --git a/src/bin/e_info_server.c b/src/bin/e_info_server.c index 29967a86b3..e09874c735 100644 --- a/src/bin/e_info_server.c +++ b/src/bin/e_info_server.c @@ -9,6 +9,7 @@ #include "e_info_protocol.h" #include #include "e_comp_object.h" +#include "e_info_server_input.h" #define EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT #include @@ -6276,6 +6277,61 @@ _e_info_server_cb_focus_history(const Eldbus_Service_Interface *iface EINA_UNUSE return reply; } +static Eldbus_Message * +_e_info_server_cb_init_device(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) +{ + Eldbus_Message *reply; + char *name = NULL, *result = NULL; + unsigned int type = 0x0; + + if (!eldbus_message_arguments_get(msg, "us", &type, &name)) + { + return eldbus_message_error_new(msg, "InputUtilFailed", + "input: an attempt to excute input util from method call message failed"); + } + + result = e_info_server_input_init_device(type, name); + + reply = eldbus_message_method_return_new(msg); + + eldbus_message_arguments_append(reply, "s", result); + + return reply; +} + +static Eldbus_Message * +_e_info_server_cb_deinit_device(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) +{ + Eldbus_Message *reply; + + e_info_server_input_deinit_device(); + + reply = eldbus_message_method_return_new(msg); + + return reply; +} + +static Eldbus_Message * +_e_info_server_cb_keygen(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) +{ + Eldbus_Message *reply; + char *name = NULL, *result = NULL; + int code = 0, state = 0; + + if (!eldbus_message_arguments_get(msg, "sii", &name, &code, &state)) + { + return eldbus_message_error_new(msg, "KeygenFailed", + "keygen: an attempt to generate key event from method call message failed"); + } + + result = e_info_server_input_keygen(name, code, state); + reply = eldbus_message_method_return_new(msg); + + eldbus_message_arguments_append(reply, "s", result); + + return reply; +} + //{ "method_name", arguments_from_client, return_values_to_client, _method_cb, ELDBUS_METHOD_FLAG }, static const Eldbus_Method methods[] = { { "get_window_info", NULL, ELDBUS_ARGS({"iiiiisiiiiia("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_window_info_get, 0 }, @@ -6348,6 +6404,9 @@ static const Eldbus_Method methods[] = { { "screen_info", ELDBUS_ARGS({"i", "option"}), ELDBUS_ARGS({"as", "screen info"}), _e_info_server_cb_screen_info_get, 0 }, { "focus_policy_ext_set", ELDBUS_ARGS({"i", "option"}), ELDBUS_ARGS({"i", "result"}), _e_info_server_cb_focus_policy_ext_set, 0 }, { "focus_history", NULL, ELDBUS_ARGS({"a(ubbbs)", "history array"}), _e_info_server_cb_focus_history, 0 }, + { "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}, { NULL, NULL, NULL, NULL, 0 } }; diff --git a/src/bin/e_info_server_input.c b/src/bin/e_info_server_input.c new file mode 100644 index 0000000000..08f73bba5b --- /dev/null +++ b/src/bin/e_info_server_input.c @@ -0,0 +1,236 @@ +#include "e.h" +#include "e_info_server_input.h" +#include "e_info_shared_types.h" + +#include + +typedef struct _E_Info_Server_Input +{ + struct + { + Eina_Bool virtual_dev; + int fd; + } gen; +} E_Info_Server_Input; + +static E_Info_Server_Input _e_info_input = +{ + { + EINA_FALSE, /* virtual_dev */ + -1 /* fd */ + } +}; + + +static int +_e_info_input_keygen_create_device(const char *dev_name) +{ + int fd_uinput = -1, nwrite = 0, i; + struct uinput_user_dev dev_uinput = {0, }; + + fd_uinput = open("/dev/uinput", O_WRONLY | O_NDELAY); + EINA_SAFETY_ON_FALSE_RETURN_VAL(fd_uinput >= 0, -1); + + 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); + + for (i = KEY_ESC; i <= KEY_MAX; i++) + ioctl(fd_uinput, UI_SET_KEYBIT, i); + + ioctl(fd_uinput, UI_SET_MSCBIT, MSC_SCAN); + + /* 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_keygen_open_device(char *identifier) +{ + int fd = -1; + + fd = open(identifier, O_WRONLY | O_NDELAY); + if (fd < 0) + { + ERR("Failed to open %s node.\n", identifier); + return -1; + } + + return fd; +} + +static int +_write_event_to_device_node(int type, int code, int value) +{ + int nwrite; + struct input_event ev; + + gettimeofday(&ev.time, NULL); + + ev.type = type; + ev.code = code; + ev.value = value; + + nwrite = write(_e_info_input.gen.fd, &ev, sizeof(ev)); + return nwrite; +} + +static void +_key_gen(int keycode, int value) +{ + _write_event_to_device_node(EV_KEY, keycode, value); +} + +static void +_sync_gen(void) +{ + _write_event_to_device_node(EV_SYN, 0, 0); +} + +static void +_key_gen_down(int key_code) +{ + _key_gen(key_code, 1); + _sync_gen(); +} + +static void +_key_gen_up(int key_code) +{ + _key_gen(key_code, 0); + _sync_gen(); +} + +static void +_e_info_input_keygen(int key_code, int key_state) +{ + switch (key_state) + { + case E_INFO_KEY_STATE_PRESS: + _key_gen_down(key_code); + break; + case E_INFO_KEY_STATE_RELEASE: + _key_gen_up(key_code); + break; + case E_INFO_KEY_STATE_ALL: + _key_gen_down(key_code); + _key_gen_up(key_code); + break; + default: + return; + } +} + +static void +_e_info_input_keygen_close_device(void) +{ + int ret; + + if (_e_info_input.gen.virtual_dev) + { + ret = ioctl(_e_info_input.gen.fd, UI_DEV_DESTROY, NULL); + if (ret) WRN("Failed destroy fd: %d (ret: %d)\n", _e_info_input.gen.fd, ret); + } + close(_e_info_input.gen.fd); + + _e_info_input.gen.fd = -1; + _e_info_input.gen.virtual_dev = EINA_FALSE; +} + +char * +e_info_server_input_init_device(unsigned int type, char *name) +{ + int fd = -1; + Eina_List *device_list, *l; + Ecore_Device *dev; + + if (_e_info_input.gen.fd >=0) return "Already opened device is exist"; + if (type) + { + if (type & E_INPUT_SEAT_KEYBOARD) + { + fd = _e_info_input_keygen_create_device(name); + _e_info_input.gen.virtual_dev = EINA_TRUE; + _e_info_input.gen.fd = fd; + } + else + { + WRN("Currently only keyboard is supported.\n"); + } + } + else + { + device_list = (Eina_List *)ecore_device_list(); + EINA_SAFETY_ON_NULL_RETURN_VAL(device_list, "No Opened device"); + + 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); + _e_info_input.gen.virtual_dev = EINA_FALSE; + _e_info_input.gen.fd = fd; + } + } + } + + if (fd < 0) + { + _e_info_input.gen.virtual_dev = EINA_FALSE; + _e_info_input.gen.fd = -1; + return "Failed to open event node or uinput node"; + } + + return E_INFO_INPUT_RESULT_NONE; +} + +void +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(); + else + { + close(_e_info_input.gen.fd); + + _e_info_input.gen.fd = -1; + _e_info_input.gen.virtual_dev = EINA_FALSE; + } + + return; +} + +char +*e_info_server_input_keygen(char *name, int code, int state) +{ + if (_e_info_input.gen.fd < 0) return "Initialize device first"; + + if (strlen(name) > 0) + { + code = e_comp_wl_input_keymap_keyname_to_keycode(name) - 8; + } + else + code = code - 8; + + _e_info_input_keygen(code, state); + + return E_INFO_INPUT_RESULT_NONE; +} diff --git a/src/bin/e_info_server_input.h b/src/bin/e_info_server_input.h new file mode 100644 index 0000000000..0a0484bd9d --- /dev/null +++ b/src/bin/e_info_server_input.h @@ -0,0 +1,10 @@ +#ifndef E_INFO_CLIENT_SCREEN_RECORDER_H +#define E_INFO_CLIENT_INPUT_H + +#define INPUT_ARG_NAME "input" + +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); + +#endif diff --git a/src/bin/e_info_shared_types.h b/src/bin/e_info_shared_types.h index 5b65e3ec71..f1a1ed4a4f 100644 --- a/src/bin/e_info_shared_types.h +++ b/src/bin/e_info_shared_types.h @@ -285,4 +285,13 @@ typedef enum "Example:\n" \ "\twinfo -screen_info\n" +typedef enum +{ + E_INFO_KEY_STATE_RELEASE = 0, + E_INFO_KEY_STATE_PRESS, + E_INFO_KEY_STATE_ALL +} E_Info_Key_State; + +#define E_INFO_INPUT_RESULT_NONE "None" + #endif /* end of _E_INFO_SHARED_TYPES_ */