Last active
June 21, 2019 20:06
-
-
Save amshafer/14daf7526867814ebb20b98b9fad2291 to your computer and use it in GitHub Desktop.
DOOM seL4 HID
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
/* | |
* seL4 doom HID serial input driver | |
* | |
* Austin Shafer - 2019 | |
*/ | |
#include <termios.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
#include <fcntl.h> | |
#include <X11/Xlib.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <X11/keysym.h> | |
#include <X11/XKBlib.h> | |
#include <poll.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <stdint.h> | |
/* taken from linuxdoom */ | |
// | |
// DOOM keyboard definition. | |
// This is the stuff configured by Setup.Exe. | |
// Most key data are simple ascii (uppercased). | |
// | |
#define KEY_RIGHTARROW 0xae | |
#define KEY_LEFTARROW 0xac | |
#define KEY_UPARROW 0xad | |
#define KEY_DOWNARROW 0xaf | |
#define KEY_ESCAPE 27 | |
#define KEY_ENTER 13 | |
#define KEY_TAB 9 | |
#define KEY_F1 (0x80+0x3b) | |
#define KEY_F2 (0x80+0x3c) | |
#define KEY_F3 (0x80+0x3d) | |
#define KEY_F4 (0x80+0x3e) | |
#define KEY_F5 (0x80+0x3f) | |
#define KEY_F6 (0x80+0x40) | |
#define KEY_F7 (0x80+0x41) | |
#define KEY_F8 (0x80+0x42) | |
#define KEY_F9 (0x80+0x43) | |
#define KEY_F10 (0x80+0x44) | |
#define KEY_F11 (0x80+0x57) | |
#define KEY_F12 (0x80+0x58) | |
#define KEY_BACKSPACE 127 | |
#define KEY_PAUSE 0xff | |
#define KEY_EQUALS 0x3d | |
#define KEY_MINUS 0x2d | |
#define KEY_RSHIFT (0x80+0x36) | |
#define KEY_RCTRL (0x80+0x1d) | |
#define KEY_RALT (0x80+0x38) | |
#define KEY_LALT KEY_RALT | |
// Event structure. | |
// Input event types. | |
typedef enum | |
{ | |
ev_keydown, | |
ev_keyup, | |
ev_mouse, | |
ev_joystick | |
} evtype_t; | |
typedef struct | |
{ | |
uint32_t type; | |
uint32_t data1; // keys / mouse/joystick buttons | |
uint32_t data2; // mouse/joystick x move | |
uint32_t data3; // mouse/joystick y move | |
} event_t; | |
char pressed[256]; | |
Display *display; | |
Window window; | |
XEvent event; | |
int | |
xlatekey () | |
{ | |
int rc; | |
switch(rc = XKeycodeToKeysym(display, event.xkey.keycode, 0)) | |
{ | |
case XK_Left: rc = KEY_LEFTARROW; break; | |
case XK_Right: rc = KEY_RIGHTARROW; break; | |
case XK_Down: rc = KEY_DOWNARROW; break; | |
case XK_Up: rc = KEY_UPARROW; break; | |
case XK_Escape: rc = KEY_ESCAPE; break; | |
case XK_Return: rc = KEY_ENTER; break; | |
case XK_Tab: rc = KEY_TAB; break; | |
case XK_F1: rc = KEY_F1; break; | |
case XK_F2: rc = KEY_F2; break; | |
case XK_F3: rc = KEY_F3; break; | |
case XK_F4: rc = KEY_F4; break; | |
case XK_F5: rc = KEY_F5; break; | |
case XK_F6: rc = KEY_F6; break; | |
case XK_F7: rc = KEY_F7; break; | |
case XK_F8: rc = KEY_F8; break; | |
case XK_F9: rc = KEY_F9; break; | |
case XK_F10: rc = KEY_F10; break; | |
case XK_F11: rc = KEY_F11; break; | |
case XK_F12: rc = KEY_F12; break; | |
case XK_BackSpace: | |
case XK_Delete: rc = KEY_BACKSPACE; break; | |
case XK_Pause: rc = KEY_PAUSE; break; | |
case XK_KP_Equal: | |
case XK_equal: rc = KEY_EQUALS; break; | |
case XK_KP_Subtract: | |
case XK_minus: rc = KEY_MINUS; break; | |
case XK_Shift_L: | |
case XK_Shift_R: | |
rc = KEY_RSHIFT; | |
break; | |
case XK_Control_L: | |
case XK_Control_R: | |
rc = KEY_RCTRL; | |
break; | |
case XK_Alt_L: | |
case XK_Meta_L: | |
case XK_Alt_R: | |
case XK_Meta_R: | |
rc = KEY_RALT; | |
break; | |
default: | |
if (rc >= XK_space && rc <= XK_asciitilde) | |
rc = rc - XK_space + ' '; | |
if (rc >= 'A' && rc <= 'Z') | |
rc = rc - 'A' + 'a'; | |
break; | |
} | |
return rc; | |
} | |
/* | |
* bits stolen from javiercantero's gist | |
* https://gist.github.com/javiercantero/7753445 | |
*/ | |
int | |
main (int argc, char *argv[]) | |
{ | |
event_t ev; | |
int s, fd, error; | |
char buff[256]; | |
struct pollfd fds[1]; | |
struct termios term; | |
if (argc != 2) { | |
printf("Usage: doom-sel4hid <tty>\n"); | |
exit(1); | |
} | |
fd = open(argv[1], O_RDWR|O_NOCTTY|O_NDELAY); | |
assert(fd > 0); | |
/* open connection with the server */ | |
display = XOpenDisplay(NULL); | |
if (display == NULL) | |
{ | |
fprintf(stderr, "Cannot open display\n"); | |
exit(1); | |
} | |
s = DefaultScreen(display); | |
/* create window */ | |
window = XCreateSimpleWindow(display, RootWindow(display, s), 10, 10, 200, 200, 1, | |
BlackPixel(display, s), WhitePixel(display, s)); | |
/* select kind of events we are interested in */ | |
XSelectInput(display, window, KeyPressMask | KeyReleaseMask ); | |
int ret; | |
XkbSetDetectableAutoRepeat(display, 1, &ret); | |
assert(ret == 1); | |
/* map (show) the window */ | |
XMapWindow(display, window); | |
fds[0].fd = fd; | |
fds[0].events = POLLIN; | |
/* set terminal attributes */ | |
error = tcgetattr(fd, &term); | |
assert(error == 0); | |
cfsetospeed(&term, B115200); | |
cfsetispeed(&term, B115200); | |
term.c_cflag |= (CLOCAL|CREAD); | |
term.c_cflag &= ~PARENB; /* no parity */ | |
term.c_cflag &= ~CSTOPB; | |
term.c_cflag &= ~CSIZE; | |
term.c_cflag |= CS8; /* 8-bit chars */ | |
term.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHONL|ISIG|IEXTEN); /* raw mode */ | |
term.c_iflag &= ~(IGNBRK|IXON|IXOFF|IXANY|BRKINT|PARMRK|ISTRIP|INLCR|ICRNL|IGNCR); | |
term.c_oflag &= ~(OPOST); | |
error = tcsetattr(fd, TCSANOW, &term); | |
assert(error == 0); | |
memset(pressed, 0, sizeof(pressed)); | |
tcflush(fd, TCIOFLUSH); | |
//event_t rev; | |
while (1) { | |
/* read any text from the console to display */ | |
while (poll(fds, 1, 0) == 1) { | |
int length = read(fd, buff, 256); | |
if (length > 0) | |
write(STDOUT_FILENO, buff, length); | |
/* memset(&rev, 0, sizeof(event_t)); */ | |
/* int length = read(fd, &rev, sizeof(event_t)); */ | |
/* printf("HOST: Recieved %d Event bytes -\n", length); fflush(stdout); */ | |
/* printf(" type = %d\n", rev.type); fflush(stdout); */ | |
/* printf(" data1 = %d\n", rev.data1); fflush(stdout); */ | |
/* printf(" data2 = %d\n", rev.data2); fflush(stdout); */ | |
/* printf(" data3 = %d\n", rev.data3); fflush(stdout); */ | |
} | |
if (XPending(display) <= 0) | |
continue; | |
memset(&event, 0, sizeof(XEvent)); | |
memset(&ev, 0, sizeof(event_t)); | |
XNextEvent(display, &event); | |
switch (event.type) | |
{ | |
case KeyPress: | |
ev.type = ev_keydown; | |
ev.data1 = xlatekey(); | |
if (pressed[ev.data1] == 1) | |
continue; | |
pressed[ev.data1] = 1; | |
break; | |
case KeyRelease: | |
ev.type = ev_keyup; | |
ev.data1 = xlatekey(); | |
if (pressed[ev.data1] == 0) | |
continue; | |
pressed[ev.data1] = 0; | |
break; | |
default: | |
continue; | |
} | |
/* send the event_t over the wire to DOOM */ | |
error = write(fd, &ev, 8); | |
printf("HOST: Sending %d event bytes -\n", error); fflush(stdout); | |
printf(" type = %d\n", ev.type); fflush(stdout); | |
printf(" data1 = %d\n", ev.data1); fflush(stdout); | |
printf(" data2 = %d\n", ev.data2); fflush(stdout); | |
printf(" data3 = %d\n", ev.data3); fflush(stdout); | |
error = tcdrain(fd); | |
/* wait for ACK (XON/19) */ | |
char ack = '\0'; | |
do { | |
error = read(fd, &ack, sizeof(char)); | |
printf("HOST: found ack 0x%x\n", ack); fflush(stdout); | |
} while (error == -1 || ack != 19); | |
} | |
XCloseDisplay(display); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment