--- /dev/null
+#include "event_device.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <QApplication>
+#include <QKeyEvent>
+
+using namespace std;
+
+using std::set;
+using std::pair;
+
+EventDevice::EventDevice(const std::set<std::pair<unsigned, unsigned>> &accepted_usb_ids, QObject *receiver)
+ : accepted_usb_ids(accepted_usb_ids), receiver(receiver)
+{
+ init();
+}
+
+void EventDevice::init()
+{
+ /* scan /dev/input for event devices */
+ DIR *dir = opendir("/dev/input");
+ struct dirent *de;
+ bool found = false;
+ struct input_id found_id;
+ char path[PATH_MAX];
+
+ if (dir == NULL) {
+ perror("/dev/input");
+ exit(1);
+ }
+
+ while ((de = readdir(dir))) {
+ if (strncmp(de->d_name, "event", 5) != 0)
+ continue;
+
+ sprintf(path, "/dev/input/%s", de->d_name);
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "Warning, skipping %s: %s\n",
+ path, strerror(errno));
+ } else {
+ struct input_id id;
+ if (ioctl(fd, EVIOCGID, &id) == -1) {
+ fprintf(stderr, "ioctl on %s: %s\n",
+ path, strerror(errno));
+ exit(1);
+ }
+
+ if (accepted_usb_ids.count({ id.vendor, id.product }) != 0) {
+ found = true;
+ found_id = id;
+ break;
+ }
+
+ close(fd);
+ }
+ }
+
+ closedir(dir);
+
+ if (found) {
+ char name[256];
+ ioctl(fd, EVIOCGNAME(255), name);
+
+ fprintf(stderr, "Found device (%04x,%04x) at %s: \"%s\"\n",
+ found_id.vendor, found_id.product, path, name);
+ } else {
+ fprintf(stderr, "Could not find the USB device\n");
+ }
+}
+
+void EventDevice::start_thread()
+{
+ thr = thread(&EventDevice::thread_func, this);
+ thr.detach();
+}
+
+void EventDevice::thread_func()
+{
+ struct input_event iev;
+ int ret;
+
+ for ( ;; ) {
+ if (fd != -1) {
+ ret = read(fd, &iev, sizeof(iev));
+ if (ret != sizeof(iev)) {
+ perror("read");
+ fd = -1;
+ }
+ }
+ if (fd == -1) {
+ sleep(5);
+ init();
+ continue;
+ }
+
+ if (iev.type != EV_KEY)
+ continue;
+ if (iev.value != 1)
+ continue;
+
+ QEvent *event = nullptr;
+ switch (iev.code) {
+ case 11:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0");
+ break;
+ case 2:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier, "1");
+ break;
+ case 3:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_2, Qt::NoModifier, "2");
+ break;
+ case 4:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_3, Qt::NoModifier, "3");
+ break;
+ case 5:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_4, Qt::NoModifier, "4");
+ break;
+ case 6:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_5, Qt::NoModifier, "5");
+ break;
+ case 7:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_6, Qt::NoModifier, "6");
+ break;
+ case 8:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_7, Qt::NoModifier, "7");
+ break;
+ case 9:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_8, Qt::NoModifier, "8");
+ break;
+ case 10:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9");
+ break;
+ case 30:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ShiftModifier, "A");
+ break;
+ case 48:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_B, Qt::ShiftModifier, "B");
+ break;
+ case 46:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_C, Qt::ShiftModifier, "C");
+ break;
+ case 32:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_D, Qt::ShiftModifier, "D");
+ break;
+ case 18:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_E, Qt::ShiftModifier, "E");
+ break;
+ case 33:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_F, Qt::ShiftModifier, "F");
+ break;
+ case 14:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
+ break;
+ case 28:
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
+ break;
+ }
+ if (event) {
+ QApplication::postEvent(receiver, event);
+ }
+ // printf("iev.type=%d iev.value=%d iev.code=%d\n", iev.type, iev.value, iev.code);
+ }
+}
+