diff --git a/input/input_common.c b/input/input_common.c index 92090205d0..48be176d96 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -37,8 +37,13 @@ static const rarch_joypad_driver_t *joypad_drivers[] = { const rarch_joypad_driver_t *input_joypad_find_driver(const char *ident) { for (unsigned i = 0; i < sizeof(joypad_drivers) / sizeof(joypad_drivers[0]); i++) + { if (strcmp(ident, joypad_drivers[i]->ident) == 0) + { + RARCH_LOG("Found joypad driver: %s\n", joypad_drivers[i]->ident); return joypad_drivers[i]; + } + } return NULL; } @@ -46,8 +51,13 @@ const rarch_joypad_driver_t *input_joypad_find_driver(const char *ident) const rarch_joypad_driver_t *input_joypad_init_first(void) { for (unsigned i = 0; i < sizeof(joypad_drivers) / sizeof(joypad_drivers[0]); i++) + { if (joypad_drivers[i]->init()) + { + RARCH_LOG("Found joypad driver: %s\n", joypad_drivers[i]->ident); return joypad_drivers[i]; + } + } return NULL; } diff --git a/input/linuxraw_joypad.c b/input/linuxraw_joypad.c new file mode 100644 index 0000000000..43624b3b18 --- /dev/null +++ b/input/linuxraw_joypad.c @@ -0,0 +1,140 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "input_common.h" +#include "../general.h" +#include +#include +#include +#include + +#define NUM_BUTTONS 32 +#define NUM_AXES 32 + +struct linuxraw_joypad +{ + int fd; + bool buttons[NUM_BUTTONS]; + int16_t axes[NUM_AXES]; +}; + +static struct linuxraw_joypad g_pads[MAX_PLAYERS]; + +static bool linuxraw_joypad_init(void) +{ + bool has_pad = false; + + for (unsigned i = 0; i < MAX_PLAYERS; i++) + { + struct linuxraw_joypad *pad = &g_pads[i]; + + char path[PATH_MAX]; + snprintf(path, sizeof(path), "/dev/input/js%u", i); + pad->fd = open(path, O_RDONLY | O_NONBLOCK); + + has_pad |= pad->fd >= 0; + } + + return has_pad; +} + +static void linuxraw_joypad_destroy(void) +{ + for (unsigned i = 0; i < MAX_PLAYERS; i++) + { + if (g_pads[i].fd >= 0) + close(g_pads[i].fd); + } + + memset(g_pads, 0, sizeof(g_pads)); + for (unsigned i = 0; i < MAX_PLAYERS; i++) + g_pads[i].fd = -1; +} + +static bool linuxraw_joypad_button(unsigned port, uint16_t joykey) +{ + const struct linuxraw_joypad *pad = &g_pads[port]; + + return joykey < NUM_BUTTONS && pad->buttons[joykey]; +} + +static int16_t linuxraw_joypad_axis(unsigned port, uint32_t joyaxis) +{ + if (joyaxis == AXIS_NONE) + return 0; + + const struct linuxraw_joypad *pad = &g_pads[port]; + + int16_t val = 0; + if (AXIS_NEG_GET(joyaxis) < NUM_AXES) + { + val = pad->axes[AXIS_NEG_GET(joyaxis)]; + if (val > 0) + val = 0; + // Kernel returns values in range [-0x7fff, 0x7fff]. + } + else if (AXIS_POS_GET(joyaxis) < NUM_AXES) + { + val = pad->axes[AXIS_POS_GET(joyaxis)]; + if (val < 0) + val = 0; + } + + return val; +} + +static void poll_pad(struct linuxraw_joypad *pad) +{ + struct js_event event; + while (read(pad->fd, &event, sizeof(event)) == (ssize_t)sizeof(event)) + { + unsigned type = event.type & ~JS_EVENT_INIT; + + switch (type) + { + case JS_EVENT_BUTTON: + if (event.number < NUM_BUTTONS) + pad->buttons[event.number] = event.value; + break; + + case JS_EVENT_AXIS: + if (event.number < NUM_AXES) + pad->axes[event.number] = event.value; + break; + } + } +} + +static void linuxraw_joypad_poll(void) +{ + for (unsigned i = 0; i < MAX_PLAYERS; i++) + { + struct linuxraw_joypad *pad = &g_pads[i]; + if (pad->fd < 0) + continue; + + poll_pad(pad); + } +} + +const rarch_joypad_driver_t linuxraw_joypad = { + linuxraw_joypad_init, + linuxraw_joypad_destroy, + linuxraw_joypad_button, + linuxraw_joypad_axis, + linuxraw_joypad_poll, + "linuxraw", +}; + diff --git a/input/sdl_input.c b/input/sdl_input.c index b941be7003..992d7ec335 100644 --- a/input/sdl_input.c +++ b/input/sdl_input.c @@ -141,11 +141,6 @@ static void *sdl_input_init(void) return NULL; sdl->joypad = input_joypad_init_first(); - if (sdl->joypad) - RARCH_LOG("SDL: Found joypad driver: %s\n", sdl->joypad->ident); - else - RARCH_WARN("SDL: Didn't find suitable input driver.\n"); - return sdl; } @@ -300,6 +295,7 @@ static void sdl_input_poll(void *data) SDL_PumpEvents(); sdl_input_t *sdl = (sdl_input_t*)data; + input_joypad_poll(sdl->joypad); sdl_poll_mouse(sdl); }