Improve sensor detection for Linux gamepad

This commit is contained in:
meyraud705 2023-05-13 18:25:45 +02:00 committed by Sam Lantinga
parent 000277060c
commit 9cfac88054
4 changed files with 55 additions and 15 deletions

View file

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

View file

@ -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_ */

View file

@ -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
*/

View file

@ -41,6 +41,7 @@
#include <dirent.h>
#include <linux/joystick.h>
#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);
}