Added Steam Input API support for game controllers

Added support for getting the real controller info, as well as the function SDL_GetGamepadSteamHandle() to get the Steam Input API handle, from the virtual gamepads provided by Steam.

Also added an event SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED which is triggered when a controller's API handle changes, e.g. the controllers were reassigned slots in the Steam UI.
main
Sam Lantinga 2023-12-09 23:05:34 -08:00
parent a8f4f40d08
commit c981a597dc
42 changed files with 779 additions and 40 deletions

View File

@ -407,6 +407,7 @@
<ClInclude Include="..\..\src\joystick\SDL_gamepad_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamepad_db.h" />
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\..\src\joystick\usb_ids.h" />
<ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
@ -634,6 +635,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
<ClCompile Include="..\..\src\joystick\SDL_gamepad.c" />
<ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />

View File

@ -507,6 +507,9 @@
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h">
<Filter>joystick</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h">
<Filter>joystick</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h">
<Filter>joystick</Filter>
</ClInclude>
@ -964,6 +967,9 @@
<ClCompile Include="..\..\src\joystick\SDL_joystick.c">
<Filter>joystick</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c">
<Filter>joystick</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libm\e_atan2.c">
<Filter>libm</Filter>
</ClCompile>

View File

@ -127,6 +127,7 @@
<ClInclude Include="..\src\joystick\SDL_gamepad_c.h" />
<ClInclude Include="..\src\joystick\SDL_gamepad_db.h" />
<ClInclude Include="..\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
<ClInclude Include="..\src\joystick\windows\SDL_dinputjoystick_c.h" />
@ -331,6 +332,7 @@
<ClCompile Include="..\src\joystick\controller_type.c" />
<ClCompile Include="..\src\joystick\SDL_gamepad.c" />
<ClCompile Include="..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\src\joystick\windows\SDL_windowsjoystick.c" />

View File

@ -261,6 +261,9 @@
<ClInclude Include="..\src\joystick\SDL_joystick_c.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\joystick\SDL_steam_virtual_gamepad.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\joystick\SDL_sysjoystick.h">
<Filter>Source Files</Filter>
</ClInclude>
@ -585,6 +588,9 @@
<ClCompile Include="..\src\joystick\SDL_joystick.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\joystick\SDL_steam_virtual_gamepad.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\joystick\virtual\SDL_virtualjoystick.c">
<Filter>Source Files</Filter>
</ClCompile>

View File

@ -357,6 +357,7 @@
<ClInclude Include="..\..\src\joystick\SDL_gamepad_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamepad_db.h" />
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\..\src\joystick\usb_ids.h" />
<ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
@ -537,6 +538,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
<ClCompile Include="..\..\src\joystick\SDL_gamepad.c" />
<ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />

View File

@ -501,6 +501,9 @@
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h">
<Filter>joystick</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h">
<Filter>joystick</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h">
<Filter>joystick</Filter>
</ClInclude>
@ -945,6 +948,9 @@
<ClCompile Include="..\..\src\joystick\SDL_joystick.c">
<Filter>joystick</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c">
<Filter>joystick</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libm\e_atan2.c">
<Filter>libm</Filter>
</ClCompile>

View File

@ -384,6 +384,10 @@
F32DDAD32AB795A30041EAA5 /* SDL_audioqueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F32DDACD2AB795A30041EAA5 /* SDL_audioqueue.h */; };
F32DDAD42AB795A30041EAA5 /* SDL_audioresample.c in Sources */ = {isa = PBXBuildFile; fileRef = F32DDACE2AB795A30041EAA5 /* SDL_audioresample.c */; };
F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; };
F362B9192B3349E200D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9152B3349E200D30B94 /* controller_list.h */; };
F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */; };
F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B91C2B3349E200D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */; };
F36C7AD1294BA009004D61C3 /* SDL_runapp.c in Sources */ = {isa = PBXBuildFile; fileRef = F36C7AD0294BA009004D61C3 /* SDL_runapp.c */; };
F376F6552559B4E300CFC0BC /* SDL_hidapi.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A81423E2513F00DCD162 /* SDL_hidapi.c */; };
F37A8E1A28405AA100C38E95 /* CMake in Resources */ = {isa = PBXBuildFile; fileRef = F37A8E1928405AA100C38E95 /* CMake */; };
@ -879,6 +883,10 @@
F32DDACC2AB795A30041EAA5 /* SDL_audio_resampler_filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_resampler_filter.h; sourceTree = "<group>"; };
F32DDACD2AB795A30041EAA5 /* SDL_audioqueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audioqueue.h; sourceTree = "<group>"; };
F32DDACE2AB795A30041EAA5 /* SDL_audioresample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audioresample.c; sourceTree = "<group>"; };
F362B9152B3349E200D30B94 /* controller_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_list.h; sourceTree = "<group>"; };
F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamepad_c.h; sourceTree = "<group>"; };
F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_steam_virtual_gamepad.h; sourceTree = "<group>"; };
F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_steam_virtual_gamepad.c; sourceTree = "<group>"; };
F36C7AD0294BA009004D61C3 /* SDL_runapp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_runapp.c; sourceTree = "<group>"; };
F376F6182559B29300CFC0BC /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
F376F61A2559B2AF00CFC0BC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@ -1670,12 +1678,16 @@
A7D8A7BE23E2513E00DCD162 /* hidapi */,
A7D8A7A123E2513E00DCD162 /* steam */,
75E09157241EA924004729E1 /* virtual */,
A7D8A7AD23E2513E00DCD162 /* SDL_gamepad.c */,
A7D8A7A923E2513E00DCD162 /* SDL_joystick.c */,
F362B9152B3349E200D30B94 /* controller_list.h */,
F3820712284F3609004DD584 /* controller_type.c */,
A7D8A7D923E2513E00DCD162 /* controller_type.h */,
F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */,
A7D8A79E23E2513E00DCD162 /* SDL_gamepad_db.h */,
A7D8A7AD23E2513E00DCD162 /* SDL_gamepad.c */,
A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */,
A7D8A7A923E2513E00DCD162 /* SDL_joystick.c */,
F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */,
F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */,
A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */,
A7D8A7CB23E2513E00DCD162 /* usb_ids.h */,
);
@ -2167,6 +2179,7 @@
F3F7D9B92933074E00816151 /* SDL_cpuinfo.h in Headers */,
F3990E062A788303000D8759 /* SDL_hidapi_ios.h in Headers */,
A7D8B98023E2514400DCD162 /* SDL_d3dmath.h in Headers */,
F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */,
A7D8B8A223E2514400DCD162 /* SDL_diskaudio.h in Headers */,
A7D8BB3F23E2514500DCD162 /* SDL_displayevents_c.h in Headers */,
A7D8BA1923E2514400DCD162 /* SDL_draw.h in Headers */,
@ -2180,6 +2193,7 @@
A7D8AB1023E2514100DCD162 /* SDL_dynapi_overrides.h in Headers */,
A7D8AB1C23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
F3F7D9252933074E00816151 /* SDL_egl.h in Headers */,
F362B9192B3349E200D30B94 /* controller_list.h in Headers */,
A7D8ABD923E2514100DCD162 /* SDL_egl_c.h in Headers */,
F3F7D93D2933074E00816151 /* SDL_endian.h in Headers */,
F3F7D9352933074E00816151 /* SDL_error.h in Headers */,
@ -2219,6 +2233,7 @@
F3F7D91D2933074E00816151 /* SDL_messagebox.h in Headers */,
F3F7D98D2933074E00816151 /* SDL_metal.h in Headers */,
F395C1BA2569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */,
F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
F3F7D9992933074E00816151 /* SDL_misc.h in Headers */,
F3F7D9AD2933074E00816151 /* SDL_mouse.h in Headers */,
A7D8BB1B23E2514500DCD162 /* SDL_mouse_c.h in Headers */,
@ -2583,6 +2598,7 @@
A7D8BAD323E2514500DCD162 /* s_tan.c in Sources */,
A7D8AA6523E2514000DCD162 /* SDL_hints.c in Sources */,
A7D8B53F23E2514300DCD162 /* SDL_hidapi_ps4.c in Sources */,
F362B91C2B3349E200D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8AD6E23E2514100DCD162 /* SDL_pixels.c in Sources */,
A7D8B75E23E2514300DCD162 /* SDL_sysloadso.c in Sources */,
A7D8BBD723E2574800DCD162 /* SDL_uikitevents.m in Sources */,

