|
|
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/uinput.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
//List of button definitons and whatnot
#define START 0x01
#define WEST 0x02
#define EAST 0x08
#define SOUTH 0x04
#define DPAD_LEFT 0x10
#define DPAD_RIGHT 0x20
#define DPAD_DOWN 0x40
#define DPAD_UP 0x80
#define SELECT 0x100
#define LEFT_TRIGGER 0x200
#define NORTH 0x400
#define RIGHT_TRIGGER 0x800
//#define DEBUG_MODE 0x1337
//#define CONTROLLER_MODE 0x420
//A list that will hold the button offsets in a sequential order
int buttons_list[] = { START,WEST,EAST,SOUTH, // 0 - 3
DPAD_LEFT,DPAD_RIGHT,DPAD_DOWN,DPAD_UP, // 4 - 7
SELECT,LEFT_TRIGGER,NORTH,RIGHT_TRIGGER // 8 - 11
};
#ifdef DEBUG_MODE
//1-letter names for buttons
char debug_names[] = "TWESLRDUMZNC"; #endif
//Actual mappings for the buttons, in the same order as in buttons_list
#ifdef CONTROLLER_MODE
//Mappings that are binding the controller as a joystick instead of a keyboard
int mappings[] = { BTN_START,BTN_WEST,BTN_EAST,BTN_SOUTH, BTN_DPAD_LEFT,BTN_DPAD_RIGHT,BTN_DPAD_DOWN,BTN_DPAD_UP, BTN_SELECT,BTN_TL,BTN_NORTH,BTN_TR }; #else
//Mappings that correspond to a particular subset of keyboard keys
int mappings[] = { KEY_ESC,KEY_A,KEY_D,KEY_S, KEY_LEFT,KEY_RIGHT,KEY_DOWN,KEY_UP, KEY_X,KEY_Z,KEY_W,KEY_C }; #endif
int input; int uinput_fd;
//a bit of stolen code to make things work
void emit(int fd, int type, int code, int val) { struct input_event ie;
ie.type = type; ie.code = code; ie.value = val; /* timestamp values below are ignored */ ie.time.tv_sec = 0; ie.time.tv_usec = 0;
write(fd, &ie, sizeof(ie)); }
void bye(int signum) { //wait some more just because we want all the events that are happening to happen before we close everything.
sleep(1); printf("Exit signal received - destroying the uinput device.\n"); close(input); ioctl(uinput_fd, UI_DEV_DESTROY); sleep(1); close(uinput_fd); exit(0); };
int set_interface_attribs(int fd, int speed, int parity) { struct termios tty; if (tcgetattr(fd, &tty) != 0) { printf("Error %d from tcget",errno); return -1; }
cfsetospeed(&tty, speed); cfsetispeed(&tty, speed); tty.c_lflag = 0; tty.c_cflag |= CRTSCTS | CS8 | CLOCAL | CREAD; tty.c_iflag = IGNPAR; tty.c_oflag = 0; tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; tcflush(fd, TCIFLUSH); if (tcsetattr(fd, TCSANOW, &tty) != 0) { printf("Error %d when setting up tty", errno); return -1; } return 0; }
int set_blocking(int fd, int should_block) { struct termios tty; memset (&tty, 0, sizeof(tty)); if(tcgetattr(fd, &tty) != 0) { printf("Error %d from tcget", errno); return -1; } tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &tty) != 0) { printf("Error %d from tcset", errno); return -1; } return 0; }
int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: driver <input device>\n"); return 1; } //Open tty device for reading
input = open(argv[1], O_RDWR | O_NOCTTY | O_SYNC); if (!input) { printf("Unable to open device %s for reading: %s\n",argv[1],strerror(errno)); return errno; } set_interface_attribs(input, B9600, 0); set_blocking(input, 1);
//Create uinput configuration struct and open /dev/uinput
struct uinput_setup usetup; uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); //Add this to gracefully close uinput_fd and input
signal(SIGINT, bye);
ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY); for (int k = 0; k < 12; k++) { ioctl(uinput_fd, UI_SET_KEYBIT, mappings[k]); }
//Clear struct, set vendor and product.
memset(&usetup, 0, sizeof(usetup)); usetup.id.bustype = BUS_USB; usetup.id.vendor = 0x041e; usetup.id.product = 0x1003; strcpy(usetup.name,"Macrohard YBox 2pi LPT2USB controller");
//Call setup
if (ioctl(uinput_fd, UI_DEV_SETUP, &usetup)) { perror("UI_DEV_SETUP"); printf("Note: This might have been the result of not running the program as root\n"); return 1; } if (ioctl(uinput_fd, UI_DEV_CREATE)) { perror("UI_DEV_CREATE"); return 1; }
//Wait for some time so that uinput has time to setup stuff
sleep(1); short unsigned int buffer[2]; short unsigned int prev_state = 0x0; short unsigned int changes = 0x0; short unsigned int current_state = 0x0; //Main loop
while(1) { read(input, buffer, 2); current_state = ~buffer[0]; changes = prev_state ^ current_state; if (changes != 0) { #ifdef DEBUG_MODE
printf("State hash: %u\n",current_state); printf("Recieved message: %u\n",buffer[0]); #endif
for (int k = 0; k < 12; k++) { if (changes & buttons_list[k]) { emit(uinput_fd, EV_KEY, mappings[k], (current_state & buttons_list[k]) > 0); emit(uinput_fd, EV_SYN, SYN_REPORT, 0); #ifdef DEBUG_MODE
printf("Internal key name: %c\n",debug_names[k]); printf("Key state: %u\n",(current_state & buttons_list[k]) > 0); printf("Key mapping: %u\n",mappings[k]); #endif
} } #ifdef DEBUG_MODE
printf("-------\n"); fflush(stdout); #endif
} prev_state = current_state; } //haha what a loser can't even get here because while true do loop
return 0; }
|