Skip to content

Instantly share code, notes, and snippets.

@amshafer
Last active June 21, 2019 20:06
Show Gist options
  • Save amshafer/14daf7526867814ebb20b98b9fad2291 to your computer and use it in GitHub Desktop.
Save amshafer/14daf7526867814ebb20b98b9fad2291 to your computer and use it in GitHub Desktop.
DOOM seL4 HID
/*
* 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