View File

@ -170,6 +170,7 @@ typedef enum
SDL_EVENT_GAMEPAD_TOUCHPAD_UP, /**< Gamepad touchpad finger was lifted */
SDL_EVENT_GAMEPAD_SENSOR_UPDATE, /**< Gamepad sensor was updated */
SDL_EVENT_GAMEPAD_UPDATE_COMPLETE, /**< Gamepad update is complete */
SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED, /**< Gamepad Steam handle has changed */
/* Touch events */
SDL_EVENT_FINGER_DOWN = 0x700,
@ -457,7 +458,7 @@ typedef struct SDL_GamepadButtonEvent
*/
typedef struct SDL_GamepadDeviceEvent
{
Uint32 type; /**< ::SDL_EVENT_GAMEPAD_ADDED, ::SDL_EVENT_GAMEPAD_REMOVED, or ::SDL_EVENT_GAMEPAD_REMAPPED or ::SDL_EVENT_GAMEPAD_UPDATE_COMPLETE */
Uint32 type; /**< ::SDL_EVENT_GAMEPAD_ADDED, ::SDL_EVENT_GAMEPAD_REMOVED, or ::SDL_EVENT_GAMEPAD_REMAPPED, ::SDL_EVENT_GAMEPAD_UPDATE_COMPLETE or ::SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED */
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_JoystickID which; /**< The joystick instance id */
} SDL_GamepadDeviceEvent;

View File

