#include "sormc.h"
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define MAX_DEVICES 32
#define DEVICE_PATH "/dev/input/event"
/*
const char *keycode_to_char[] = {
"", "ESC", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
"-", "=", "BACKSPACE", "TAB", "q", "w", "e", "r", "t", "y",
"u", "i", "o", "p", "[", "]", "ENTER", "CTRL", "a", "s",
"d", "f", "g", "h", "j", "k", "l", ";", "'", "`", "SHIFT",
"\\", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/",
"SHIFT", "*", "ALT", " ", "CAPSLOCK"
};*/
const char *keycode_to_char[] = {
[2] = "1", [3] = "2", [4] = "3", [5] = "4", [6] = "5",
[7] = "6", [8] = "7", [9] = "8", [10] = "9", [11] = "0",
[12] = "-", [13] = "=", [14] = "BACKSPACE", [15] = "TAB",
[16] = "Q", [17] = "W", [18] = "E", [19] = "R", [20] = "T",
[21] = "Y", [22] = "U", [23] = "I", [24] = "O", [25] = "P",
[26] = "[", [27] = "]", [28] = "ENTER", [29] = "LEFT_CTRL",
[30] = "A", [31] = "S", [32] = "D", [33] = "F", [34] = "G",
[35] = "H", [36] = "J", [37] = "K", [38] = "L", [39] = ";",
[40] = "'", [41] = "`", [42] = "LEFT_SHIFT", [43] = "\\",
[44] = "Z", [45] = "X", [46] = "C", [47] = "V", [48] = "B",
[49] = "N", [50] = "M", [51] = ",", [52] = ".", [53] = "/",
[54] = "RIGHT_SHIFT", [55] = "KEYPAD_*", [56] = "LEFT_ALT",
[57] = "SPACE", [58] = "CAPSLOCK",
[59] = "F1", [60] = "F2", [61] = "F3", [62] = "F4",
[63] = "F5", [64] = "F6", [65] = "F7", [66] = "F8",
[67] = "F9", [68] = "F10", [87] = "F11", [88] = "F12",
[69] = "NUMLOCK", [70] = "SCROLLLOCK", [71] = "KEYPAD_7",
[72] = "KEYPAD_8", [73] = "KEYPAD_9", [74] = "KEYPAD_-",
[75] = "KEYPAD_4", [76] = "KEYPAD_5", [77] = "KEYPAD_6",
[78] = "KEYPAD_+", [79] = "KEYPAD_1", [80] = "KEYPAD_2",
[81] = "KEYPAD_3", [82] = "KEYPAD_0", [83] = "KEYPAD_.",
[86] = "<", [100] = "RIGHT_ALT", [97] = "RIGHT_CTRL",
[119] = "PAUSE", [120] = "SYSRQ", [121] = "BREAK",
[102] = "HOME", [103] = "UP", [104] = "PAGEUP",
[105] = "LEFT", [106] = "RIGHT", [107] = "END",
[108] = "DOWN", [109] = "PAGEDOWN", [110] = "INSERT",
[111] = "DELETE",
[113] = "MUTE", [114] = "VOLUME_DOWN", [115] = "VOLUME_UP",
[163] = "MEDIA_NEXT", [165] = "MEDIA_PREV", [164] = "MEDIA_PLAY_PAUSE"
};
int is_keyboard(int fd) {
char device_name[256] = {0};
if (ioctl(fd, EVIOCGNAME(sizeof(device_name)), device_name) < 0) {
return 0;
}
return strstr(device_name, "keyboard") != NULL;
}
int main() {
int db = sormc("tikker.db");
ulonglong times_repeated = 0;
ulonglong times_pressed = 0;
ulonglong times_released = 0;
sormq(db, "CREATE TABLE IF NOT EXISTS kevent (id INTEGER PRIMARY KEY AUTOINCREMENT, code,event,name,timestamp,char)");
int keyboard_fds[MAX_DEVICES];
int num_keyboards = 0;
for (int i = 0; i < MAX_DEVICES; i++) {
char device_path[32];
snprintf(device_path, sizeof(device_path), "%s%d", DEVICE_PATH, i);
int fd = open(device_path, O_RDONLY);
if (fd < 0) {
continue;
}
if (is_keyboard(fd)) {
keyboard_fds[num_keyboards++] = fd;
printf("Found keyboard: %s\n", device_path);
} else {
close(fd);
}
}
if (num_keyboards == 0) {
fprintf(stderr, "No keyboard found.\n");
return 1;
}
printf("Monitoring %d keyboards.\n", num_keyboards);
struct input_event ev;
fd_set read_fds;
while (1) {
FD_ZERO(&read_fds);
int max_fd = -1;
for (int i = 0; i < num_keyboards; i++) {
FD_SET(keyboard_fds[i], &read_fds);
if (keyboard_fds[i] > max_fd) {
max_fd = keyboard_fds[i];
}
}
if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) < 0) {
perror("select error");
break;
}
for (int i = 0; i < num_keyboards; i++) {
if (FD_ISSET(keyboard_fds[i], &read_fds)) {
ssize_t bytes = read(keyboard_fds[i], &ev, sizeof(struct input_event));
if (bytes == sizeof(struct input_event)) {
if (ev.type == EV_KEY) {
char * char_name = NULL;
if (ev.code < sizeof(keycode_to_char) / sizeof(keycode_to_char[0])) {
char_name = (char *)keycode_to_char[ev.code], ev.code);
}
char keyboard_name[256];
ioctl(keyboard_fds[i], EVIOCGNAME(sizeof(keyboard_name)), keyboard_name);
printf("Keyboard: %s, ", keyboard_name);
char *event_name = NULL;
if (ev.value == 1) {
event_name = "PRESSED";
times_pressed++;
} else if (ev.value == 0) {
event_name = "RELEASED";
times_released++;
} else {
event_name = "REPEATED";
times_repeated++;
}
sormq(db, "INSERT INTO kevent (code, event, name,timestamp,char) VALUES (%d, %s, %s, DATETIME('now'),%s)", ev.code,
event_name, keyboard_name,char_name);
printf("Event: %s, ", ev.value == 1 ? "PRESSED" : ev.value == 0 ? "RELEASED" : "REPEATED");
printf("Key Code: %d, ", ev.code);
printf("Name: %s, ", char_name);
printf("Pr: %lld Rel: %lld Rep: %lld\n", times_pressed, times_released, times_repeated);
}
}
}
}
}
for (int i = 0; i < num_keyboards; i++) {
close(keyboard_fds[i]);
}
return 0;
}