#include #include #include #include #include #include #include #include #include //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 \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; }