#include #include #include #include #include #include #include #include #include #include #include "config.h" static struct termios original_term; const char * key_names[256] = { 0 }; static int repeat_counters[256] = { 1 }; static int current_repeat_key = 0; static int line_lock = -1; enum KEY_STATUS { KEY_RELEASE = 0, KEY_PRESS = 1, KEY_REPEAT = 2 }; void usage() { printf("Usage: %s .\n", PROGRAM_NAME); } void version() { printf("%s (v%s)\n", PROGRAM_FULL_NAME, PROGRAM_VERSION); printf("%s\n", PROGRAM_AUTHORS); } void init_key_names() { key_names[KEY_RESERVED] = "KEY_RESERVED"; key_names[KEY_Q] = "Q"; key_names[KEY_W] = "W"; key_names[KEY_E] = "E"; key_names[KEY_R] = "R"; key_names[KEY_T] = "T"; key_names[KEY_Y] = "Y"; key_names[KEY_U] = "U"; key_names[KEY_I] = "I"; key_names[KEY_O] = "O"; key_names[KEY_P] = "P"; key_names[KEY_A] = "A"; key_names[KEY_S] = "S"; key_names[KEY_D] = "D"; key_names[KEY_F] = "F"; key_names[KEY_G] = "G"; key_names[KEY_H] = "H"; key_names[KEY_J] = "J"; key_names[KEY_K] = "K"; key_names[KEY_L] = "L"; key_names[KEY_Z] = "Z"; key_names[KEY_X] = "X"; key_names[KEY_C] = "C"; key_names[KEY_V] = "V"; key_names[KEY_B] = "B"; key_names[KEY_N] = "N"; key_names[KEY_M] = "M"; key_names[KEY_1] = "1"; key_names[KEY_2] = "2"; key_names[KEY_3] = "3"; key_names[KEY_4] = "4"; key_names[KEY_5] = "5"; key_names[KEY_6] = "6"; key_names[KEY_7] = "7"; key_names[KEY_8] = "8"; key_names[KEY_9] = "9"; key_names[KEY_0] = "0"; key_names[KEY_MINUS] = "-"; key_names[KEY_EQUAL] = "="; key_names[KEY_LEFTBRACE] = "["; key_names[KEY_RIGHTBRACE] = "]"; key_names[KEY_SEMICOLON] = ";"; key_names[KEY_APOSTROPHE] = "'"; key_names[KEY_GRAVE] = "`"; key_names[KEY_BACKSLASH] = "\\"; key_names[KEY_COMMA] = ","; key_names[KEY_DOT] = "."; key_names[KEY_SLASH] = "/"; key_names[KEY_SPACE] = ""; key_names[KEY_ESC] = ""; key_names[KEY_BACKSPACE] = ""; key_names[KEY_TAB] = ""; key_names[KEY_ENTER] = ""; key_names[KEY_LEFTSHIFT] = ""; key_names[KEY_RIGHTSHIFT] = ""; key_names[KEY_LEFTCTRL] = ""; key_names[KEY_RIGHTCTRL] = ""; key_names[KEY_LEFTALT] = ""; key_names[KEY_RIGHTALT] = ""; key_names[KEY_LEFTMETA] = ""; key_names[KEY_RIGHTMETA] = ""; key_names[KEY_CAPSLOCK] = ""; key_names[KEY_NUMLOCK] = ""; key_names[KEY_SCROLLLOCK] = ""; key_names[KEY_F1] = ""; key_names[KEY_F2] = ""; key_names[KEY_F3] = ""; key_names[KEY_F4] = ""; key_names[KEY_F5] = ""; key_names[KEY_F6] = ""; key_names[KEY_F7] = ""; key_names[KEY_F8] = ""; key_names[KEY_F9] = ""; key_names[KEY_F10] = ""; key_names[KEY_F11] = ""; key_names[KEY_F12] = ""; key_names[KEY_F13] = ""; key_names[KEY_F14] = ""; key_names[KEY_F15] = ""; key_names[KEY_F16] = ""; key_names[KEY_F17] = ""; key_names[KEY_F18] = ""; key_names[KEY_F19] = ""; key_names[KEY_F20] = ""; key_names[KEY_F21] = ""; key_names[KEY_F22] = ""; key_names[KEY_F23] = ""; key_names[KEY_F24] = ""; key_names[KEY_KP0] = ""; key_names[KEY_KP1] = ""; key_names[KEY_KP2] = ""; key_names[KEY_KP3] = ""; key_names[KEY_KP4] = ""; key_names[KEY_KP5] = ""; key_names[KEY_KP6] = ""; key_names[KEY_KP7] = ""; key_names[KEY_KP8] = ""; key_names[KEY_KP9] = ""; key_names[KEY_KPDOT] = ""; key_names[KEY_KPCOMMA] = ""; key_names[KEY_KPENTER] = ""; key_names[KEY_KPMINUS] = ""; key_names[KEY_KPPLUS] = ""; key_names[KEY_KPSLASH] = ""; key_names[KEY_KPASTERISK] = ""; key_names[KEY_KPEQUAL] = ""; key_names[KEY_UP] = ""; key_names[KEY_DOWN] = ""; key_names[KEY_LEFT] = ""; key_names[KEY_RIGHT] = ""; key_names[KEY_HOME] = ""; key_names[KEY_END] = ""; key_names[KEY_PAGEUP] = ""; key_names[KEY_PAGEDOWN] = ""; key_names[KEY_INSERT] = ""; key_names[KEY_DELETE] = ""; key_names[KEY_MUTE] = ""; key_names[KEY_VOLUMEDOWN] = ""; key_names[KEY_VOLUMEUP] = ""; key_names[KEY_POWER] = ""; key_names[KEY_SLEEP] = ""; key_names[KEY_WAKEUP] = ""; key_names[KEY_PLAY] = ""; key_names[KEY_PAUSE] = ""; key_names[KEY_PLAYPAUSE] = ""; key_names[KEY_STOPCD] = ""; key_names[KEY_PREVIOUSSONG] = ""; key_names[KEY_NEXTSONG] = ""; key_names[KEY_REWIND] = ""; key_names[KEY_FASTFORWARD] = ""; key_names[KEY_RECORD] = ""; key_names[KEY_EJECTCD] = ""; key_names[KEY_SYSRQ] = ""; key_names[KEY_PAUSE] = ""; key_names[KEY_MENU] = ""; key_names[KEY_CALC] = ""; key_names[KEY_MAIL] = ""; key_names[KEY_WWW] = ""; key_names[KEY_SEARCH] = ""; key_names[KEY_BACK] = ""; key_names[KEY_FORWARD] = ""; key_names[KEY_REFRESH] = ""; key_names[KEY_STOP] = ""; key_names[KEY_COPY] = ""; key_names[KEY_CUT] = ""; key_names[KEY_PASTE] = ""; key_names[KEY_UNDO] = ""; key_names[KEY_REDO] = ""; key_names[KEY_FIND] = ""; key_names[KEY_HELP] = ""; key_names[KEY_FILE] = ""; key_names[KEY_SAVE] = ""; key_names[KEY_NEW] = ""; key_names[KEY_OPEN] = ""; key_names[KEY_CLOSE] = ""; key_names[KEY_EXIT] = ""; key_names[KEY_PRINT] = ""; key_names[KEY_BRIGHTNESSDOWN] = ""; key_names[KEY_BRIGHTNESSUP] = ""; key_names[KEY_DISPLAY_OFF] = ""; key_names[KEY_MICMUTE] = ""; key_names[KEY_WLAN] = ""; key_names[KEY_BLUETOOTH] = ""; } void disable_term_echo() { struct termios new_setting, init_setting; tcgetattr(0, & original_term); new_setting = original_term; new_setting.c_lflag &= ~ECHO; tcsetattr(0, TCSANOW, & new_setting); } void enable_term_echo() { tcsetattr(0, TCSANOW, & original_term); } void print_pure(struct input_event * ie) { if (repeat_counters[ie -> code] != 1) { printf("\r%-15s x%-13d", key_names[ie -> code], repeat_counters[ie -> code]); } else { printf("%s", key_names[ie -> code]); } fflush(stdout); } void print_with_time(struct input_event * ie) { struct tm * tm_info; char time_buf[64]; time_t sec = (time_t) ie -> input_event_sec; tm_info = localtime( & sec); strftime(time_buf, sizeof(time_buf), "%F %T", tm_info); if (repeat_counters[ie -> code] != 1) { printf("%s.%06ld: %s x%d\n", time_buf, (long) ie -> time.tv_usec, key_names[ie -> code], repeat_counters[ie -> code]); } else { printf("%s.%06ld: %s\n", time_buf, (long) ie -> time.tv_usec, key_names[ie -> code]); } return; } int main(int argc, char ** argv) { if (argv[1] != NULL && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)) { usage(); return -1; } else if (argv[1] != NULL && (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v")) == 0) { version(); return -1; } setvbuf(stdout, NULL, _IONBF, 0); disable_term_echo(); struct config * cfg = config_init(); if (!cfg) { return -1; } printf("Device: %s\n", cfg -> device); struct input_event ie; int fd = open(cfg -> device, O_RDONLY); if (fd == -1 && errno == EACCES) { printf("Permission denied: please run %s with sudo.\n", PROGRAM_NAME); return -1; } if (fd == -1 && errno == ENOENT) { printf("No such file or directory: %s\n", cfg -> device); return -1; } init_key_names(); void( * fp)(struct input_event * ie) = (cfg -> enable_time == true) ? print_with_time : print_pure; while (1) { read(fd, & ie, sizeof(ie)); if (ie.type == EV_KEY) { if (ie.value == KEY_PRESS) { if (line_lock != -1 && !cfg -> enable_time) printf("\n"); repeat_counters[ie.code] = 1; line_lock = ie.code; fp(&ie); } if (ie.value == KEY_REPEAT) { line_lock = ie.code; repeat_counters[ie.code]++; fp(&ie); } if (ie.value == KEY_RELEASE) { repeat_counters[ie.code] = 1; } } } enable_term_echo(); return 0; }