From 2056ebc80378fabf1f96883de3c7c930c809d101 Mon Sep 17 00:00:00 2001 From: Zoran Vuckovic Date: Fri, 2 Jun 2017 01:08:28 +0200 Subject: [PATCH 1/2] Allow udev input to be used with X11 context --- gfx/drivers_context/x_ctx.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index 222e5d11e9..141fec877b 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -36,6 +36,9 @@ #endif +#include + +#include "../../configuration.h" #include "../../frontend/frontend_driver.h" #include "../common/gl_common.h" #include "../common/x11_common.h" @@ -900,8 +903,21 @@ static void gfx_ctx_x_input_driver(void *data, const char *joypad_name, const input_driver_t **input, void **input_data) { - void *xinput = input_x.init(joypad_name); +#ifdef HAVE_UDEV + settings_t *settings = config_get_ptr(); + if (string_is_equal_fast(settings->arrays.input_driver, "udev", 5)) + { + *input_data = input_udev.init(joypad_name); + if (*input_data) + { + *input = &input_udev; + return; + } + } +#endif + + void *xinput = input_x.init(joypad_name); *input = xinput ? &input_x : NULL; *input_data = xinput; } From 11559f294af0a479c497ca0c6416059cd35bd0aa Mon Sep 17 00:00:00 2001 From: Zoran Vuckovic Date: Fri, 2 Jun 2017 07:57:07 +0200 Subject: [PATCH 2/2] Add multiple mice support to udev driver --- input/drivers/udev_input.c | 277 ++++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 99 deletions(-) diff --git a/input/drivers/udev_input.c b/input/drivers/udev_input.c index 0a96d01122..c6eadaf13d 100644 --- a/input/drivers/udev_input.c +++ b/input/drivers/udev_input.c @@ -60,6 +60,28 @@ typedef struct udev_input udev_input_t; typedef struct udev_input_device udev_input_device_t; +enum udev_input_dev_type +{ + UDEV_INPUT_KEYBOARD, + UDEV_INPUT_MOUSE, + UDEV_INPUT_TOUCHPAD +}; + +/* NOTE: must be in sync with enum udev_input_dev_type */ +static const char *g_dev_type_str[] = +{ + "ID_INPUT_KEYBOARD", + "ID_INPUT_MOUSE", + "ID_INPUT_TOUCHPAD" +}; + +typedef struct +{ + int16_t x, y; + bool l, r, m; + bool wu, wd, whu, whd; +} udev_input_mouse_t; + struct udev_input_device { int fd; @@ -67,13 +89,12 @@ struct udev_input_device void (*handle_cb)(void *data, const struct input_event *event, udev_input_device_t *dev); char devnode[PATH_MAX_LENGTH]; + enum udev_input_dev_type type; union { - /* - * keyboard - * mouse - */ + udev_input_mouse_t mouse; + struct { float x, y; @@ -100,10 +121,6 @@ struct udev_input int epfd; udev_input_device_t **devices; unsigned num_devices; - - int16_t mouse_x; - int16_t mouse_y; - bool mouse_l, mouse_r, mouse_m, mouse_wu, mouse_wd, mouse_whu, mouse_whd; }; #ifdef HAVE_XKBCOMMON @@ -155,7 +172,18 @@ static void udev_input_kb_free(void) static void udev_handle_touchpad(void *data, const struct input_event *event, udev_input_device_t *dev) { - udev_input_t *udev = (udev_input_t*)data; + unsigned i; + udev_input_t *udev = (udev_input_t*)data; + udev_input_mouse_t *mouse = NULL; + + for (i = 0; i < udev->num_devices; ++i) + { + if (udev->devices[i]->type == UDEV_INPUT_MOUSE) + { + mouse = &udev->devices[i]->state.mouse; + break; + } + } switch (event->type) { @@ -170,9 +198,8 @@ static void udev_handle_touchpad(void *data, float x_norm = (float)x / range; float rel_x = x_norm - dev->state.touchpad.x; - if (dev->state.touchpad.touch) - udev->mouse_x += (int16_t) - roundf(dev->state.touchpad.mod_x * rel_x); + if (dev->state.touchpad.touch && mouse) + mouse->x += (int16_t)roundf(dev->state.touchpad.mod_x * rel_x); dev->state.touchpad.x = x_norm; /* Some factor, not sure what's good to do here ... */ @@ -188,8 +215,8 @@ static void udev_handle_touchpad(void *data, float y_norm = (float)y / range; float rel_y = y_norm - dev->state.touchpad.y; - if (dev->state.touchpad.touch) - udev->mouse_y += (int16_t)roundf(dev->state.touchpad.mod_y * rel_y); + if (dev->state.touchpad.touch && mouse) + mouse->y += (int16_t)roundf(dev->state.touchpad.mod_y * rel_y); dev->state.touchpad.y = y_norm; @@ -221,24 +248,23 @@ static void udev_handle_touchpad(void *data, static void udev_handle_mouse(void *data, const struct input_event *event, udev_input_device_t *dev) { - udev_input_t *udev = (udev_input_t*)data; + udev_input_mouse_t *mouse = &dev->state.mouse; switch (event->type) { case EV_KEY: - /* TODO: mouse wheel up/down doesn't work */ switch (event->code) { case BTN_LEFT: - udev->mouse_l = event->value; + mouse->l = event->value; break; case BTN_RIGHT: - udev->mouse_r = event->value; + mouse->r = event->value; break; case BTN_MIDDLE: - udev->mouse_m = event->value; + mouse->m = event->value; break; default: break; @@ -249,36 +275,28 @@ static void udev_handle_mouse(void *data, switch (event->code) { case REL_X: - udev->mouse_x += event->value; + mouse->x += event->value; break; - case REL_Y: - udev->mouse_y += event->value; + mouse->y += event->value; break; case REL_WHEEL: if (event->value == 1) - udev->mouse_wu = 1; + mouse->wu = 1; else if (event->value == -1) - udev->mouse_wd = 1; + mouse->wd = 1; break; case REL_HWHEEL: if (event->value == 1) - udev->mouse_whu = 1; + mouse->whu = 1; else if (event->value == -1) - udev->mouse_whd = 1; - break; - default: - break; + mouse->whd = 1; } - break; - - default: - break; } } static bool udev_input_add_device(udev_input_t *udev, - const char *devnode, device_handle_cb cb) + enum udev_input_dev_type type, const char *devnode, device_handle_cb cb) { int fd; udev_input_device_t **tmp; @@ -299,11 +317,12 @@ static bool udev_input_add_device(udev_input_t *udev, device->fd = fd; device->dev = st.st_dev; device->handle_cb = cb; + device->type = type; strlcpy(device->devnode, devnode, sizeof(device->devnode)); /* Touchpads report in absolute coords. */ - if (cb == udev_handle_touchpad && + if (type == UDEV_INPUT_TOUCHPAD && (ioctl(fd, EVIOCGABS(ABS_X), &device->state.touchpad.info_x) < 0 || ioctl(fd, EVIOCGABS(ABS_Y), &device->state.touchpad.info_y) < 0)) goto error; @@ -348,12 +367,13 @@ static void udev_input_remove_device(udev_input_t *udev, const char *devnode) static void udev_input_handle_hotplug(udev_input_t *udev) { - const char *devtype = NULL; - const char *val_keyboard = NULL; - const char *val_mouse = NULL; - const char *val_touchpad = NULL; - const char *action = NULL; - const char *devnode = NULL; + const char *val_keyboard; + const char *val_mouse; + const char *val_touchpad; + const char *action; + const char *devnode; + enum udev_input_dev_type dev_type; + device_handle_cb cb; struct udev_device *dev = udev_monitor_receive_device(udev->monitor); if (!dev) @@ -366,33 +386,31 @@ static void udev_input_handle_hotplug(udev_input_t *udev) devnode = udev_device_get_devnode(dev); if (val_keyboard && string_is_equal_fast(val_keyboard, "1", 1) && devnode) - devtype = "keyboard"; - - if (val_mouse && string_is_equal_fast(val_mouse, "1", 1) && devnode) - devtype = "mouse"; - - if (val_touchpad && string_is_equal_fast(val_touchpad, "1", 1) && devnode) - devtype = "touchpad"; - - if (!devtype) + { + dev_type = UDEV_INPUT_KEYBOARD; + cb = udev_handle_keyboard; + } + else if (val_mouse && string_is_equal_fast(val_mouse, "1", 1) && devnode) + { + dev_type = UDEV_INPUT_MOUSE; + cb = udev_handle_mouse; + } + else if (val_touchpad && string_is_equal_fast(val_touchpad, "1", 1) && devnode) + { + dev_type = UDEV_INPUT_TOUCHPAD; + cb = udev_handle_touchpad; + } + else goto end; if (string_is_equal_fast(action, "add", 3)) { - device_handle_cb cb = NULL; - if (string_is_equal_fast(devtype, "keyboard", 8)) - cb = udev_handle_keyboard; - else if (string_is_equal_fast(devtype, "touchpad", 8)) - cb = udev_handle_touchpad; - else if (string_is_equal_fast(devtype, "mouse", 5)) - cb = udev_handle_mouse; - - RARCH_LOG("[udev]: Hotplug add %s: %s.\n", devtype, devnode); - udev_input_add_device(udev, devnode, cb); + RARCH_LOG("[udev]: Hotplug add %s: %s.\n", g_dev_type_str[dev_type], devnode); + udev_input_add_device(udev, dev_type, devnode, cb); } else if (string_is_equal_fast(action, "remove", 6)) { - RARCH_LOG("[udev]: Hotplug remove %s: %s.\n", devtype, devnode); + RARCH_LOG("[udev]: Hotplug remove %s: %s.\n", g_dev_type_str[dev_type], devnode); udev_input_remove_device(udev, devnode); } @@ -404,14 +422,21 @@ static void udev_input_poll(void *data) { int i, ret; struct epoll_event events[32]; + udev_input_mouse_t *mouse; udev_input_t *udev = (udev_input_t*)data; if (!udev) return; - udev->mouse_x = udev->mouse_y = 0; - udev->mouse_wu = udev->mouse_wd = 0; - udev->mouse_whu = udev->mouse_whd = 0; + for (i = 0; i < udev->num_devices; ++i) + { + if (udev->devices[i]->type == UDEV_INPUT_MOUSE) + { + mouse = &udev->devices[i]->state.mouse; + mouse->x = mouse->y = 0; + mouse->wu = mouse->wd = mouse->whu = mouse->whd = false; + } + } while (udev->monitor && udev_hotplug_available(udev->monitor)) udev_input_handle_hotplug(udev); @@ -439,51 +464,87 @@ static void udev_input_poll(void *data) udev->joypad->poll(); } -static int16_t udev_mouse_state(udev_input_t *udev, unsigned id) +static int16_t udev_mouse_state(udev_input_t *udev, unsigned port, unsigned id) { + unsigned i, j; + udev_input_mouse_t *mouse = NULL; + + for (i = j = 0; i < udev->num_devices; ++i) + { + if (udev->devices[i]->type != UDEV_INPUT_MOUSE) + continue; + if (j == port) + { + mouse = &udev->devices[i]->state.mouse; + break; + } + ++j; + } + + if (!mouse) + return 0; + switch (id) { case RETRO_DEVICE_ID_MOUSE_X: - return udev->mouse_x; + return mouse->x; case RETRO_DEVICE_ID_MOUSE_Y: - return udev->mouse_y; + return mouse->y; case RETRO_DEVICE_ID_MOUSE_LEFT: - return udev->mouse_l; + return mouse->l; case RETRO_DEVICE_ID_MOUSE_RIGHT: - return udev->mouse_r; + return mouse->r; case RETRO_DEVICE_ID_MOUSE_MIDDLE: - return udev->mouse_m; + return mouse->m; case RETRO_DEVICE_ID_MOUSE_WHEELUP: - return udev->mouse_wu; + return mouse->wu; case RETRO_DEVICE_ID_MOUSE_WHEELDOWN: - return udev->mouse_wd; + return mouse->wd; case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP: - return udev->mouse_whu; + return mouse->whu; case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN: - return udev->mouse_whd; + return mouse->whd; } return 0; } -static int16_t udev_lightgun_state(udev_input_t *udev, unsigned id) +static int16_t udev_lightgun_state(udev_input_t *udev, unsigned port, unsigned id) { + unsigned i, j; + udev_input_mouse_t *mouse = NULL; + + for (i = j = 0; i < udev->num_devices; ++i) + { + if (udev->devices[i]->type != UDEV_INPUT_MOUSE) + continue; + if (j == port) + { + mouse = &udev->devices[i]->state.mouse; + break; + } + ++j; + } + + if (!mouse) + return 0; + switch (id) { case RETRO_DEVICE_ID_LIGHTGUN_X: - return udev->mouse_x; + return mouse->x; case RETRO_DEVICE_ID_LIGHTGUN_Y: - return udev->mouse_y; + return mouse->y; case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: - return udev->mouse_l; + return mouse->l; case RETRO_DEVICE_ID_LIGHTGUN_CURSOR: - return udev->mouse_m; + return mouse->m; case RETRO_DEVICE_ID_LIGHTGUN_TURBO: - return udev->mouse_r; + return mouse->r; case RETRO_DEVICE_ID_LIGHTGUN_START: - return udev->mouse_m && udev->mouse_r; + return mouse->m && mouse->r; case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: - return udev->mouse_m && udev->mouse_l; + return mouse->m && mouse->l; } return 0; @@ -509,9 +570,10 @@ static int16_t udev_analog_pressed(const struct retro_keybind *binds, unsigned i } static int16_t udev_pointer_state(udev_input_t *udev, - unsigned idx, unsigned id, bool screen) + unsigned port, unsigned id, bool screen) { struct video_viewport vp; + unsigned i, j; bool inside = false; int16_t res_x = 0; int16_t res_y = 0; @@ -525,8 +587,25 @@ static int16_t udev_pointer_state(udev_input_t *udev, vp.full_width = 0; vp.full_height = 0; - if (!(video_driver_translate_coord_viewport_wrap(&vp, udev->mouse_x, udev->mouse_y, - &res_x, &res_y, &res_screen_x, &res_screen_y))) + udev_input_mouse_t *mouse = NULL; + + for (i = j = 0; i < udev->num_devices; ++i) + { + if (udev->devices[i]->type != UDEV_INPUT_MOUSE) + continue; + if (j == port) + { + mouse = &udev->devices[i]->state.mouse; + break; + } + ++j; + } + + if (!mouse) + return 0; + + if (!(video_driver_translate_coord_viewport_wrap(&vp, + mouse->x, mouse->y, &res_x, &res_y, &res_screen_x, &res_screen_y))) return 0; if (screen) @@ -547,7 +626,7 @@ static int16_t udev_pointer_state(udev_input_t *udev, case RETRO_DEVICE_ID_POINTER_Y: return res_y; case RETRO_DEVICE_ID_POINTER_PRESSED: - return udev->mouse_l; + return mouse->l; } return 0; @@ -582,16 +661,14 @@ static int16_t udev_input_state(void *data, bit = input_keymaps_translate_rk_to_keysym((enum retro_key)id); return id < RETROK_LAST && BIT_GET(udev_key_state, bit); case RETRO_DEVICE_MOUSE: - return udev_mouse_state(udev, id); + return udev_mouse_state(udev, port, id); case RETRO_DEVICE_POINTER: + return udev_pointer_state(udev, port, id, false); case RARCH_DEVICE_POINTER_SCREEN: - if (idx == 0) - return udev_pointer_state(udev, idx, id, - device == RARCH_DEVICE_POINTER_SCREEN); - break; + return udev_pointer_state(udev, port, id, true); case RETRO_DEVICE_LIGHTGUN: - return udev_lightgun_state(udev, id); + return udev_lightgun_state(udev, port, id); } return 0; @@ -632,8 +709,10 @@ static void udev_input_free(void *data) free(udev); } -static bool open_devices(udev_input_t *udev, const char *type, device_handle_cb cb) +static bool open_devices(udev_input_t *udev, + enum udev_input_dev_type type, device_handle_cb cb) { + const char *type_str = g_dev_type_str[type]; struct udev_list_entry *devs = NULL; struct udev_list_entry *item = NULL; struct udev_enumerate *enumerate = udev_enumerate_new(udev->udev); @@ -641,7 +720,7 @@ static bool open_devices(udev_input_t *udev, const char *type, device_handle_cb if (!enumerate) return false; - udev_enumerate_add_match_property(enumerate, type, "1"); + udev_enumerate_add_match_property(enumerate, type_str, "1"); udev_enumerate_scan_devices(enumerate); devs = udev_enumerate_get_list_entry(enumerate); @@ -658,8 +737,8 @@ static bool open_devices(udev_input_t *udev, const char *type, device_handle_cb { int fd = open(devnode, O_RDONLY | O_NONBLOCK); - RARCH_LOG("[udev] Adding device %s as type %s.\n", devnode, type); - if (!udev_input_add_device(udev, devnode, cb)) + RARCH_LOG("[udev] Adding device %s as type %s.\n", devnode, type_str); + if (!udev_input_add_device(udev, type, devnode, cb)) RARCH_ERR("[udev] Failed to open device: %s (%s).\n", devnode, strerror(errno)); close(fd); } @@ -703,19 +782,19 @@ static void *udev_input_init(const char *joypad_driver) goto error; } - if (!open_devices(udev, "ID_INPUT_KEYBOARD", udev_handle_keyboard)) + if (!open_devices(udev, UDEV_INPUT_KEYBOARD, udev_handle_keyboard)) { RARCH_ERR("Failed to open keyboard.\n"); goto error; } - if (!open_devices(udev, "ID_INPUT_MOUSE", udev_handle_mouse)) + if (!open_devices(udev, UDEV_INPUT_MOUSE, udev_handle_mouse)) { RARCH_ERR("Failed to open mouse.\n"); goto error; } - if (!open_devices(udev, "ID_INPUT_TOUCHPAD", udev_handle_touchpad)) + if (!open_devices(udev, UDEV_INPUT_TOUCHPAD, udev_handle_touchpad)) { RARCH_ERR("Failed to open touchpads.\n"); goto error;