Merge pull request #3471 from Hinsbart/remove_libevdev

remove dependancy on libevdev
This commit is contained in:
punto- 2016-01-27 04:32:27 -03:00
commit 93bef9b9b1
3 changed files with 135 additions and 105 deletions

View file

@ -158,18 +158,14 @@ def configure(env):
if (env["gamepad"]=="yes" and platform.system() == "Linux"): if (env["gamepad"]=="yes" and platform.system() == "Linux"):
# pkg-config returns 0 when the lib exists... # pkg-config returns 0 when the lib exists...
found_udev = not os.system("pkg-config --exists libudev") found_udev = not os.system("pkg-config --exists libudev")
found_evdev = not os.system("pkg-config --exists libevdev")
if (found_udev and found_evdev): if (found_udev):
print("Enabling gamepad support with udev/evdev") print("Enabling gamepad support with udev")
env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"]) env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"])
env.ParseConfig('pkg-config libudev --cflags --libs') env.ParseConfig('pkg-config libudev --cflags --libs')
env.ParseConfig('pkg-config libevdev --cflags --libs')
else: else:
if (not found_udev): print("libudev development libraries not found")
print("libudev development libraries not found")
if (not found_evdev):
print("libevdev development libraries not found")
print("Some libraries are missing for the required gamepad support, aborting!") print("Some libraries are missing for the required gamepad support, aborting!")
print("Install the mentioned libraries or build with 'gamepad=no' to disable gamepad support.") print("Install the mentioned libraries or build with 'gamepad=no' to disable gamepad support.")
sys.exit(255) sys.exit(255)

View file

