From 15f8a5c7fa078dc5cfed963ce14fb5e3cea7d7bd Mon Sep 17 00:00:00 2001 From: sorgelig Date: Tue, 28 May 2019 00:57:35 +0800 Subject: [PATCH] input: inject keys from gamepad to HPS. --- fpga_io.cpp | 1 + input.cpp | 167 ++++++++++++++++++++++++++++++++++++++++++++-------- input.h | 1 + 3 files changed, 145 insertions(+), 24 deletions(-) diff --git a/fpga_io.cpp b/fpga_io.cpp index fdfc098..2092eda 100644 --- a/fpga_io.cpp +++ b/fpga_io.cpp @@ -633,6 +633,7 @@ void app_restart(const char *path) fpga_core_reset(1); input_switch(0); + input_uinp_destroy(); char *appname = getappname(); printf("restarting the %s\n", appname); diff --git a/input.cpp b/input.cpp index 3f7feb1..2492108 100644 --- a/input.cpp +++ b/input.cpp @@ -9,6 +9,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "input.h" #include "user_io.h" @@ -21,6 +27,7 @@ #define NUMDEV 30 #define NUMPLAYERS 6 +#define UINPUT_NAME "MiSTer virtual input" static int ev2amiga[] = { @@ -1369,6 +1376,69 @@ static uint32_t mouse_timer = 0; #define BTN_TGL 100 #define BTN_OSD 101 +static int uinp_fd = -1; +static int input_uinp_setup() +{ + if (uinp_fd <= 0) + { + struct uinput_user_dev uinp; + + if (!(uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY))) + { + printf("Unable to open /dev/uinput\n"); + uinp_fd = -1; + return 0; + } + + memset(&uinp, 0, sizeof(uinp)); + strncpy(uinp.name, UINPUT_NAME, UINPUT_MAX_NAME_SIZE); + uinp.id.version = 4; + uinp.id.bustype = BUS_USB; + + ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY); + for (int i = 0; i < 256; i++) ioctl(uinp_fd, UI_SET_KEYBIT, i); + + write(uinp_fd, &uinp, sizeof(uinp)); + if (ioctl(uinp_fd, UI_DEV_CREATE)) + { + printf("Unable to create UINPUT device."); + close(uinp_fd); + uinp_fd = -1; + return 0; + } + } + return 1; +} + +void input_uinp_destroy() +{ + if (uinp_fd > 0) + { + ioctl(uinp_fd, UI_DEV_DESTROY); + close(uinp_fd); + uinp_fd = -1; + } +} + +static void uinp_send_key(uint16_t key, int press) +{ + if (uinp_fd > 0) + { + static struct input_event event; + + memset(&event, 0, sizeof(event)); + gettimeofday(&event.time, NULL); + event.type = EV_KEY; + event.code = key; + event.value = press ? 1 : 0; + write(uinp_fd, &event, sizeof(event)); + event.type = EV_SYN; + event.code = SYN_REPORT; + event.value = 0; + write(uinp_fd, &event, sizeof(event)); + } +} + static void mouse_cb(unsigned char b, int16_t x = 0, int16_t y = 0, int16_t w = 0) { if (grabbed) user_io_mouse(b, x, y, w); @@ -1533,6 +1603,43 @@ static void joy_digital(int jnum, uint32_t mask, uint32_t code, char press, int input_cb(&ev, 0, 0); } + else if (video_fb_state()) + { + switch (mask) + { + case JOY_RIGHT: + uinp_send_key(KEY_RIGHT, press); + break; + + case JOY_LEFT: + uinp_send_key(KEY_LEFT, press); + break; + + case JOY_UP: + uinp_send_key(KEY_UP, press); + break; + + case JOY_DOWN: + uinp_send_key(KEY_DOWN, press); + break; + + case JOY_BTN1: + uinp_send_key(KEY_ENTER, press); + break; + + case JOY_BTN2: + uinp_send_key(KEY_ESC, press); + break; + + case JOY_BTN3: + uinp_send_key(KEY_SPACE, press); + break; + + case JOY_BTN4: + uinp_send_key(KEY_TAB, press); + break; + } + } else if(jnum) { if (press) joy[num] |= mask; @@ -2247,6 +2354,7 @@ int input_test(int getchar) if (state == 0) { + input_uinp_setup(); memset(pool, -1, sizeof(pool)); signal(SIGINT, INThandler); @@ -2297,6 +2405,14 @@ int input_test(int getchar) input[n].led = has_led(pool[n].fd); } + //skip our virtual device + if (!strcmp(input[n].name, UINPUT_NAME)) + { + close(pool[n].fd); + pool[n].fd = -1; + continue; + } + input[n].bind = -1; // enable scroll wheel reading @@ -2882,36 +2998,39 @@ int input_poll(int getchar) if (!mouse_emu_x && !mouse_emu_y) mouse_timer = 0; - for (int i = 0; i < NUMPLAYERS; i++) + if (grabbed) { - if (!af_delay[i]) af_delay[i] = 50; - - if (!time[i]) time[i] = GetTimer(af_delay[i]); - int send = 0; - - int newdir = ((joy[i] & 0xF) != (joy_prev[i] & 0xF)); - if (joy[i] != joy_prev[i]) + for (int i = 0; i < NUMPLAYERS; i++) { - if ((joy[i] ^ joy_prev[i]) & autofire[i]) + if (!af_delay[i]) af_delay[i] = 50; + + if (!time[i]) time[i] = GetTimer(af_delay[i]); + int send = 0; + + int newdir = ((joy[i] & 0xF) != (joy_prev[i] & 0xF)); + if (joy[i] != joy_prev[i]) { - time[i] = GetTimer(af_delay[i]); - af[i] = 0; + if ((joy[i] ^ joy_prev[i]) & autofire[i]) + { + time[i] = GetTimer(af_delay[i]); + af[i] = 0; + } + + send = 1; + joy_prev[i] = joy[i]; } - send = 1; - joy_prev[i] = joy[i]; - } + if (CheckTimer(time[i])) + { + time[i] = GetTimer(af_delay[i]); + af[i] = !af[i]; + if (joy[i] & autofire[i]) send = 1; + } - if (CheckTimer(time[i])) - { - time[i] = GetTimer(af_delay[i]); - af[i] = !af[i]; - if (joy[i] & autofire[i]) send = 1; - } - - if (grabbed && send) - { - user_io_digital_joystick(i, af[i] ? joy[i] & ~autofire[i] : joy[i], newdir); + if (send) + { + user_io_digital_joystick(i, af[i] ? joy[i] & ~autofire[i] : joy[i], newdir); + } } } diff --git a/input.h b/input.h index ab2fcaa..4e58d55 100644 --- a/input.h +++ b/input.h @@ -57,5 +57,6 @@ void input_lightgun_cal(uint16_t *cal); void input_switch(int grab); int input_state(); +void input_uinp_destroy(); #endif