diff --git a/CMakeLists.txt b/CMakeLists.txt index 78e409990..d378d36c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1266,6 +1266,7 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS) endif() # Always compiled for Linux, unconditionally: + set(SOURCE_FILES ${SOURCE_FILES} "${SDL2_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c") set(SOURCE_FILES ${SOURCE_FILES} "${SDL2_SOURCE_DIR}/src/core/linux/SDL_threadprio.c") # src/core/unix/*.c is included in a generic if(UNIX) section, elsewhere. diff --git a/configure b/configure index d52252133..458d37926 100755 --- a/configure +++ b/configure @@ -24838,9 +24838,11 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h fi # Set up files for evdev input if test x$use_input_events = xyes; then - SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev*.c" + SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev.c" + SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev_kbd.c" fi # Set up other core UNIX files + SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev_capabilities.c" SOURCES="$SOURCES $srcdir/src/core/linux/SDL_threadprio.c" SOURCES="$SOURCES $srcdir/src/core/unix/*.c" ;; diff --git a/configure.ac b/configure.ac index c9c0295ec..550af8503 100644 --- a/configure.ac +++ b/configure.ac @@ -3658,9 +3658,11 @@ case "$host" in fi # Set up files for evdev input if test x$use_input_events = xyes; then - SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev*.c" + SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev.c" + SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev_kbd.c" fi # Set up other core UNIX files + SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev_capabilities.c" SOURCES="$SOURCES $srcdir/src/core/linux/SDL_threadprio.c" SOURCES="$SOURCES $srcdir/src/core/unix/*.c" ;; diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index f7c376aad..1fdf24111 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -44,6 +44,7 @@ #include "SDL_scancode.h" #include "../../events/SDL_events_c.h" #include "../../events/scancodes_linux.h" /* adds linux_scancode_table */ +#include "../../core/linux/SDL_evdev_capabilities.h" #include "../../core/linux/SDL_udev.h" /* These are not defined in older Linux kernel headers */ diff --git a/src/core/linux/SDL_evdev_capabilities.c b/src/core/linux/SDL_evdev_capabilities.c new file mode 100644 index 000000000..d96b9edb6 --- /dev/null +++ b/src/core/linux/SDL_evdev_capabilities.c @@ -0,0 +1,80 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Collabora Ltd. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_evdev_capabilities.h" + +#if HAVE_LIBUDEV_H + +extern int +SDL_EVDEV_GuessDeviceClass(unsigned long bitmask_ev[NBITS(EV_MAX)], + unsigned long bitmask_abs[NBITS(ABS_MAX)], + unsigned long bitmask_key[NBITS(KEY_MAX)], + unsigned long bitmask_rel[NBITS(REL_MAX)]) +{ + int devclass = 0; + unsigned long keyboard_mask; + + if (test_bit(EV_ABS, bitmask_ev) && + test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs)) { + if (test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key)) { + ; /* ID_INPUT_TABLET */ + } else if (test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key)) { + ; /* ID_INPUT_TOUCHPAD */ + } else if (test_bit(BTN_MOUSE, bitmask_key)) { + devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */ + } else if (test_bit(BTN_TOUCH, bitmask_key)) { + /* TODO: better determining between touchscreen and multitouch touchpad, + see https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-input_id.c */ + devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; /* ID_INPUT_TOUCHSCREEN */ + } + + if (test_bit(BTN_TRIGGER, bitmask_key) || + test_bit(BTN_A, bitmask_key) || + test_bit(BTN_1, bitmask_key) || + test_bit(ABS_RX, bitmask_abs) || + test_bit(ABS_RY, bitmask_abs) || + test_bit(ABS_RZ, bitmask_abs) || + test_bit(ABS_THROTTLE, bitmask_abs) || + test_bit(ABS_RUDDER, bitmask_abs) || + test_bit(ABS_WHEEL, bitmask_abs) || + test_bit(ABS_GAS, bitmask_abs) || + test_bit(ABS_BRAKE, bitmask_abs)) { + devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */ + } + } + + if (test_bit(EV_REL, bitmask_ev) && + test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel) && + test_bit(BTN_MOUSE, bitmask_key)) { + devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */ + } + + /* the first 32 bits are ESC, numbers, and Q to D; if we have any of + * those, consider it a keyboard device; do not test KEY_RESERVED, though */ + keyboard_mask = 0xFFFFFFFE; + if ((bitmask_key[0] & keyboard_mask) != 0) + devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEYBOARD */ + + return devclass; +} + +#endif diff --git a/src/core/linux/SDL_evdev_capabilities.h b/src/core/linux/SDL_evdev_capabilities.h new file mode 100644 index 000000000..cef151331 --- /dev/null +++ b/src/core/linux/SDL_evdev_capabilities.h @@ -0,0 +1,58 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + Copyright (C) 2020 Collabora Ltd. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#ifndef SDL_evdev_capabilities_h_ +#define SDL_evdev_capabilities_h_ + +#if HAVE_LIBUDEV_H + +#include + +/* A device can be any combination of these classes */ +typedef enum +{ + SDL_UDEV_DEVICE_UNKNOWN = 0x0000, + SDL_UDEV_DEVICE_MOUSE = 0x0001, + SDL_UDEV_DEVICE_KEYBOARD = 0x0002, + SDL_UDEV_DEVICE_JOYSTICK = 0x0004, + SDL_UDEV_DEVICE_SOUND = 0x0008, + SDL_UDEV_DEVICE_TOUCHSCREEN = 0x0010 +} SDL_UDEV_deviceclass; + +#define BITS_PER_LONG (sizeof(unsigned long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define EVDEV_OFF(x) ((x)%BITS_PER_LONG) +#define EVDEV_LONG(x) ((x)/BITS_PER_LONG) +#define test_bit(bit, array) ((array[EVDEV_LONG(bit)] >> EVDEV_OFF(bit)) & 1) + +extern int SDL_EVDEV_GuessDeviceClass(unsigned long bitmask_ev[NBITS(EV_MAX)], + unsigned long bitmask_abs[NBITS(ABS_MAX)], + unsigned long bitmask_key[NBITS(KEY_MAX)], + unsigned long bitmask_rel[NBITS(REL_MAX)]); + +#endif /* HAVE_LIBUDEV_H */ + +#endif /* SDL_evdev_capabilities_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index 9c9e9503f..b45ed10e4 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -32,6 +32,7 @@ #include #include "SDL_assert.h" +#include "SDL_evdev_capabilities.h" #include "SDL_loadso.h" #include "SDL_timer.h" #include "SDL_hints.h" @@ -291,12 +292,6 @@ SDL_UDEV_LoadLibrary(void) return retval; } -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define OFF(x) ((x)%BITS_PER_LONG) -#define LONG(x) ((x)/BITS_PER_LONG) -#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) - static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len) { const char *value; @@ -330,13 +325,11 @@ static void get_caps(struct udev_device *dev, struct udev_device *pdev, const ch static int guess_device_class(struct udev_device *dev) { - int devclass = 0; struct udev_device *pdev; unsigned long bitmask_ev[NBITS(EV_MAX)]; unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)]; unsigned long bitmask_rel[NBITS(REL_MAX)]; - unsigned long keyboard_mask; /* walk up the parental chain until we find the real input device; the * argument is very likely a subdevice of this, like eventN */ @@ -353,48 +346,10 @@ guess_device_class(struct udev_device *dev) get_caps(dev, pdev, "capabilities/rel", bitmask_rel, SDL_arraysize(bitmask_rel)); get_caps(dev, pdev, "capabilities/key", bitmask_key, SDL_arraysize(bitmask_key)); - if (test_bit(EV_ABS, bitmask_ev) && - test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs)) { - if (test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key)) { - ; /* ID_INPUT_TABLET */ - } else if (test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key)) { - ; /* ID_INPUT_TOUCHPAD */ - } else if (test_bit(BTN_MOUSE, bitmask_key)) { - devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */ - } else if (test_bit(BTN_TOUCH, bitmask_key)) { - /* TODO: better determining between touchscreen and multitouch touchpad, - see https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-input_id.c */ - devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; /* ID_INPUT_TOUCHSCREEN */ - } - - if (test_bit(BTN_TRIGGER, bitmask_key) || - test_bit(BTN_A, bitmask_key) || - test_bit(BTN_1, bitmask_key) || - test_bit(ABS_RX, bitmask_abs) || - test_bit(ABS_RY, bitmask_abs) || - test_bit(ABS_RZ, bitmask_abs) || - test_bit(ABS_THROTTLE, bitmask_abs) || - test_bit(ABS_RUDDER, bitmask_abs) || - test_bit(ABS_WHEEL, bitmask_abs) || - test_bit(ABS_GAS, bitmask_abs) || - test_bit(ABS_BRAKE, bitmask_abs)) { - devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */ - } - } - - if (test_bit(EV_REL, bitmask_ev) && - test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel) && - test_bit(BTN_MOUSE, bitmask_key)) { - devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */ - } - - /* the first 32 bits are ESC, numbers, and Q to D; if we have any of - * those, consider it a keyboard device; do not test KEY_RESERVED, though */ - keyboard_mask = 0xFFFFFFFE; - if ((bitmask_key[0] & keyboard_mask) != 0) - devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEYBOARD */ - - return devclass; + return SDL_EVDEV_GuessDeviceClass(&bitmask_ev[0], + &bitmask_abs[0], + &bitmask_key[0], + &bitmask_rel[0]); } static void diff --git a/src/core/linux/SDL_udev.h b/src/core/linux/SDL_udev.h index e61085379..83b4610c8 100644 --- a/src/core/linux/SDL_udev.h +++ b/src/core/linux/SDL_udev.h @@ -46,17 +46,6 @@ typedef enum SDL_UDEV_DEVICEREMOVED } SDL_UDEV_deviceevent; -/* A device can be any combination of these classes */ -typedef enum -{ - SDL_UDEV_DEVICE_UNKNOWN = 0x0000, - SDL_UDEV_DEVICE_MOUSE = 0x0001, - SDL_UDEV_DEVICE_KEYBOARD = 0x0002, - SDL_UDEV_DEVICE_JOYSTICK = 0x0004, - SDL_UDEV_DEVICE_SOUND = 0x0008, - SDL_UDEV_DEVICE_TOUCHSCREEN = 0x0010 -} SDL_UDEV_deviceclass; - typedef void (*SDL_UDEV_Callback)(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath); typedef struct SDL_UDEV_CallbackList { diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 81ea0bf62..6e9533b66 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -28,6 +28,7 @@ #include "SDL_joystick.h" #include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */ #include "../../joystick/linux/SDL_sysjoystick_c.h" /* For joystick hwdata */ +#include "../../core/linux/SDL_evdev_capabilities.h" #include "../../core/linux/SDL_udev.h" #include /* close */ @@ -86,8 +87,6 @@ static SDL_hapticlist_item *SDL_hapticlist = NULL; static SDL_hapticlist_item *SDL_hapticlist_tail = NULL; static int numhaptics = 0; -#define test_bit(nr, addr) \ - (((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0) #define EV_TEST(ev,f) \ if (test_bit((ev), features)) ret |= (f); /* diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 0d1079912..a94bfe39f 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -78,6 +78,7 @@ #define BTN_DPAD_RIGHT 0x223 #endif +#include "../../core/linux/SDL_evdev_capabilities.h" #include "../../core/linux/SDL_udev.h" #if 0 @@ -124,10 +125,6 @@ static int numjoysticks = 0; static Uint32 last_joy_detect_time; static time_t last_input_dir_mtime; -#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 void FixupDeviceInfoForMapping(int fd, struct input_id *inpid) {