@ -31,22 +31,34 @@
#ifdef JOYDEV_ENABLED #ifdef JOYDEV_ENABLED
#include "joystick_linux.h" #include "joystick_linux.h"
#include "print_string.h"
#include <libevdev/libevdev.h> #include <linux/input.h>
#include <libudev.h> #include <libudev.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <cstring>
#define test_bit(nr, addr) (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
#define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
static const char* ignore_str = "/dev/input/js"; static const char* ignore_str = "/dev/input/js";
joystick_linux::Joystick::Joystick() { joystick_linux::Joystick::Joystick() {
fd = -1; fd = -1;
dpad = 0; dpad = 0;
dev = NULL;
devpath = ""; devpath = "";
for (int i = 0; i < MAX_ABS; i++) {
abs_info[i] = NULL;
}
}
joystick_linux::Joystick::~Joystick() {
for (int i = 0; i < MAX_ABS; i++) {
if (abs_info[i]) {
memdelete(abs_info[i]);
}
}
} }
void joystick_linux::Joystick::reset() { void joystick_linux::Joystick::reset() {
@ -112,10 +124,14 @@ void joystick_linux::enumerate_joysticks(udev *p_udev) {
dev = udev_device_new_from_syspath(p_udev, path); dev = udev_device_new_from_syspath(p_udev, path);
const char* devnode = udev_device_get_devnode(dev); const char* devnode = udev_device_get_devnode(dev);
if (devnode != NULL && strstr(devnode, ignore_str) == NULL) { if (devnode) {
joy_mutex->lock();
open_joystick(devnode); String devnode_str = devnode;
joy_mutex->unlock(); if (devnode_str.find(ignore_str) == -1) {
joy_mutex->lock();
open_joystick(devnode);
joy_mutex->unlock();
}
} }
udev_device_unref(dev); udev_device_unref(dev);
} }
@ -146,22 +162,24 @@ void joystick_linux::monitor_joysticks(udev *p_udev) {
/* Check if our file descriptor has received data. */ /* Check if our file descriptor has received data. */
if (ret > 0 && FD_ISSET(fd, &fds)) { if (ret > 0 && FD_ISSET(fd, &fds)) {
/* Make the call to receive the device. /* Make the call to receive the device.
select() ensured that this will not block. */ select() ensured that this will not block. */
dev = udev_monitor_receive_device(mon); dev = udev_monitor_receive_device(mon);
if (dev && udev_device_get_devnode(dev) != 0) { if (dev && udev_device_get_devnode(dev) != 0) {
joy_mutex->lock(); joy_mutex->lock();
const char* action = udev_device_get_action(dev); String action = udev_device_get_action(dev);
const char* devnode = udev_device_get_devnode(dev); const char* devnode = udev_device_get_devnode(dev);
if (devnode) {
if (strstr(devnode, ignore_str) == NULL) { String devnode_str = devnode;
if (devnode_str.find(ignore_str) == -1) {
if (strcmp(action, "add") == 0) if (action == "add")
open_joystick(devnode); open_joystick(devnode);
else if (String(action) == "remove")
else if (strcmp(action, "remove") == 0) close_joystick(get_joy_from_path(devnode));
close_joystick(get_joy_from_path(devnode)); }
} }
udev_device_unref(dev); udev_device_unref(dev);
@ -208,7 +226,6 @@ void joystick_linux::close_joystick(int p_id) {
if (joy.fd != -1) { if (joy.fd != -1) {
libevdev_free(joy.dev);
close(joy.fd); close(joy.fd);
joy.fd = -1; joy.fd = -1;
input->joy_connection_changed(p_id, false, ""); input->joy_connection_changed(p_id, false, "");
@ -230,21 +247,27 @@ static String _hex_str(uint8_t p_byte) {
void joystick_linux::setup_joystick_properties(int p_id) { void joystick_linux::setup_joystick_properties(int p_id) {
Joystick* joy = &joysticks[p_id]; Joystick* joy = &joysticks[p_id];
libevdev* dev = joy->dev;
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
int num_buttons = 0; int num_buttons = 0;
int num_axes = 0; int num_axes = 0;
if ((ioctl(joy->fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
(ioctl(joy->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
return;
}
for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) { for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
if (libevdev_has_event_code(dev, EV_KEY, i)) { if (test_bit(i, keybit)) {
joy->key_map[i] = num_buttons++; joy->key_map[i] = num_buttons++;
} }
} }
for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) { for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
if (libevdev_has_event_code(dev, EV_KEY, i)) { if (test_bit(i, keybit)) {
joy->key_map[i] = num_buttons++; joy->key_map[i] = num_buttons++;
} }
@ -255,68 +278,82 @@ void joystick_linux::setup_joystick_properties(int p_id) {
i = ABS_HAT3Y; i = ABS_HAT3Y;
continue; continue;
} }
if (libevdev_has_event_code(dev, EV_ABS, i)) { if (test_bit(i, absbit)) {
joy->abs_map[i] = num_axes++; joy->abs_map[i] = num_axes++;
joy->abs_info[i] = memnew(input_absinfo);
if (ioctl(joy->fd, EVIOCGABS(i), joy->abs_info[i]) < 0) {
memdelete(joy->abs_info[i]);
joy->abs_info[i] = NULL;
}
} }
} }
} }
void joystick_linux::open_joystick(const char *p_path) { void joystick_linux::open_joystick(const char *p_path) {
int joy_num = get_free_joy_slot(); int joy_num = get_free_joy_slot();
int fd = open(p_path, O_RDONLY | O_NONBLOCK); int fd = open(p_path, O_RDONLY | O_NONBLOCK);
if (fd != -1 && joy_num != -1) { if (fd != -1 && joy_num != -1) {
int rc = libevdev_new_from_fd(fd, &joysticks[joy_num].dev); unsigned long evbit[NBITS(EV_MAX)] = { 0 };
if (rc < 0) { unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc)); if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
(ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
(ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
return; return;
} }
libevdev *dev = joysticks[joy_num].dev;
//check if the device supports basic gamepad events, prevents certain keyboards from //check if the device supports basic gamepad events, prevents certain keyboards from
//being detected as joysticks //being detected as joysticks
if (libevdev_has_event_type(dev, EV_ABS) && libevdev_has_event_type(dev, EV_KEY) && if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
(libevdev_has_event_code(dev, EV_KEY, BTN_A) || libevdev_has_event_code(dev, EV_KEY, BTN_THUMBL) || libevdev_has_event_code(dev, EV_KEY, BTN_TOP))) { ((test_bit(ABS_X, absbit) || test_bit(ABS_Y, absbit)) ||
(test_bit(BTN_A, keybit) || test_bit(BTN_THUMBL, keybit))))) {
close(fd);
return;
}
char uid[128]; char uid[128];
String name = libevdev_get_name(dev); char namebuf[128];
uint16_t bus = __bswap_16(libevdev_get_id_bustype(dev)); String name = "";
uint16_t vendor = __bswap_16(libevdev_get_id_vendor(dev)); input_id inpid;
uint16_t product = __bswap_16(libevdev_get_id_product(dev)); if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) >= 0) {
uint16_t version = __bswap_16(libevdev_get_id_version(dev)); name = namebuf;
}
joysticks[joy_num].reset(); if (ioctl(fd, EVIOCGID, &inpid) < 0) {
close(fd);
return;
}
Joystick &joy = joysticks[joy_num]; joysticks[joy_num].reset();
joy.fd = fd;
joy.devpath = String(p_path);
setup_joystick_properties(joy_num);
sprintf(uid, "%04x%04x", bus, 0);
if (vendor && product && version) {
sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor,0,product,0,version,0); Joystick &joy = joysticks[joy_num];
input->joy_connection_changed(joy_num, true, name, uid); joy.fd = fd;
} joy.devpath = String(p_path);
else { setup_joystick_properties(joy_num);
String uidname = uid; sprintf(uid, "%04x%04x", __bswap_16(inpid.bustype), 0);
int uidlen = MIN(name.length(), 11); if (inpid.vendor && inpid.product && inpid.version) {
for (int i=0; i<uidlen; i++) {
uidname = uidname + _hex_str(name[i]); uint16_t vendor = __bswap_16(inpid.vendor);
} uint16_t product = __bswap_16(inpid.product);
uidname += "00"; uint16_t version = __bswap_16(inpid.version);
input->joy_connection_changed(joy_num, true, name, uidname);
} sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor,0,product,0,version,0);
input->joy_connection_changed(joy_num, true, name, uid);
} }
else { else {
//device is not a gamepad, clean up String uidname = uid;
libevdev_free(dev); int uidlen = MIN(name.length(), 11);
close(fd); for (int i=0; i<uidlen; i++) {
uidname = uidname + _hex_str(name[i]);
}
uidname += "00";
input->joy_connection_changed(joy_num, true, name, uidname);
} }
} }
} }
@ -350,58 +387,54 @@ uint32_t joystick_linux::process_joysticks(uint32_t p_event_id) {
if (joysticks[i].fd == -1) continue; if (joysticks[i].fd == -1) continue;
input_event ev; input_event events[32];
Joystick* joy = &joysticks[i]; Joystick* joy = &joysticks[i];
libevdev* dev = joy->dev;
int rc = 1;
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); int len;
if (rc < 0 && rc != -EAGAIN) { while ((len = read(joy->fd, events, (sizeof events))) > 0) {
continue; len /= sizeof(events[0]);
} for (int j = 0; j < len; j++) {
while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS) { input_event &ev = events[j];
switch (ev.type) {
switch (ev.type) { case EV_KEY:
case EV_KEY: p_event_id = input->joy_button(p_event_id, i, joy->key_map[ev.code], ev.value);
p_event_id = input->joy_button(p_event_id, i, joy->key_map[ev.code], ev.value);
break;
case EV_ABS:
switch (ev.code) {
case ABS_HAT0X:
if (ev.value != 0) {
if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_LEFT;
else joy->dpad |= InputDefault::HAT_MASK_RIGHT;
}
else joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT);
p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
break; break;
case ABS_HAT0Y: case EV_ABS:
if (ev.value != 0) {
if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_UP;
else joy->dpad |= InputDefault::HAT_MASK_DOWN;
}
else joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN);
p_event_id = input->joy_hat(p_event_id, i, joy->dpad); switch (ev.code) {
break; case ABS_HAT0X:
if (ev.value != 0) {
if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_LEFT;
else joy->dpad |= InputDefault::HAT_MASK_RIGHT;
}
else joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT);
default: p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
if (joy->abs_map[ev.code] != -1) { break;
InputDefault::JoyAxis value = axis_correct(libevdev_get_abs_info(dev, ev.code), ev.value);
joy->curr_axis[joy->abs_map[ev.code]] = value; case ABS_HAT0Y:
if (ev.value != 0) {
if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_UP;
else joy->dpad |= InputDefault::HAT_MASK_DOWN;
}
else joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN);
p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
break;
default:
if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) {
InputDefault::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value);
joy->curr_axis[joy->abs_map[ev.code]] = value;
}
break;
} }
break; break;
} }
break;
} }
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
} }
for (int j = 0; j < MAX_ABS; j++) { for (int j = 0; j < MAX_ABS; j++) {
int index = joy->abs_map[j]; int index = joy->abs_map[j];

View file

@ -61,9 +61,10 @@ private:
int fd; int fd;
String devpath; String devpath;
struct libevdev *dev; input_absinfo *abs_info[MAX_ABS];
Joystick(); Joystick();
~Joystick();
void reset(); void reset();
}; };