diff --git a/src/SDL_utils.c b/src/SDL_utils.c index 653e671dfd..7401d1cbef 100644 --- a/src/SDL_utils.c +++ b/src/SDL_utils.c @@ -48,3 +48,16 @@ int SDL_powerof2(int x) return value; } + +SDL_bool SDL_endswith(const char *string, const char *suffix) +{ + size_t string_length = string ? SDL_strlen(string) : 0; + size_t suffix_length = suffix ? SDL_strlen(suffix) : 0; + + if (suffix_length > 0 && suffix_length <= string_length) { + if (SDL_memcmp(string + string_length - suffix_length, suffix, suffix_length) == 0) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} diff --git a/src/SDL_utils_c.h b/src/SDL_utils_c.h index 01fac8a36f..d4c8387e86 100644 --- a/src/SDL_utils_c.h +++ b/src/SDL_utils_c.h @@ -28,4 +28,6 @@ /* Return the smallest power of 2 greater than or equal to 'x' */ extern int SDL_powerof2(int x); +SDL_bool SDL_endswith(const char *string, const char *suffix); + #endif /* SDL_utils_h_ */ diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 3db54cc586..9671904a3f 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -22,6 +22,7 @@ /* This is the gamepad API for Simple DirectMedia Layer */ +#include "../SDL_utils_c.h" #include "SDL_sysjoystick.h" #include "SDL_joystick_c.h" #include "SDL_gamepad_c.h" @@ -2069,21 +2070,6 @@ SDL_bool SDL_IsGamepad(SDL_JoystickID instance_id) return retval; } -#ifdef __LINUX__ -static SDL_bool SDL_endswith(const char *string, const char *suffix) -{ - size_t string_length = string ? SDL_strlen(string) : 0; - size_t suffix_length = suffix ? SDL_strlen(suffix) : 0; - - if (suffix_length > 0 && suffix_length <= string_length) { - if (SDL_memcmp(string + string_length - suffix_length, suffix, suffix_length) == 0) { - return SDL_TRUE; - } - } - return SDL_FALSE; -} -#endif - /* * Return 1 if the gamepad should be ignored by SDL */ diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 35938df10f..160e209466 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -41,6 +41,7 @@ #include #include +#include "../../SDL_utils_c.h" #include "../../events/SDL_events_c.h" #include "../../core/linux/SDL_evdev.h" #include "../SDL_sysjoystick.h" @@ -323,6 +324,44 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick static int IsSensor(const char *path, int fd) { + struct input_id inpid; + char *name; + char product_string[128]; + + if (ioctl(fd, EVIOCGID, &inpid) < 0) { + return 0; + } + + if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) { + return 0; + } + + name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string); + if (name == NULL) { + return 0; + } + + if (SDL_endswith(name, " Motion Sensors")) { + /* PS3 and PS4 motion controls */ + SDL_free(name); + return 1; + } + if (SDL_strncmp(name, "Nintendo ", 9) == 0 && SDL_strstr(name, " IMU") != NULL) { + /* Nintendo Switch Joy-Con and Pro Controller IMU */ + SDL_free(name); + return 1; + } + if (SDL_endswith(name, " Accelerometer") || + SDL_endswith(name, " IR") || + SDL_endswith(name, " Motion Plus") || + SDL_endswith(name, " Nunchuk")) { + /* Wii extension controls */ + /* These may create 3 sensor devices but we only support reading from 1: ignore them */ + SDL_free(name); + return 0; + } + + SDL_free(name); return GuessIsSensor(fd); }