Merge pull request #5010 from casdevel/udev

Add multiple mice support to udev input driver
This commit is contained in:
Twinaphex 2017-06-02 16:45:13 +02:00 committed by GitHub
commit a8f1831a62
2 changed files with 195 additions and 100 deletions

View File

@ -36,6 +36,9 @@
#endif
#include <string/stdstring.h>
#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;
}

View File

@ -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;