@ -758,6 +758,19 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadFirmwareVersion(SDL_Gamepad *gamepa
*/
extern DECLSPEC const char * SDLCALL SDL_GetGamepadSerial(SDL_Gamepad *gamepad);
/**
* Get the Steam Input handle of an opened gamepad, if available.
*
* Returns an InputHandle_t for the gamepad that can be used with Steam Input API:
* https://partner.steamgames.com/doc/api/ISteamInput
*
* \param gamepad the gamepad object to query.
* \returns the gamepad handle, or 0 if unavailable.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC Uint64 SDLCALL SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepad);
/**
* Get the battery level of a gamepad, if available.
*

View File

@ -965,6 +965,7 @@ SDL3_0.0.0 {
SDL_SyncWindow;
SDL_SetSurfaceScaleMode;
SDL_GetSurfaceScaleMode;
SDL_GetGamepadSteamHandle;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@ -990,3 +990,4 @@
#define SDL_SyncWindow SDL_SyncWindow_REAL
#define SDL_SetSurfaceScaleMode SDL_SetSurfaceScaleMode_REAL
#define SDL_GetSurfaceScaleMode SDL_GetSurfaceScaleMode_REAL
#define SDL_GetGamepadSteamHandle SDL_GetGamepadSteamHandle_REAL

View File

@ -1015,3 +1015,4 @@ SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t
SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GetSurfaceScaleMode,(SDL_Surface *a, SDL_ScaleMode *b),(a,b),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetGamepadSteamHandle,(SDL_Gamepad *a),(a),return)

View File

@ -433,6 +433,9 @@ static void SDL_LogEvent(const SDL_Event *event)
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_REMAPPED)
PRINT_GAMEPADDEV_EVENT(event);
break;
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED)
PRINT_GAMEPADDEV_EVENT(event);
break;
#undef PRINT_GAMEPADDEV_EVENT
#define PRINT_CTOUCHPAD_EVENT(event) \

View File

@ -25,6 +25,7 @@
#include "../SDL_utils_c.h"
#include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
#include "SDL_gamepad_c.h"
#include "SDL_gamepad_db.h"
#include "controller_type.h"
@ -2411,7 +2412,21 @@ SDL_GamepadType SDL_GetGamepadInstanceType(SDL_JoystickID instance_id)
SDL_GamepadType SDL_GetRealGamepadInstanceType(SDL_JoystickID instance_id)
{
return SDL_GetGamepadTypeFromGUID(SDL_GetJoystickInstanceGUID(instance_id), SDL_GetJoystickInstanceName(instance_id));
SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
{
info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id);
if (info) {
type = info->type;
} else {
type = SDL_GetGamepadTypeFromGUID(SDL_GetJoystickInstanceGUID(instance_id), SDL_GetJoystickInstanceName(instance_id));
}
}
SDL_UnlockJoysticks();
return type;
}
char *SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id)
@ -2518,7 +2533,7 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid)
#ifdef __LINUX__
bSteamVirtualGamepad = (vendor == USB_VENDOR_VALVE && product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD);
#elif defined(__MACOS__)
bSteamVirtualGamepad = (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 1);
bSteamVirtualGamepad = (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0);
#elif defined(__WIN32__)
/* We can't tell on Windows, but Steam will block others in input hooks */
bSteamVirtualGamepad = SDL_TRUE;
@ -3190,7 +3205,8 @@ const char *SDL_GetGamepadName(SDL_Gamepad *gamepad)
{
CHECK_GAMEPAD_MAGIC(gamepad, NULL);
if (SDL_strcmp(gamepad->name, "*") == 0) {
if (SDL_strcmp(gamepad->name, "*") == 0 ||
gamepad->joystick->steam_handle != 0) {
retval = SDL_GetJoystickName(gamepad->joystick);
} else {
retval = gamepad->name;
@ -3214,12 +3230,18 @@ const char *SDL_GetGamepadPath(SDL_Gamepad *gamepad)
SDL_GamepadType SDL_GetGamepadType(SDL_Gamepad *gamepad)
{
SDL_GamepadType type;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
{
CHECK_GAMEPAD_MAGIC(gamepad, SDL_GAMEPAD_TYPE_UNKNOWN);
type = gamepad->type;
info = SDL_GetJoystickInstanceVirtualGamepadInfo(gamepad->joystick->instance_id);
if (info) {
type = info->type;
} else {
type = gamepad->type;
}
}
SDL_UnlockJoysticks();
@ -3310,6 +3332,21 @@ const char * SDL_GetGamepadSerial(SDL_Gamepad *gamepad)
return SDL_GetJoystickSerial(joystick);
}
Uint64 SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepad)
{
Uint64 handle = 0;
SDL_LockJoysticks();
{
CHECK_GAMEPAD_MAGIC(gamepad, 0);
handle = gamepad->joystick->steam_handle;
}
SDL_UnlockJoysticks();
return handle;
}
SDL_JoystickPowerLevel SDL_GetGamepadPowerLevel(SDL_Gamepad *gamepad)
{
SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);

View File

@ -26,6 +26,7 @@
#include "../SDL_hints_c.h"
#include "SDL_gamepad_c.h"
#include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
#ifndef SDL_EVENTS_DISABLED
#include "../events/SDL_events_c.h"
@ -624,6 +625,8 @@ int SDL_InitJoysticks(void)
SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
SDL_JoystickAllowBackgroundEventsChanged, NULL);
SDL_InitSteamVirtualGamepadInfo();
status = -1;
for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
if (SDL_joystick_drivers[i]->Init() >= 0) {
@ -696,6 +699,19 @@ SDL_JoystickID *SDL_GetJoysticks(int *count)
return joysticks;
}
const SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id)
{
SDL_JoystickDriver *driver;
int device_index;
const SDL_SteamVirtualGamepadInfo *info = NULL;
if (SDL_SteamVirtualGamepadEnabled() &&
SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
info = SDL_GetSteamVirtualGamepadInfo(driver->GetDeviceSteamVirtualGamepadSlot(device_index));
}
return info;
}
/*
* Get the implementation dependent name of a joystick
*/
@ -704,9 +720,13 @@ const char *SDL_GetJoystickInstanceName(SDL_JoystickID instance_id)
SDL_JoystickDriver *driver;
int device_index;
const char *name = NULL;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id);
if (info) {
name = info->name;
} else if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
name = driver->GetDeviceName(device_index);
}
SDL_UnlockJoysticks();
@ -993,6 +1013,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
const char *joystickpath = NULL;
SDL_JoystickPowerLevel initial_power_level;
SDL_bool invert_sensors = SDL_FALSE;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
@ -1076,6 +1097,12 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
joystick->is_gamepad = SDL_IsGamepad(instance_id);
/* Get the Steam Input API handle */
info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id);
if (info) {
joystick->steam_handle = info->handle;
}
/* Use system gyro and accelerometer if the gamepad doesn't have built-in sensors */
if (ShouldAttemptSensorFusion(joystick, &invert_sensors)) {
AttemptSensorFusion(joystick, invert_sensors);
@ -1491,15 +1518,20 @@ SDL_PropertiesID SDL_GetJoystickProperties(SDL_Joystick *joystick)
const char *SDL_GetJoystickName(SDL_Joystick *joystick)
{
const char *retval;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
{
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
retval = info->name;
} else {
CHECK_JOYSTICK_MAGIC(joystick, NULL);
retval = joystick->name;
}
SDL_UnlockJoysticks();
/* FIXME: Really we should reference count this name so it doesn't go away after unlock */
return retval;
}
@ -1823,6 +1855,8 @@ void SDL_QuitJoysticks(void)
SDL_QuitSubSystem(SDL_INIT_EVENTS);
#endif
SDL_QuitSteamVirtualGamepadInfo();
SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
SDL_JoystickAllowBackgroundEventsChanged, NULL);
@ -1921,7 +1955,10 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
SDL_joystick_being_added = SDL_TRUE;
if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
player_index = driver->GetDevicePlayerIndex(device_index);
player_index = driver->GetDeviceSteamVirtualGamepadSlot(device_index);
if (player_index < 0) {
player_index = driver->GetDevicePlayerIndex(device_index);
}
}
if (player_index < 0 && SDL_IsGamepad(instance_id)) {
player_index = SDL_FindFreePlayerIndex();
@ -2200,6 +2237,43 @@ int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butto
return posted;
}
static void SendSteamHandleUpdateEvents(void)
{
SDL_Joystick *joystick;
const SDL_SteamVirtualGamepadInfo *info;
/* Check to see if any Steam handles changed */
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
SDL_bool changed = SDL_FALSE;
if (!joystick->is_gamepad) {
continue;
}
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
if (joystick->steam_handle != info->handle) {
joystick->steam_handle = info->handle;
changed = SDL_TRUE;
}
} else {
if (joystick->steam_handle != 0) {
joystick->steam_handle = 0;
changed = SDL_TRUE;
}
}
if (changed) {
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED;
event.common.timestamp = 0;
event.gdevice.which = joystick->instance_id;
SDL_PushEvent(&event);
}
}
}
void SDL_UpdateJoysticks(void)
{
int i;
@ -2212,6 +2286,10 @@ void SDL_UpdateJoysticks(void)
SDL_LockJoysticks();
if (SDL_UpdateSteamVirtualGamepadInfo()) {
SendSteamHandleUpdateEvents();
}
#ifdef SDL_JOYSTICK_HIDAPI
/* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
HIDAPI_UpdateDevices();
@ -3083,18 +3161,38 @@ SDL_JoystickGUID SDL_GetJoystickInstanceGUID(SDL_JoystickID instance_id)
Uint16 SDL_GetJoystickInstanceVendor(SDL_JoystickID instance_id)
{
Uint16 vendor;
SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id);
if (info) {
vendor = info->vendor_id;
} else {
SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
return vendor;
}
Uint16 SDL_GetJoystickInstanceProduct(SDL_JoystickID instance_id)
{
Uint16 product;
SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id);
if (info) {
product = info->product_id;
} else {
SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
return product;
}
@ -3141,18 +3239,38 @@ SDL_JoystickGUID SDL_GetJoystickGUID(SDL_Joystick *joystick)
Uint16 SDL_GetJoystickVendor(SDL_Joystick *joystick)
{
Uint16 vendor;
SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
vendor = info->vendor_id;
} else {
SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick);
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
return vendor;
}
Uint16 SDL_GetJoystickProduct(SDL_Joystick *joystick)
{
Uint16 product;
SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
product = info->product_id;
} else {
SDL_JoystickGUID guid = SDL_GetJoystickGUID(joystick);
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
return product;
}

View File

@ -32,6 +32,7 @@ extern "C" {
#endif
struct SDL_JoystickDriver;
struct SDL_SteamVirtualGamepadInfo;
extern char SDL_joystick_magic;
/* Initialization and shutdown functions */
@ -170,6 +171,9 @@ extern int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick,
extern void SDL_SendJoystickBatteryLevel(SDL_Joystick *joystick,
SDL_JoystickPowerLevel ePowerLevel);
/* Function to get the Steam virtual gamepad info for a joystick */
extern const struct SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id);
/* Internal sanity checking functions */
extern SDL_bool SDL_IsJoystickValid(SDL_Joystick *joystick);

View File

@ -0,0 +1,248 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
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"
#include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
#ifdef __WIN32__
#include "../core/windows/SDL_windows.h"
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#define SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE "SteamVirtualGamepadInfo"
static char *SDL_steam_virtual_gamepad_info_file SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static Uint64 SDL_steam_virtual_gamepad_info_file_mtime SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static Uint64 SDL_steam_virtual_gamepad_info_check_time SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static SDL_SteamVirtualGamepadInfo **SDL_steam_virtual_gamepad_info SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static int SDL_steam_virtual_gamepad_info_count SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static Uint64 GetFileModificationTime(const char *file)
{
Uint64 modification_time = 0;
#ifdef __WIN32__
WCHAR *wFile = WIN_UTF8ToStringW(file);
if (wFile) {
HANDLE hFile = CreateFileW(wFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
FILETIME last_write_time;
if (GetFileTime(hFile, NULL, NULL, &last_write_time)) {
modification_time = last_write_time.dwHighDateTime;
modification_time <<= 32;
modification_time |= last_write_time.dwLowDateTime;
}
CloseHandle(hFile);
}
SDL_free(wFile);
}
#else
struct stat sb;
if (stat(file, &sb) == 0) {
modification_time = (Uint64)sb.st_mtime;
}
#endif
return modification_time;
}
static void SDL_FreeSteamVirtualGamepadInfo(void)
{
int i;
SDL_AssertJoysticksLocked();
for (i = 0; i < SDL_steam_virtual_gamepad_info_count; ++i) {
SDL_SteamVirtualGamepadInfo *entry = SDL_steam_virtual_gamepad_info[i];
if (entry) {
SDL_free(entry->name);
SDL_free(entry);
}
}
SDL_free(SDL_steam_virtual_gamepad_info);
SDL_steam_virtual_gamepad_info = NULL;
SDL_steam_virtual_gamepad_info_count = 0;
}
static void AddVirtualGamepadInfo(int slot, SDL_SteamVirtualGamepadInfo *info)
{
SDL_SteamVirtualGamepadInfo *new_info;
SDL_AssertJoysticksLocked();
if (slot < 0) {
return;
}
if (slot >= SDL_steam_virtual_gamepad_info_count) {
SDL_SteamVirtualGamepadInfo **slots = (SDL_SteamVirtualGamepadInfo **)SDL_realloc(SDL_steam_virtual_gamepad_info, (slot + 1)*sizeof(*SDL_steam_virtual_gamepad_info));
if (!slots) {
return;
}
while (SDL_steam_virtual_gamepad_info_count <= slot) {
slots[SDL_steam_virtual_gamepad_info_count++] = NULL;
}
SDL_steam_virtual_gamepad_info = slots;
}
if (SDL_steam_virtual_gamepad_info[slot]) {
/* We already have this slot info */
return;
}
new_info = (SDL_SteamVirtualGamepadInfo *)SDL_malloc(sizeof(*new_info));
if (!new_info) {
return;
}
SDL_copyp(new_info, info);
SDL_steam_virtual_gamepad_info[slot] = new_info;
SDL_zerop(info);
}
void SDL_InitSteamVirtualGamepadInfo(void)
{
const char *file;
SDL_AssertJoysticksLocked();
file = SDL_GetHint(SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE);
if (file && *file) {
SDL_steam_virtual_gamepad_info_file = SDL_strdup(file);
}
SDL_UpdateSteamVirtualGamepadInfo();
}
SDL_bool SDL_SteamVirtualGamepadEnabled(void)
{
SDL_AssertJoysticksLocked();
return (SDL_steam_virtual_gamepad_info != NULL);
}
SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void)
{
const int UPDATE_CHECK_INTERVAL_MS = 3000;
Uint64 now;
Uint64 mtime;
char *data, *end, *next, *line, *value;
size_t size;
int slot, new_slot;
SDL_SteamVirtualGamepadInfo info;
SDL_AssertJoysticksLocked();
if (!SDL_steam_virtual_gamepad_info_file) {
return SDL_FALSE;
}
now = SDL_GetTicks();
if (SDL_steam_virtual_gamepad_info_check_time &&
now < (SDL_steam_virtual_gamepad_info_check_time + UPDATE_CHECK_INTERVAL_MS)) {
return SDL_FALSE;
}
SDL_steam_virtual_gamepad_info_check_time = now;
mtime = GetFileModificationTime(SDL_steam_virtual_gamepad_info_file);
if (mtime == 0 || mtime == SDL_steam_virtual_gamepad_info_file_mtime) {
return SDL_FALSE;
}
data = (char *)SDL_LoadFile(SDL_steam_virtual_gamepad_info_file, &size);
if (!data) {
return SDL_FALSE;
}
SDL_FreeSteamVirtualGamepadInfo();
slot = -1;
SDL_zero(info);
for (next = data, end = data + size; next < end; ) {
while (next < end && (*next == '\0' || *next == '\r' || *next == '\n')) {
++next;
}
line = next;
while (next < end && (*next != '\r' && *next != '\n')) {
++next;
}
*next = '\0';
if (SDL_sscanf(line, "[slot %d]", &new_slot) == 1) {
if (slot >= 0) {
AddVirtualGamepadInfo(slot, &info);
}
slot = new_slot;
} else {
value = SDL_strchr(line, '=');
if (value) {
*value++ = '\0';
if (SDL_strcmp(line, "name") == 0) {
SDL_free(info.name);
info.name = SDL_strdup(value);
} else if (SDL_strcmp(line, "VID") == 0) {
info.vendor_id = (Uint16)SDL_strtoul(value, NULL, 0);
} else if (SDL_strcmp(line, "PID") == 0) {
info.product_id = (Uint16)SDL_strtoul(value, NULL, 0);
} else if (SDL_strcmp(line, "type") == 0) {
info.type = SDL_GetGamepadTypeFromString(value);
} else if (SDL_strcmp(line, "handle") == 0) {
info.handle = SDL_strtoull(value, NULL, 0);
}
}
}
}
if (slot >= 0) {
AddVirtualGamepadInfo(slot, &info);
}
SDL_free(data);
SDL_steam_virtual_gamepad_info_file_mtime = mtime;
return SDL_TRUE;
}
const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot)
{
SDL_AssertJoysticksLocked();
if (slot < 0 || slot >= SDL_steam_virtual_gamepad_info_count) {
return NULL;
}
return SDL_steam_virtual_gamepad_info[slot];
}
void SDL_QuitSteamVirtualGamepadInfo(void)
{
SDL_AssertJoysticksLocked();
if (SDL_steam_virtual_gamepad_info_file) {
SDL_FreeSteamVirtualGamepadInfo();
SDL_free(SDL_steam_virtual_gamepad_info_file);
SDL_steam_virtual_gamepad_info_file = NULL;
}
}

