mirror of https://github.com/libsdl-org/SDL
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.
This commit is contained in:
parent
a8f4f40d08
commit
c981a597dc
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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: *;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -71,6 +71,7 @@ struct joystick_hwdata
|
|||
|
||||
int instance_id;
|
||||
SDL_JoystickGUID guid;
|
||||
int steam_virtual_gamepad_slot;
|
||||
|
||||
struct joystick_hwdata *pNext; /* next device */
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue