summaryrefslogtreecommitdiff
path: root/rkbd
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2012-09-26 15:04:18 +0200
committerPeter Wu <lekensteyn@gmail.com>2012-09-26 15:04:18 +0200
commit2497c1392b81e093f4de2541a98746aebd449a7f (patch)
treedb87e59d4c70c677ddb1899d9161b004f6e454ac /rkbd
downloadc-files-2497c1392b81e093f4de2541a98746aebd449a7f.tar.gz
Initial commit
Diffstat (limited to 'rkbd')
-rw-r--r--rkbd/Makefile9
-rw-r--r--rkbd/rkbd.cpp128
-rw-r--r--rkbd/uinput.c90
3 files changed, 227 insertions, 0 deletions
diff --git a/rkbd/Makefile b/rkbd/Makefile
new file mode 100644
index 0000000..f87a6c5
--- /dev/null
+++ b/rkbd/Makefile
@@ -0,0 +1,9 @@
+LDFLAGS := $(shell pkg-config --libs QtGui) -lrt
+CPPFLAGS := -Wall $(shell pkg-config --cflags QtGui)
+
+obj := rkbd
+
+$(obj): $(obj).cpp
+ g++ -o $@ $(CPPFLAGS) $< $(LDFLAGS)
+clean:
+ rm $(obj)
diff --git a/rkbd/rkbd.cpp b/rkbd/rkbd.cpp
new file mode 100644
index 0000000..62e6fea
--- /dev/null
+++ b/rkbd/rkbd.cpp
@@ -0,0 +1,128 @@
+#include <QtGui>
+#include <iostream>
+#include <time.h>
+
+int keys[] = {
+ Qt::Key_Z, /* prev wep */
+ Qt::Key_X, /* next wep */
+ Qt::Key_Space, /* shoot */
+ Qt::Key_Up,
+ Qt::Key_Left,
+ Qt::Key_Down,
+ Qt::Key_Right,
+ Qt::Key_P,
+ Qt::Key_Backspace,
+};
+
+std::string key_names[] = {
+ "Z",
+ "X",
+ "Space",
+ "Up",
+ "Left",
+ "Down",
+ "Right",
+ "Pause",
+ "Backspace",
+};
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a) )
+
+class Application: public QApplication {
+public:
+ Application(int argc, char **argv): QApplication(argc, argv) {
+ setbuf(stdout, NULL); /* disable buffering */
+ }
+ ~Application(){}
+ bool notify(QObject *object, QEvent *event) {
+ bool is_pressed = event->type() == QEvent::KeyPress;
+ if (is_pressed || event->type() == QEvent::KeyRelease) {
+ if (handle_key(static_cast<QKeyEvent *>(event)->key(), is_pressed))
+ return true;
+ }
+ return object->event(event);
+ }
+private:
+ bool handle_key(int code, bool is_pressed) {
+ for (unsigned int i=0; i<ARRAY_SIZE(keys); ++i) {
+ if (keys[i] == code) {
+ report_key(i + 1, is_pressed);
+ return true;
+ }
+ }
+ if (code == Qt::Key_Shift) {
+ release_key();
+ return true;
+ }
+ if (code == Qt::Key_Escape) {
+ std::cerr << "Escape received - quitting" << std::endl;
+ quit();
+ }
+ return false;
+ }
+ int getMS() {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
+ perror("clock_gettime");
+ return 0;
+ }
+ return (ts.tv_sec * 1000) + ts.tv_nsec / 1000000;
+ }
+ int last_code;
+ bool last_is_pressed;
+ //int last_time;
+ void release_key() {
+ if (last_code && last_is_pressed) {
+ send_key(last_code, false);
+ last_is_pressed = false;
+ }
+ }
+ bool always_send_key(int key) {
+ if (!key) return false;
+ switch (keys[key - 1]) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ return false;
+ }
+ return true;
+ }
+ void report_key(int key, bool is_pressed) {
+ //int timestamp = getMS();
+ //bool timed_out = timestamp - last_time >= 300;
+ if (last_code == key && !always_send_key(key)) {
+ if ((is_pressed == last_is_pressed) ||
+ (last_is_pressed && !is_pressed)) {
+ //if (!timed_out) {
+ return;
+ //}
+ }
+ } else {
+ if (!always_send_key(last_code))
+ release_key();
+ }
+ last_code = key;
+ last_is_pressed = is_pressed;
+ //last_time = timestamp;
+
+ send_key(key, is_pressed);
+ }
+ void send_key(int key, bool is_pressed) {
+ printf("%u %u\n", key, is_pressed);
+ if (is_pressed)
+ std::cerr << key_names[key - 1] << " " << (is_pressed ? "pressed" : "released") << std::endl;
+ }
+};
+
+
+int main(int argc, char **argv) {
+ Application app(argc, argv);
+
+ QWidget window;
+ window.resize(250, 150);
+ window.setWindowTitle("Remote keyboard");
+ window.show();
+
+ return app.exec();
+}
diff --git a/rkbd/uinput.c b/rkbd/uinput.c
new file mode 100644
index 0000000..5704679
--- /dev/null
+++ b/rkbd/uinput.c
@@ -0,0 +1,90 @@
+#include <linux/input.h>
+#include <linux/uinput.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h> /* memset */
+#include <stdlib.h> /* EXIT_FAILURE */
+
+int keys[] = {
+ KEY_Q, /* prev */
+ KEY_E, /* next */
+ KEY_Z, /* shoot */
+ KEY_W,
+ KEY_A,
+ KEY_S,
+ KEY_D,
+ KEY_P, /* pause */
+ KEY_BACKSPACE, /* really "backspace" */
+};
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a) )
+
+int main() {
+ int i;
+ int fd = open("/dev/uinput", O_WRONLY);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ if (ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0) {
+ perror("Cannot set EV_KEY bit");
+ goto err_close;
+ }
+ if (ioctl(fd, UI_SET_EVBIT, EV_SYN) < 0) {
+ perror("Cannot set EV_SYN bit");
+ goto err_close;
+ }
+ for (i = 0; i < ARRAY_SIZE(keys); ++i) {
+ if (ioctl(fd, UI_SET_KEYBIT, keys[i]) < 0) {
+ perror("SET_KEYBIT");
+ goto err_close;
+ }
+ }
+
+ struct uinput_user_dev uidev;
+ memset(&uidev, 0, sizeof(uidev));
+ snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Boxhead");
+ if (write(fd, &uidev, sizeof(uidev)) < 0) {
+ perror("write uinput struct");
+ goto err_close;
+ }
+
+ if (ioctl(fd, UI_DEV_CREATE) < 0) {
+ perror("UI_DEV_CREATE");
+ goto err_close;
+ }
+
+ unsigned int code, is_pressed;
+ printf("Waiting for input...\n");
+ struct input_event ev;
+ memset(&ev, 0, sizeof(ev));
+ while (scanf("%u %u", &code, &is_pressed) == 2) {
+ if (code >= 1 && code <= ARRAY_SIZE(keys)) {
+ ev.type = EV_KEY;
+ ev.code = keys[code - 1];
+ ev.value = !!is_pressed;
+ //printf("code=%u value=%u\n", ev.code, ev.value);
+ if (write(fd, &ev, sizeof(ev)) < 0)
+ perror("write key");
+ /* input_sync() */
+ ev.type = EV_SYN;
+ ev.code = SYN_REPORT;
+ ev.value = 0;
+ if (write(fd, &ev, sizeof(ev)) < 0)
+ perror("write sync");
+ } else {
+ fprintf(stderr, "Unexpected key: %u (%#02x)\n", code, code);
+ break;
+ }
+ }
+ if (ioctl(fd, UI_DEV_DESTROY) < 0)
+ perror("Cannot destroy device");
+ if (close(fd) < 0)
+ perror("close");
+ return 0;
+err_close:
+ if (close(fd) < 0)
+ perror("close");
+ return EXIT_FAILURE;
+}