View File

@ -0,0 +1,36 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
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"
typedef struct SDL_SteamVirtualGamepadInfo
{
Uint64 handle;
char *name;
Uint16 vendor_id;
Uint16 product_id;
SDL_GamepadType type;
} SDL_SteamVirtualGamepadInfo;
void SDL_InitSteamVirtualGamepadInfo(void);
SDL_bool SDL_SteamVirtualGamepadEnabled(void);
SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void);
const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot);
void SDL_QuitSteamVirtualGamepadInfo(void);

View File

@ -77,6 +77,7 @@ struct SDL_Joystick
char *serial _guarded; /* Joystick serial */
SDL_JoystickGUID guid _guarded; /* Joystick guid */
Uint16 firmware_version _guarded; /* Firmware version, if available */
Uint64 steam_handle _guarded; /* Steam controller API handle */
int naxes _guarded; /* Number of axis controls on the joystick */
SDL_JoystickAxisInfo *axes _guarded;
@ -168,6 +169,9 @@ typedef struct SDL_JoystickDriver
/* Function to get the device-dependent path of a joystick */
const char *(*GetDevicePath)(int device_index);
/* Function to get the Steam virtual gamepad slot of a joystick */
int (*GetDeviceSteamVirtualGamepadSlot)(int device_index);
/* Function to get the player index of a joystick */
int (*GetDevicePlayerIndex)(int device_index);

View File

@ -541,6 +541,11 @@ static const char *ANDROID_JoystickGetDevicePath(int device_index)
return NULL;
}
static int ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int ANDROID_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -681,6 +686,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = {
ANDROID_JoystickDetect,
ANDROID_JoystickGetDeviceName,
ANDROID_JoystickGetDevicePath,
ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot,
ANDROID_JoystickGetDevicePlayerIndex,
ANDROID_JoystickSetDevicePlayerIndex,
ANDROID_JoystickGetDeviceGUID,

View File

@ -661,6 +661,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
}
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype);
if (SDL_ShouldIgnoreJoystick(name, device->guid)) {
return SDL_FALSE;
}
/* This will be set when the first button press of the controller is
* detected. */
controller.playerIndex = -1;
@ -705,6 +709,7 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet
} else if (controller) {
#ifdef SDL_JOYSTICK_MFI
if (!IOS_AddMFIJoystickDevice(device, controller)) {
SDL_free(device->name);
SDL_free(device);
return;
}
@ -898,6 +903,11 @@ static const char *IOS_JoystickGetDevicePath(int device_index)
return NULL;
}
static int IOS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int IOS_JoystickGetDevicePlayerIndex(int device_index)
{
#ifdef SDL_JOYSTICK_MFI
@ -2165,6 +2175,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = {
IOS_JoystickDetect,
IOS_JoystickGetDeviceName,
IOS_JoystickGetDevicePath,
IOS_JoystickGetDeviceSteamVirtualGamepadSlot,
IOS_JoystickGetDevicePlayerIndex,
IOS_JoystickSetDevicePlayerIndex,
IOS_JoystickGetDeviceGUID,

View File

@ -543,6 +543,11 @@ static const char *BSD_JoystickGetDevicePath(int device_index)
return GetJoystickByDevIndex(device_index)->path;
}
static int BSD_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int BSD_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -850,6 +855,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = {
BSD_JoystickDetect,
BSD_JoystickGetDeviceName,
BSD_JoystickGetDevicePath,
BSD_JoystickGetDeviceSteamVirtualGamepadSlot,
BSD_JoystickGetDevicePlayerIndex,
BSD_JoystickSetDevicePlayerIndex,
BSD_JoystickGetDeviceGUID,

View File

@ -405,6 +405,19 @@ static void AddHIDElement(const void *value, void *parameter)
}
}
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *product_string)
{
int slot = -1;
if (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER) {
/* Gamepad name is "GamePad-N", where N is slot + 1 */
if (SDL_sscanf(product_string, "GamePad-%d", &slot) == 1) {
slot -= 1;
}
}
return slot;
}
static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
{
Sint32 vendor = 0;
@ -485,6 +498,7 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
#endif
pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0);
pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string);
array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);
if (array) {
@ -711,6 +725,12 @@ const char *DARWIN_JoystickGetDevicePath(int device_index)
return NULL;
}
static int DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
recDevice *device = GetDeviceForIndex(device_index);
return device ? device->steam_virtual_gamepad_slot : -1;
}
static int DARWIN_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -1056,6 +1076,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = {
DARWIN_JoystickDetect,
DARWIN_JoystickGetDeviceName,
DARWIN_JoystickGetDevicePath,
DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot,
DARWIN_JoystickGetDevicePlayerIndex,
DARWIN_JoystickSetDevicePlayerIndex,
DARWIN_JoystickGetDeviceGUID,

View File

@ -71,6 +71,7 @@ struct joystick_hwdata
int instance_id;
SDL_JoystickGUID guid;
int steam_virtual_gamepad_slot;
struct joystick_hwdata *pNext; /* next device */
};

View File

@ -51,6 +51,11 @@ static const char *DUMMY_JoystickGetDevicePath(int device_index)
return NULL;
}
static int DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int DUMMY_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -130,6 +135,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = {
DUMMY_JoystickDetect,
DUMMY_JoystickGetDeviceName,
DUMMY_JoystickGetDevicePath,
DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot,
DUMMY_JoystickGetDevicePlayerIndex,
DUMMY_JoystickSetDevicePlayerIndex,
DUMMY_JoystickGetDeviceGUID,

View File

@ -269,6 +269,11 @@ static const char *EMSCRIPTEN_JoystickGetDevicePath(int device_index)
return NULL;
}
static int EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int EMSCRIPTEN_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -416,6 +421,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = {
EMSCRIPTEN_JoystickDetect,
EMSCRIPTEN_JoystickGetDeviceName,
EMSCRIPTEN_JoystickGetDevicePath,
EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot,
EMSCRIPTEN_JoystickGetDevicePlayerIndex,
EMSCRIPTEN_JoystickSetDevicePlayerIndex,
EMSCRIPTEN_JoystickGetDeviceGUID,

View File

@ -101,6 +101,11 @@ extern "C"
return SDL_joyport[device_index];
}
static int HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int HAIKU_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -295,6 +300,7 @@ extern "C"
HAIKU_JoystickDetect,
HAIKU_JoystickGetDeviceName,
HAIKU_JoystickGetDevicePath,
HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot,
HAIKU_JoystickGetDevicePlayerIndex,
HAIKU_JoystickSetDevicePlayerIndex,
HAIKU_JoystickGetDeviceGUID,

View File

@ -1376,6 +1376,11 @@ static const char *HIDAPI_JoystickGetDevicePath(int device_index)
return path;
}
static int HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
{
SDL_HIDAPI_Device *device;
@ -1654,6 +1659,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = {
HIDAPI_JoystickDetect,
HIDAPI_JoystickGetDeviceName,
HIDAPI_JoystickGetDevicePath,
HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot,
HIDAPI_JoystickGetDevicePlayerIndex,
HIDAPI_JoystickSetDevicePlayerIndex,
HIDAPI_JoystickGetDeviceGUID,

View File

@ -220,14 +220,18 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version,
}
#endif /* SDL_JOYSTICK_HIDAPI */
static SDL_bool GetVirtualGamepadSlot(const char *name, int *slot)
static SDL_bool GetSteamVirtualGamepadSlot(int fd, int *slot)
{
const char *digits = SDL_strstr(name, "pad ");
if (digits) {
digits += 4;
if (SDL_isdigit(*digits)) {
*slot = SDL_atoi(digits);
return SDL_TRUE;
char name[128];
if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) {
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;
@ -445,7 +449,6 @@ static void MaybeAddDevice(const char *path)
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("found joystick: %s\n", path);
#endif
close(fd);
item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item));
if (!item) {
SDL_free(name);
@ -460,7 +463,7 @@ static void MaybeAddDevice(const char *path)
if (vendor == USB_VENDOR_VALVE &&
product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
GetVirtualGamepadSlot(item->name, &item->steam_virtual_gamepad_slot);
GetSteamVirtualGamepadSlot(fd, &item->steam_virtual_gamepad_slot);
}
if ((!item->path) || (!item->name)) {
@ -487,7 +490,6 @@ static void MaybeAddDevice(const char *path)
#ifdef DEBUG_INPUT_EVENTS
SDL_Log("found sensor: %s\n", path);
#endif
close(fd);
item_sensor = (SDL_sensorlist_item *)SDL_calloc(1, sizeof(SDL_sensorlist_item));
if (!item_sensor) {
goto done;
@ -505,8 +507,10 @@ static void MaybeAddDevice(const char *path)
goto done;
}
close(fd);
done:
if (fd >= 0) {
close(fd);
}
SDL_UnlockJoysticks();
}
@ -874,7 +878,6 @@ static void LINUX_ScanSteamVirtualGamepads(void)
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;
@ -889,8 +892,7 @@ static void LINUX_ScanSteamVirtualGamepads(void)
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)) {
GetSteamVirtualGamepadSlot(fd, &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];
@ -1116,11 +1118,16 @@ static const char *LINUX_JoystickGetDevicePath(int device_index)
return GetJoystickByDevIndex(device_index)->path;
}
static int LINUX_JoystickGetDevicePlayerIndex(int device_index)
static int LINUX_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return GetJoystickByDevIndex(device_index)->steam_virtual_gamepad_slot;
}
static int LINUX_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
}
static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
{
}
@ -2689,6 +2696,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = {
LINUX_JoystickDetect,
LINUX_JoystickGetDeviceName,
LINUX_JoystickGetDevicePath,
LINUX_JoystickGetDeviceSteamVirtualGamepadSlot,
LINUX_JoystickGetDevicePlayerIndex,
LINUX_JoystickSetDevicePlayerIndex,
LINUX_JoystickGetDeviceGUID,

View File

@ -231,6 +231,11 @@ static const char *N3DS_JoystickGetDevicePath(int device_index)
return NULL;
}
static int N3DS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int N3DS_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -271,6 +276,7 @@ SDL_JoystickDriver SDL_N3DS_JoystickDriver = {
.Detect = N3DS_JoystickDetect,
.GetDeviceName = N3DS_JoystickGetDeviceName,
.GetDevicePath = N3DS_JoystickGetDevicePath,
.GetDeviceSteamVirtualGamepadSlot = N3DS_JoystickGetDeviceSteamVirtualGamepadSlot,
.GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex,
.SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex,
.GetDeviceGUID = N3DS_JoystickGetDeviceGUID,

View File

@ -157,6 +157,12 @@ static const char *PS2_JoystickGetDevicePath(int index)
return NULL;
}
/* Function to get the Steam virtual gamepad slot of a joystick */
static int PS2_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
/* Function to get the player index of a joystick */
static int PS2_JoystickGetDevicePlayerIndex(int device_index)
{
@ -341,6 +347,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = {
PS2_JoystickDetect,
PS2_JoystickGetDeviceName,
PS2_JoystickGetDevicePath,
PS2_JoystickGetDeviceSteamVirtualGamepadSlot,
PS2_JoystickGetDevicePlayerIndex,
PS2_JoystickSetDevicePlayerIndex,
PS2_JoystickGetDeviceGUID,

View File

@ -121,6 +121,11 @@ static const char *PSP_JoystickGetDevicePath(int index)
return NULL;
}
static int PSP_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int PSP_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -253,6 +258,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = {
PSP_JoystickDetect,
PSP_JoystickGetDeviceName,
PSP_JoystickGetDevicePath,
PSP_JoystickGetDeviceSteamVirtualGamepadSlot,
PSP_JoystickGetDevicePlayerIndex,
PSP_JoystickSetDevicePlayerIndex,
PSP_JoystickGetDeviceGUID,

View File

@ -367,6 +367,11 @@ static const char *VIRTUAL_JoystickGetDevicePath(int device_index)
return NULL;
}
static int VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int VIRTUAL_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -728,6 +733,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = {
VIRTUAL_JoystickDetect,
VIRTUAL_JoystickGetDeviceName,
VIRTUAL_JoystickGetDevicePath,
VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot,
VIRTUAL_JoystickGetDevicePlayerIndex,
VIRTUAL_JoystickSetDevicePlayerIndex,
VIRTUAL_JoystickGetDeviceGUID,

View File

@ -181,6 +181,11 @@ const char *VITA_JoystickGetDevicePath(int index)
return NULL;
}
static int VITA_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int VITA_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -378,6 +383,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = {
VITA_JoystickDetect,
VITA_JoystickGetDeviceName,
VITA_JoystickGetDevicePath,
VITA_JoystickGetDeviceSteamVirtualGamepadSlot,
VITA_JoystickGetDevicePlayerIndex,
VITA_JoystickSetDevicePlayerIndex,
VITA_JoystickGetDeviceGUID,

View File

@ -435,6 +435,17 @@ int SDL_DINPUT_JoystickInit(void)
return 0;
}
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path)
{
int slot = -1;
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
(void)SDL_sscanf(device_path, "\\\\?\\HID#VID_28DE&PID_11FF&IG_0%d", &slot);
}
return slot;
}
/* helper function for direct input, gets called for each connected joystick */
static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
{
@ -487,10 +498,10 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
pNewJoystick = pNewJoystick->pNext;
}
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData));
CHECK(pNewJoystick);
SDL_zerop(pNewJoystick);
pNewJoystick->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(vendor, product, hidPath);
SDL_strlcpy(pNewJoystick->path, hidPath, SDL_arraysize(pNewJoystick->path));
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));

View File

@ -114,6 +114,7 @@ typedef struct SDL_RAWINPUT_Device
SDL_JoystickGUID guid;
SDL_bool is_xinput;
SDL_bool is_xboxone;
int steam_virtual_gamepad_slot;
PHIDP_PREPARSED_DATA preparsed_data;
HANDLE hDevice;
@ -841,6 +842,19 @@ static SDL_RAWINPUT_Device *RAWINPUT_DeviceFromHandle(HANDLE hDevice)
return NULL;
}
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path)
{
int slot = -1;
// The format for the raw input device path is documented here:
// https://partner.steamgames.com/doc/features/steam_controller/steam_input_gamepad_emulation_bestpractices
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
(void)SDL_sscanf(device_path, "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%*X&%*X&%*X#%d#%*u", &slot);
}
return slot;
}
static void RAWINPUT_AddDevice(HANDLE hDevice)
{
#define CHECK(expression) \
@ -883,6 +897,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
device->version = (Uint16)rdi.hid.dwVersionNumber;
device->is_xinput = SDL_TRUE;
device->is_xboxone = SDL_IsJoystickXboxOne(device->vendor_id, device->product_id);
device->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(device->vendor_id, device->product_id, dev_name);
/* Get HID Top-Level Collection Preparsed Data */
size = 0;
@ -1189,6 +1204,11 @@ static const char *RAWINPUT_JoystickGetDevicePath(int device_index)
return RAWINPUT_GetDeviceByIndex(device_index)->path;
}
static int RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return RAWINPUT_GetDeviceByIndex(device_index)->steam_virtual_gamepad_slot;
}
static int RAWINPUT_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -2198,6 +2218,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = {
RAWINPUT_JoystickDetect,
RAWINPUT_JoystickGetDeviceName,
RAWINPUT_JoystickGetDevicePath,
RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,
RAWINPUT_JoystickGetDevicePlayerIndex,
RAWINPUT_JoystickSetDevicePlayerIndex,
RAWINPUT_JoystickGetDeviceGUID,

View File

@ -58,6 +58,7 @@ typedef struct WindowsGamingInputControllerState
char *name;
SDL_JoystickGUID guid;
SDL_JoystickType type;
int steam_virtual_gamepad_slot;
} WindowsGamingInputControllerState;
typedef HRESULT(WINAPI *CoIncrementMTAUsage_t)(PVOID *pCookie);
@ -356,6 +357,34 @@ static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_Release(__FI
return rc;
}
static int GetSteamVirtualGamepadSlot(__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller, Uint16 vendor_id, Uint16 product_id)
{
int slot = -1;
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, (void **)&controller2);
if (SUCCEEDED(hr)) {
HSTRING hString;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_NonRoamableId(controller2, &hString);
if (SUCCEEDED(hr)) {
PCWSTR string = wgi.WindowsGetStringRawBuffer(hString, NULL);
if (string) {
char *id = WIN_StringToUTF8W(string);
if (id) {
(void)SDL_sscanf(id, "{wgi/nrid/:steam-%*X&%*X&%*X#%d#%*u}", &slot);
SDL_free(id);
}
}
wgi.WindowsDeleteString(hString);
}
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
}
return slot;
}
static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController *e)
{
HRESULT hr;
@ -464,6 +493,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
state->name = name;
state->guid = guid;
state->type = type;
state->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(controller, vendor, product);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_AddRef(controller);
@ -664,6 +694,11 @@ static const char *WGI_JoystickGetDevicePath(int device_index)
return NULL;
}
static int WGI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return wgi.controllers[device_index].steam_virtual_gamepad_slot;
}
static int WGI_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -983,6 +1018,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = {
WGI_JoystickDetect,
WGI_JoystickGetDeviceName,
WGI_JoystickGetDevicePath,
WGI_JoystickGetDeviceSteamVirtualGamepadSlot,
WGI_JoystickGetDevicePlayerIndex,
WGI_JoystickSetDevicePlayerIndex,
WGI_JoystickGetDeviceGUID,

View File

@ -612,6 +612,23 @@ static const char *WINDOWS_JoystickGetDevicePath(int device_index)
return device->path;
}
static int WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
JoyStick_DeviceData *device = SYS_Joystick;
int index;
for (index = device_index; index > 0; index--) {
device = device->pNext;
}
if (device->bXInputDevice) {
/* The slot for XInput devices can change as controllers are seated */
return SDL_XINPUT_GetSteamVirtualGamepadSlot(device->XInputUserId);
} else {
return device->steam_virtual_gamepad_slot;
}
}
static int WINDOWS_JoystickGetDevicePlayerIndex(int device_index)
{
JoyStick_DeviceData *device = SYS_Joystick;
@ -669,7 +686,6 @@ static int WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index)
}
/* allocate memory for system specific hardware data */
joystick->instance_id = device->nInstanceID;
joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata));
if (!joystick->hwdata) {
return -1;
@ -792,6 +808,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = {
WINDOWS_JoystickDetect,
WINDOWS_JoystickGetDeviceName,
WINDOWS_JoystickGetDevicePath,
WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot,
WINDOWS_JoystickGetDevicePlayerIndex,
WINDOWS_JoystickSetDevicePlayerIndex,
WINDOWS_JoystickGetDeviceGUID,

View File

@ -42,6 +42,7 @@ typedef struct JoyStick_DeviceData
Uint8 XInputUserId;
DIDEVICEINSTANCE dxdevice;
char path[MAX_PATH];
int steam_virtual_gamepad_slot;
struct JoyStick_DeviceData *pNext;
} JoyStick_DeviceData;

View File

@ -127,13 +127,31 @@ static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Ui
capabilities.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER;
}
*pVID = capabilities.VendorId;
*pPID = capabilities.ProductId;
*pVersion = capabilities.ProductVersion;
if (pVID) {
*pVID = capabilities.VendorId;
}
if (pPID) {
*pPID = capabilities.ProductId;
}
if (pVersion) {
*pVersion = capabilities.ProductVersion;
}
return SDL_TRUE;
}
int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid)
{
XINPUT_CAPABILITIES_EX capabilities;
if (XINPUTGETCAPABILITIESEX &&
XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) == ERROR_SUCCESS &&
capabilities.VendorId == USB_VENDOR_VALVE &&
capabilities.ProductId == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
return (int)capabilities.unk2;
}
return -1;
}
static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
{
Uint16 vendor = 0;

View File

@ -36,6 +36,7 @@ extern Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick);
extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick);
extern void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick);
extern void SDL_XINPUT_JoystickQuit(void);
extern int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus

View File

@ -1292,6 +1292,13 @@ static void DrawGamepadInfo(SDL_Renderer *renderer)
SDL_SetRenderDrawColor(renderer, r, g, b, a);
}
if (controller->joystick) {
SDL_snprintf(text, sizeof(text), "(%" SDL_PRIu32 ")", SDL_GetJoystickInstanceID(controller->joystick));
x = (float)SCREEN_WIDTH - (FONT_CHARACTER_SIZE * SDL_strlen(text)) - 8.0f;
y = 8.0f;
SDLTest_DrawString(renderer, x, y, text);
}
if (controller_name && *controller_name) {
x = title_area.x + title_area.w / 2 - (FONT_CHARACTER_SIZE * SDL_strlen(controller_name)) / 2;
y = title_area.y + title_area.h / 2 - FONT_CHARACTER_SIZE / 2;
@ -1311,6 +1318,14 @@ static void DrawGamepadInfo(SDL_Renderer *renderer)
SDLTest_DrawString(renderer, x, y, type);
if (display_mode == CONTROLLER_MODE_TESTING) {
Uint64 steam_handle = SDL_GetGamepadSteamHandle(controller->gamepad);
if (steam_handle) {
SDL_snprintf(text, SDL_arraysize(text), "Steam: 0x%.16llx", (unsigned long long)steam_handle);
y = (float)SCREEN_HEIGHT - 2 * (8.0f + FONT_LINE_HEIGHT);
x = (float)SCREEN_WIDTH - 8.0f - (FONT_CHARACTER_SIZE * SDL_strlen(text));
SDLTest_DrawString(renderer, x, y, text);
}
SDL_snprintf(text, SDL_arraysize(text), "VID: 0x%.4x PID: 0x%.4x",
SDL_GetJoystickVendor(controller->joystick),
SDL_GetJoystickProduct(controller->joystick));
@ -1595,6 +1610,10 @@ static void loop(void *arg)
HandleGamepadRemapped(event.gdevice.which);
break;
case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED:
RefreshControllerName();
break;
#ifdef VERBOSE_TOUCHPAD
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: