Revert "Back out Steam virtual gamepad changes"

This reverts commit 34eb24ebc4.
main
Sam Lantinga 2023-12-13 09:45:39 -08:00
parent b0e7b7db6f
commit e6d8ef1a5b
1 changed files with 114 additions and 17 deletions

View File

@ -156,6 +156,7 @@ typedef struct SDL_joylist_item
char *name; /* "SideWinder 3D Pro" or whatever */
SDL_JoystickGUID guid;
dev_t devnum;
int steam_virtual_gamepad_slot;
struct joystick_hwdata *hwdata;
struct SDL_joylist_item *next;
@ -219,6 +220,19 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version,
}
#endif /* SDL_JOYSTICK_HIDAPI */
static SDL_bool GetVirtualGamepadSlot(const char *name, int *slot)
{
const char *digits = SDL_strstr(name, "pad ");
if (digits) {
digits += 4;
if (SDL_isdigit(*digits)) {
*slot = SDL_atoi(digits);
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static int GuessDeviceClass(int fd)
{
unsigned long propbit[NBITS(INPUT_PROP_MAX)] = { 0 };
@ -259,7 +273,7 @@ static int GuessIsSensor(int fd)
return 0;
}
static int IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid)
static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vendor_return, Uint16 *product_return, SDL_JoystickGUID *guid)
{
struct input_id inpid;
char *name;
@ -312,6 +326,8 @@ static int IsJoystick(const char *path, int fd, char **name_return, SDL_Joystick
return 0;
}
*name_return = name;
*vendor_return = inpid.vendor;
*product_return = inpid.product;
return 1;
}
@ -389,6 +405,7 @@ static void MaybeAddDevice(const char *path)
struct stat sb;
int fd = -1;
char *name = NULL;
Uint16 vendor, product;
SDL_JoystickGUID guid;
SDL_joylist_item *item;
SDL_sensorlist_item *item_sensor;
@ -424,7 +441,7 @@ static void MaybeAddDevice(const char *path)
SDL_Log("Checking %s\n", path);
#endif
if (IsJoystick(path, fd, &name, &guid)) {
if (IsJoystick(path, fd, &name, &vendor, &product, &guid)) {
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("found joystick: %s\n", path);
#endif
@ -436,10 +453,16 @@ static void MaybeAddDevice(const char *path)
}
item->devnum = sb.st_rdev;
item->steam_virtual_gamepad_slot = -1;
item->path = SDL_strdup(path);
item->name = name;
item->guid = guid;
if (vendor == USB_VENDOR_VALVE &&
product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
GetVirtualGamepadSlot(item->name, &item->steam_virtual_gamepad_slot);
}
if ((!item->path) || (!item->name)) {
FreeJoylistItem(item);
goto done;
@ -832,6 +855,91 @@ static int SDLCALL sort_entries(const void *_a, const void *_b)
return numA - numB;
}
typedef struct
{
char *path;
int slot;
} VirtualGamepadEntry;
static int SDLCALL sort_virtual_gamepads(const void *_a, const void *_b)
{
const VirtualGamepadEntry *a = (const VirtualGamepadEntry *)_a;
const VirtualGamepadEntry *b = (const VirtualGamepadEntry *)_b;
return a->slot - b->slot;
}
static void LINUX_ScanSteamVirtualGamepads(void)
{
int i, count;
int fd;
struct dirent **entries = NULL;
char path[PATH_MAX];
char name[128];
struct input_id inpid;
int num_virtual_gamepads = 0;
int virtual_gamepad_slot;
VirtualGamepadEntry *virtual_gamepads = NULL;
count = scandir("/dev/input", &entries, filter_entries, NULL);
for (i = 0; i < count; ++i) {
(void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
fd = open(path, O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (ioctl(fd, EVIOCGID, &inpid) == 0 &&
inpid.vendor == USB_VENDOR_VALVE &&
inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD &&
ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0 &&
GetVirtualGamepadSlot(name, &virtual_gamepad_slot)) {
VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads));
if (new_virtual_gamepads) {
VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads];
entry->path = SDL_strdup(path);
entry->slot = virtual_gamepad_slot;
if (entry->path) {
virtual_gamepads = new_virtual_gamepads;
++num_virtual_gamepads;
} else {
SDL_free(entry->path);
SDL_free(new_virtual_gamepads);
}
}
}
close(fd);
}
free(entries[i]); /* This should NOT be SDL_free() */
}
free(entries); /* This should NOT be SDL_free() */
if (num_virtual_gamepads > 1) {
SDL_qsort(virtual_gamepads, num_virtual_gamepads, sizeof(*virtual_gamepads), sort_virtual_gamepads);
}
for (i = 0; i < num_virtual_gamepads; ++i) {
MaybeAddDevice(virtual_gamepads[i].path);
SDL_free(virtual_gamepads[i].path);
}
SDL_free(virtual_gamepads);
}
static void LINUX_ScanInputDevices(void)
{
int i, count;
struct dirent **entries = NULL;
char path[PATH_MAX];
count = scandir("/dev/input", &entries, filter_entries, NULL);
if (count > 1) {
SDL_qsort(entries, count, sizeof(*entries), sort_entries);
}
for (i = 0; i < count; ++i) {
(void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
MaybeAddDevice(path);
free(entries[i]); /* This should NOT be SDL_free() */
}
free(entries); /* This should NOT be SDL_free() */
}
static void LINUX_FallbackJoystickDetect(void)
{
const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
@ -842,21 +950,10 @@ static void LINUX_FallbackJoystickDetect(void)
/* Opening input devices can generate synchronous device I/O, so avoid it if we can */
if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
int i, count;
struct dirent **entries = NULL;
char path[PATH_MAX];
/* Look for Steam virtual gamepads first, and sort by Steam controller slot */
LINUX_ScanSteamVirtualGamepads();
count = scandir("/dev/input", &entries, filter_entries, NULL);
if (count > 1) {
SDL_qsort(entries, count, sizeof(*entries), sort_entries);
}
for (i = 0; i < count; ++i) {
(void)SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
MaybeAddDevice(path);
free(entries[i]); /* This should NOT be SDL_free() */
}
free(entries); /* This should NOT be SDL_free() */
LINUX_ScanInputDevices();
last_input_dir_mtime = sb.st_mtime;
}
@ -1021,7 +1118,7 @@ static const char *LINUX_JoystickGetDevicePath(int device_index)
static int LINUX_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
return GetJoystickByDevIndex(device_index)->steam_virtual_gamepad_slot;
}
static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)