Last active
October 24, 2020 19:55
-
-
Save saivert/28bb5bade6e4d936d4b49173b346ef44 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-2.0 | |
// Coding style: Linux kernel | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <poll.h> | |
#include <stdlib.h> | |
#include <ctype.h> | |
#include <signal.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include <linux/input.h> | |
#include <xkbcommon/xkbcommon.h> | |
#include <termios.h> | |
static int position_x, position_y; | |
static volatile sig_atomic_t doquit; | |
static void quit(int sig) | |
{ | |
(void)sig; | |
doquit = 1; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int timeout_ms = 5000; | |
char *input_dev; | |
if (argc != 2) { | |
printf("Usage: evdev /dev/input/eventX\n"); | |
return 1; | |
} | |
input_dev = argv[1]; | |
int ret; | |
int previous_type; | |
struct pollfd fds[1]; | |
signal(SIGINT, quit); | |
fds[0].fd = open(input_dev, O_RDONLY|O_NONBLOCK); | |
if (fds[0].fd < 0) { | |
printf("Error: unable open for reading '%s'\n", input_dev); | |
return 1; | |
} | |
// Disable local echo | |
struct termios old, new; | |
tcgetattr(STDIN_FILENO, &old); // get current settings | |
new = old; // create a backup | |
new.c_lflag &= ~(ICANON | ECHO); // disable line buffering and feedback | |
tcsetattr(STDIN_FILENO, TCSANOW, &new); // set our new config | |
struct xkb_state *xkb_state; | |
struct xkb_context *xkb_context; | |
struct xkb_keymap *xkb_keymap; | |
struct xkb_rule_names names = { | |
.rules = NULL, | |
.model = "pc105", | |
.layout = "no", | |
.variant = NULL, | |
.options = "" | |
}; | |
const int input_size = sizeof(struct input_event); | |
unsigned char input_data[sizeof(struct input_event)]; | |
memset(input_data, 0, input_size); | |
fds[0].events = POLLIN; | |
xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | |
xkb_keymap = xkb_keymap_new_from_names(xkb_context, &names, | |
XKB_KEYMAP_COMPILE_NO_FLAGS); | |
xkb_state = xkb_state_new(xkb_keymap); | |
printf("Evdev tester, press ^C to quit!\n\n"); | |
while (!doquit) { | |
ret = poll(fds, 1, timeout_ms); | |
if (ret > 0) { | |
if (fds[0].revents) { | |
ssize_t r = read(fds[0].fd, input_data, input_size); | |
if (r < 0) { | |
printf("Error %d\n", (int)r); | |
break; | |
} | |
struct input_event *event = (struct input_event *)(input_data); | |
//printf("type = %hu, code = %hu value= %u\n", event->type, event->code, event->value); | |
xkb_keycode_t keycode; | |
xkb_keysym_t keysym; | |
if (event->type == EV_KEY && (event->value == 1 || event->value == 0)) { | |
xkb_state_update_key(xkb_state, event->code+8, event->value ? XKB_KEY_DOWN : XKB_KEY_UP); | |
if (event->code == BTN_LEFT) | |
printf("\33[2K\rKey pressed: Left mouse button %s\n", (event->value ? "pressed" : "released")); | |
else if (event->code == BTN_RIGHT) | |
printf("\33[2K\rKey pressed: Right mouse button %s\n", (event->value ? "pressed" : "released")); | |
} | |
if (event->type == EV_KEY && event->value == 1) { | |
keycode = event->code+8; // offset to convert from evdev scan code to xbk keycode | |
keysym = xkb_state_key_get_one_sym(xkb_state, keycode); | |
char keysym_name[64]; | |
xkb_keysym_get_name(keysym, keysym_name, sizeof(keysym_name)); | |
//printf("XKB Keysym = %s\n", keysym_name); | |
char *buffer; | |
int size; | |
// First find the needed size; return value is the same as snprintf(3). | |
size = xkb_state_key_get_utf8(xkb_state, keycode, NULL, 0) + 1; | |
if (size >= 1) { | |
buffer = calloc(1, size); | |
xkb_state_key_get_utf8(xkb_state, keycode, buffer, size); | |
// Don't print control characters | |
if (iscntrl(buffer[0])) | |
buffer[0] = '\0'; | |
printf("\33[2K\rKey pressed: %s%s[%s]", buffer, buffer[0] ? " " : "", keysym_name); | |
fflush(stdout); | |
free(buffer); | |
} | |
} else if (event->type == EV_ABS) { | |
if (event->code == ABS_X) | |
position_x = event->value; | |
if (event->code == ABS_Y) | |
position_y = event->value; | |
previous_type = EV_ABS; | |
} else if (event->type == EV_SYN && event->code == SYN_REPORT && previous_type == EV_ABS) { | |
printf("\33[2K\rX = %d, Y = %d absolute", position_x, position_y); | |
fflush(stdout); | |
} else if (event->type == EV_REL) { | |
if (event->code == REL_X) | |
position_x += event->value; | |
if (event->code == REL_Y) | |
position_y += event->value; | |
previous_type = EV_REL; | |
} else if (event->type == EV_SYN && event->code == SYN_REPORT && previous_type == EV_REL) { | |
printf("\33[2K\rX = %d, Y = %d relative", position_x, position_y); | |
fflush(stdout); | |
} | |
memset(input_data, 0, input_size); | |
} else { | |
printf("Error!\n"); | |
} | |
} else { | |
printf("\33[2K\rtimeout"); | |
fflush(stdout); | |
} | |
} | |
tcsetattr(STDIN_FILENO, TCSANOW, &old); | |
xkb_keymap_unref(xkb_keymap); | |
xkb_state_unref(xkb_state); | |
xkb_context_unref(xkb_context); | |
close(fds[0].fd); | |
printf("\33[2K\rBye!\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment