Added Steam Input API support for game controllers

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

Also added an event SDL_CONTROLLERSTEAMHANDLEUPDATED which is triggered when a controller's API handle changes, e.g. the controllers were reassigned slots in the Steam UI.

(cherry picked from commit c981a597dc7c69e7532796b3a206071807479d35)
This commit is contained in:
Sam Lantinga 2023-12-09 23:05:34 -08:00
parent 9720672374
commit 7bb0e839a6
41 changed files with 827 additions and 49 deletions

View file

@ -412,6 +412,7 @@
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.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" />
@ -609,6 +610,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
<ClCompile Include="..\..\src\joystick\SDL_gamecontroller.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>
@ -943,6 +946,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

@ -125,6 +125,7 @@
<ClInclude Include="..\src\joystick\controller_type.h" />
<ClInclude Include="..\src\joystick\SDL_gamecontrollerdb.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" />
@ -237,6 +238,7 @@
<ClCompile Include="..\src\joystick\controller_type.c" />
<ClCompile Include="..\src\joystick\SDL_gamecontroller.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

@ -255,6 +255,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>
@ -558,6 +561,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>
@ -846,4 +852,4 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
</Project>

View file

@ -336,6 +336,7 @@
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.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" />
@ -501,6 +502,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
<ClCompile Include="..\..\src\joystick\SDL_gamecontroller.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>
@ -934,6 +937,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

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@ -3396,6 +3396,33 @@
F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; };
F34B9896291DEFF700AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; };
F34B9897291DEFFA00AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; };
F362B9202B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9212B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9222B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9232B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9242B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9252B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9262B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9272B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9282B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9292B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92A2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92B2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92C2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92D2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92F2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B9302B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B9312B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B9322B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9332B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9342B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9352B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9362B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9372B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9382B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9392B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B93A2B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F3631C6424884ACF004F28EA /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26792462701100718109 /* SDL_locale.h */; settings = {ATTRIBUTES = (Public, ); }; };
F3631C652488534E004F28EA /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26792462701100718109 /* SDL_locale.h */; settings = {ATTRIBUTES = (Public, ); }; };
F376F6192559B29300CFC0BC /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F376F6182559B29300CFC0BC /* OpenGLES.framework */; platformFilter = ios; };
@ -4107,6 +4134,9 @@
F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_offscreenopengles.h; sourceTree = "<group>"; };
F31A92C728D4CB39003BFD6A /* SDL_offscreenopengles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_offscreenopengles.c; sourceTree = "<group>"; };
F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_combined.c; sourceTree = "<group>"; };
F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_steam_virtual_gamepad.c; sourceTree = "<group>"; };
F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_steam_virtual_gamepad.h; sourceTree = "<group>"; };
F362B91F2B33916600D30B94 /* controller_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_list.h; 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; };
F376F6312559B31D00CFC0BC /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/iOSSupport/System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
@ -4950,12 +4980,15 @@
A7D8A7AA23E2513E00DCD162 /* iphoneos */,
A7D8A7A123E2513E00DCD162 /* steam */,
75E09157241EA924004729E1 /* virtual */,
A7D8A7AD23E2513E00DCD162 /* SDL_gamecontroller.c */,
A7D8A7A923E2513E00DCD162 /* SDL_joystick.c */,
F362B91F2B33916600D30B94 /* controller_list.h */,
F3820712284F3609004DD584 /* controller_type.c */,
A7D8A7D923E2513E00DCD162 /* controller_type.h */,
A7D8A7AD23E2513E00DCD162 /* SDL_gamecontroller.c */,
A7D8A79E23E2513E00DCD162 /* SDL_gamecontrollerdb.h */,
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 */,
);
@ -5456,6 +5489,7 @@
A75FCD4323E25AB700529352 /* SDL_keyboard.h in Headers */,
A75FCD4423E25AB700529352 /* SDL_uikitevents.h in Headers */,
A75FCD4523E25AB700529352 /* SDL_gesture_c.h in Headers */,
F362B9392B33916600D30B94 /* controller_list.h in Headers */,
A75FCD4623E25AB700529352 /* SDL_shaders_gl.h in Headers */,
A75FCD4723E25AB700529352 /* SDL_systhread_c.h in Headers */,
A1BB8B7327F6CF330057CFA8 /* SDL_list.h in Headers */,
@ -5540,6 +5574,7 @@
A75FCD9E23E25AB700529352 /* controller_type.h in Headers */,
A75FCDA023E25AB700529352 /* SDL_uikitclipboard.h in Headers */,
A75FCDA123E25AB700529352 /* vulkan_xlib.h in Headers */,
F362B9302B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A75FCDA223E25AB700529352 /* SDL_uikitwindow.h in Headers */,
A75FCDA323E25AB700529352 /* vulkan_vi.h in Headers */,
A75FCDA423E25AB700529352 /* vulkan_mir.h in Headers */,
@ -5685,6 +5720,7 @@
A75FCEFC23E25AC700529352 /* SDL_keyboard.h in Headers */,
A75FCEFD23E25AC700529352 /* SDL_uikitevents.h in Headers */,
A75FCEFE23E25AC700529352 /* SDL_gesture_c.h in Headers */,
F362B93A2B33916600D30B94 /* controller_list.h in Headers */,
A75FCEFF23E25AC700529352 /* SDL_shaders_gl.h in Headers */,
A75FCF0023E25AC700529352 /* SDL_systhread_c.h in Headers */,
A1BB8B7427F6CF330057CFA8 /* SDL_list.h in Headers */,
@ -5769,6 +5805,7 @@
A75FCF5723E25AC700529352 /* controller_type.h in Headers */,
A75FCF5923E25AC700529352 /* SDL_uikitclipboard.h in Headers */,
A75FCF5A23E25AC700529352 /* vulkan_xlib.h in Headers */,
F362B9312B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A75FCF5B23E25AC700529352 /* SDL_uikitwindow.h in Headers */,
A75FCF5C23E25AC700529352 /* vulkan_vi.h in Headers */,
A75FCF5D23E25AC700529352 /* vulkan_mir.h in Headers */,
@ -5933,6 +5970,7 @@
A769B10223E259AE00872273 /* math_private.h in Headers */,
A769B10323E259AE00872273 /* vulkan_wayland.h in Headers */,
A769B10523E259AE00872273 /* SDL_cocoashape.h in Headers */,
F362B92E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A769B10723E259AE00872273 /* SDL_shaders_gles2.h in Headers */,
A769B10923E259AE00872273 /* SDL_glesfuncs.h in Headers */,
A769B10A23E259AE00872273 /* SDL_blendpoint.h in Headers */,
@ -5997,6 +6035,7 @@
A769B15623E259AE00872273 /* SDL_syshaptic.h in Headers */,
A769B15723E259AE00872273 /* SDL_vulkan_internal.h in Headers */,
A769B15923E259AE00872273 /* SDL_cocoaevents.h in Headers */,
F362B9372B33916600D30B94 /* controller_list.h in Headers */,
A769B15A23E259AE00872273 /* vk_icd.h in Headers */,
A769B15B23E259AE00872273 /* SDL_nullframebuffer_c.h in Headers */,
A769B15D23E259AE00872273 /* SDL_dynapi_procs.h in Headers */,
@ -6218,6 +6257,7 @@
A7D8BB2223E2514500DCD162 /* scancodes_windows.h in Headers */,
A7D8BBA023E2514500DCD162 /* scancodes_xfree86.h in Headers */,
A7D8B57023E2514300DCD162 /* usb_ids.h in Headers */,
F362B92A2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A1626A532617008D003F1973 /* SDL_triangle.h in Headers */,
A7D8B25523E2514200DCD162 /* vk_icd.h in Headers */,
A7D8B24F23E2514200DCD162 /* vk_layer.h in Headers */,
@ -6234,6 +6274,7 @@
A7D8B25B23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B27923E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8B27F23E2514200DCD162 /* vulkan_win32.h in Headers */,
F362B9332B33916600D30B94 /* controller_list.h in Headers */,
A7D8B29123E2514200DCD162 /* vulkan_xcb.h in Headers */,
A7D8B29D23E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8B28B23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */,
@ -6452,6 +6493,7 @@
A7D8BB2323E2514500DCD162 /* scancodes_windows.h in Headers */,
A7D8BBA123E2514500DCD162 /* scancodes_xfree86.h in Headers */,
A7D8B57123E2514300DCD162 /* usb_ids.h in Headers */,
F362B92B2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A1626A542617008D003F1973 /* SDL_triangle.h in Headers */,
A7D8B25623E2514200DCD162 /* vk_icd.h in Headers */,
A7D8B25023E2514200DCD162 /* vk_layer.h in Headers */,
@ -6468,6 +6510,7 @@
A7D8B25C23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B27A23E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8B28023E2514200DCD162 /* vulkan_win32.h in Headers */,
F362B9342B33916600D30B94 /* controller_list.h in Headers */,
A7D8B29223E2514200DCD162 /* vulkan_xcb.h in Headers */,
A7D8B29E23E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8B28C23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */,
@ -6570,6 +6613,7 @@
A7D8BAC523E2514500DCD162 /* math_private.h in Headers */,
A7D8B27C23E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8AE8623E2514100DCD162 /* SDL_cocoashape.h in Headers */,
F362B92D2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A7D8BA5323E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
A7D8BA4723E2514400DCD162 /* SDL_glesfuncs.h in Headers */,
A7D8BA1123E2514400DCD162 /* SDL_blendpoint.h in Headers */,
@ -6634,6 +6678,7 @@
A7D8AAD823E2514100DCD162 /* SDL_syshaptic.h in Headers */,
A7D8AD2123E2514100DCD162 /* SDL_vulkan_internal.h in Headers */,
A7D8AF1623E2514100DCD162 /* SDL_cocoaevents.h in Headers */,
F362B9362B33916600D30B94 /* controller_list.h in Headers */,
A7D8B25823E2514200DCD162 /* vk_icd.h in Headers */,
A7D8ABE923E2514100DCD162 /* SDL_nullframebuffer_c.h in Headers */,
A7D8AB2023E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
@ -6855,6 +6900,7 @@
A7D8BB2123E2514500DCD162 /* scancodes_windows.h in Headers */,
A7D8BB9F23E2514500DCD162 /* scancodes_xfree86.h in Headers */,
A7D8B56F23E2514300DCD162 /* usb_ids.h in Headers */,
F362B9292B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A1626A522617008D003F1973 /* SDL_triangle.h in Headers */,
A7D8B25423E2514200DCD162 /* vk_icd.h in Headers */,
A7D8B24E23E2514200DCD162 /* vk_layer.h in Headers */,
@ -6871,6 +6917,7 @@
A7D8B25A23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B27823E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8B27E23E2514200DCD162 /* vulkan_win32.h in Headers */,
F362B9322B33916600D30B94 /* controller_list.h in Headers */,
A7D8B29023E2514200DCD162 /* vulkan_xcb.h in Headers */,
A7D8B29C23E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8B28A23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */,
@ -6888,6 +6935,7 @@
A7D8AC0C23E2514100DCD162 /* SDL_shape_internals.h in Headers */,
A7D8BA7C23E2514400DCD162 /* SDL_glfuncs.h in Headers */,
A7D8AC0623E2514100DCD162 /* SDL_rect_c.h in Headers */,
F362B9352B33916600D30B94 /* controller_list.h in Headers */,
75E09166241EA924004729E1 /* SDL_virtualjoystick_c.h in Headers */,
A7D8B99E23E2514400DCD162 /* SDL_shaders_metal_osx.h in Headers */,
A7D8B98F23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
@ -6963,6 +7011,7 @@
A7D8BBFF23E2574800DCD162 /* SDL_uikitview.h in Headers */,
A7D8BBA823E2514500DCD162 /* SDL_events_c.h in Headers */,
A7D8BAC423E2514500DCD162 /* math_private.h in Headers */,
F362B92C2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A7D8B27B23E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8BBF523E2574800DCD162 /* SDL_uikitmetalview.h in Headers */,
A7D8AE8523E2514100DCD162 /* SDL_cocoashape.h in Headers */,
@ -7122,6 +7171,7 @@
DB313FDA17554B71006C0E22 /* SDL_keyboard.h in Headers */,
A7D8ACC223E2514100DCD162 /* SDL_uikitevents.h in Headers */,
A7D8BB3E23E2514500DCD162 /* SDL_gesture_c.h in Headers */,
F362B9382B33916600D30B94 /* controller_list.h in Headers */,
A7D8BA7823E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A7D8B42D23E2514300DCD162 /* SDL_systhread_c.h in Headers */,
A1BB8B7227F6CF330057CFA8 /* SDL_list.h in Headers */,
@ -7206,6 +7256,7 @@
A7D8AC7A23E2514100DCD162 /* SDL_uikitclipboard.h in Headers */,
A7D8B2A123E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8AC9E23E2514100DCD162 /* SDL_uikitwindow.h in Headers */,
F362B92F2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A7D8B25F23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B29B23E2514200DCD162 /* vulkan_mir.h in Headers */,
DB313FE817554B71006C0E22 /* SDL_quit.h in Headers */,
@ -7797,6 +7848,7 @@
A75FCE2823E25AB700529352 /* SDL_dropevents.c in Sources */,
A75FCE2923E25AB700529352 /* e_atan2.c in Sources */,
A75FCE2A23E25AB700529352 /* s_sin.c in Sources */,
F362B9272B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A75FCE2B23E25AB700529352 /* SDL_power.c in Sources */,
A75FCE2C23E25AB700529352 /* SDL_cocoakeyboard.m in Sources */,
A75FCE2D23E25AB700529352 /* SDL_dynapi.c in Sources */,
@ -7993,6 +8045,7 @@
A75FCFE123E25AC700529352 /* SDL_dropevents.c in Sources */,
A75FCFE223E25AC700529352 /* e_atan2.c in Sources */,
A75FCFE323E25AC700529352 /* s_sin.c in Sources */,
F362B9282B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A75FCFE423E25AC700529352 /* SDL_power.c in Sources */,
A75FCFE523E25AC700529352 /* SDL_cocoakeyboard.m in Sources */,
A75FCFE623E25AC700529352 /* SDL_dynapi.c in Sources */,
@ -8303,6 +8356,7 @@
A769B22723E259AE00872273 /* e_sqrt.c in Sources */,
A769B22823E259AE00872273 /* SDL_cocoavideo.m in Sources */,
A769B22923E259AE00872273 /* SDL.c in Sources */,
F362B9252B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A769B22B23E259AE00872273 /* SDL_cocoavulkan.m in Sources */,
A769B22C23E259AE00872273 /* SDL_uikitappdelegate.m in Sources */,
A1626A432617006A003F1973 /* SDL_triangle.c in Sources */,
@ -8386,6 +8440,7 @@
A7D8B5E823E2514300DCD162 /* SDL_power.c in Sources */,
A7D8AED723E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */,
A7D8AB1723E2514100DCD162 /* SDL_dynapi.c in Sources */,
F362B9212B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BA8623E2514400DCD162 /* SDL_shaders_gl.c in Sources */,
A7D8BAF223E2514500DCD162 /* e_log.c in Sources */,
A7D8AED123E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */,
@ -8582,6 +8637,7 @@
A7D8B5E923E2514300DCD162 /* SDL_power.c in Sources */,
A7D8AED823E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */,
A7D8AB1823E2514100DCD162 /* SDL_dynapi.c in Sources */,
F362B9222B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BA8723E2514400DCD162 /* SDL_shaders_gl.c in Sources */,
A7D8BAF323E2514500DCD162 /* e_log.c in Sources */,
A7D8AED223E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */,
@ -8892,6 +8948,7 @@
A7D8BAFB23E2514500DCD162 /* e_sqrt.c in Sources */,
A7D8AEB023E2514100DCD162 /* SDL_cocoavideo.m in Sources */,
A7D8A94F23E2514000DCD162 /* SDL.c in Sources */,
F362B9242B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8AEA423E2514100DCD162 /* SDL_cocoavulkan.m in Sources */,
A7D8AC6723E2514100DCD162 /* SDL_uikitappdelegate.m in Sources */,
A1626A422617006A003F1973 /* SDL_triangle.c in Sources */,
@ -8955,6 +9012,7 @@
A7D8BA1F23E2514400DCD162 /* SDL_blendline.c in Sources */,
A7D8BBE723E2574800DCD162 /* SDL_uikitviewcontroller.m in Sources */,
A7D8ADF223E2514100DCD162 /* SDL_blit_A.c in Sources */,
F362B9202B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BBDD23E2574800DCD162 /* SDL_uikitmodes.m in Sources */,
A7D8BA3723E2514400DCD162 /* SDL_d3dmath.c in Sources */,
75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */,
@ -8999,6 +9057,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 */,
@ -9150,6 +9209,7 @@
A7D8B53C23E2514300DCD162 /* SDL_hidapi_xbox360.c in Sources */,
A7D8B8D523E2514400DCD162 /* SDL_coreaudio.m in Sources */,
A7D8BA2223E2514400DCD162 /* SDL_blendline.c in Sources */,
F362B9232B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BC0623E2574800DCD162 /* SDL_uikitwindow.m in Sources */,
A7D8ADF523E2514100DCD162 /* SDL_blit_A.c in Sources */,
A7D8BA3A23E2514400DCD162 /* SDL_d3dmath.c in Sources */,
@ -9345,6 +9405,7 @@
A7D8B8D723E2514400DCD162 /* SDL_coreaudio.m in Sources */,
A7D8BA2423E2514400DCD162 /* SDL_blendline.c in Sources */,
A7D8ADF723E2514100DCD162 /* SDL_blit_A.c in Sources */,
F362B9262B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BA3C23E2514400DCD162 /* SDL_d3dmath.c in Sources */,
A7D8ABF023E2514100DCD162 /* SDL_nullvideo.c in Sources */,
A7D8AB6C23E2514100DCD162 /* SDL_offscreenevents.c in Sources */,

View file

@ -131,6 +131,8 @@ typedef enum
SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */
SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */
SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */
SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3,
SDL_CONTROLLERSTEAMHANDLEUPDATED, /**< Game controller Steam handle has changed */
/* Touch events */
SDL_FINGERDOWN = 0x700,
@ -446,7 +448,7 @@ typedef struct SDL_ControllerButtonEvent
*/
typedef struct SDL_ControllerDeviceEvent
{
Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, ::SDL_CONTROLLERDEVICEREMAPPED, or ::SDL_CONTROLLERSTEAMHANDLEUPDATED */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
} SDL_ControllerDeviceEvent;

View file

@ -524,6 +524,20 @@ extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetFirmwareVersion(SDL_GameCont
*/
extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller);
/**
* Get the Steam Input handle of an opened controller, if available.
*
* Returns an InputHandle_t for the controller that can be used with Steam Input API:
* https://partner.steamgames.com/doc/api/ISteamInput
*
* \param gamecontroller the game controller object to query.
* \returns the gamepad handle, or 0 if unavailable.
*
* \since This function is available since SDL 2.30.0.
*/
extern DECLSPEC Uint64 SDLCALL SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller);
/**
* Check if a controller has been opened and is currently connected.
*

View file

@ -871,3 +871,4 @@
++'_SDL_HasWindowSurface'.'SDL2.dll'.'SDL_HasWindowSurface'
++'_SDL_DestroyWindowSurface'.'SDL2.dll'.'SDL_DestroyWindowSurface'
# ++'_SDL_GDKGetDefaultUser'.'SDL2.dll'.'SDL_GDKGetDefaultUser'
++'_SDL_GameControllerGetSteamHandle'.'SDL2.dll'.'SDL_GameControllerGetSteamHandle'

View file

@ -897,3 +897,4 @@
#define SDL_HasWindowSurface SDL_HasWindowSurface_REAL
#define SDL_DestroyWindowSurface SDL_DestroyWindowSurface_REAL
#define SDL_GDKGetDefaultUser SDL_GDKGetDefaultUser_REAL
#define SDL_GameControllerGetSteamHandle SDL_GameControllerGetSteamHandle_REAL

View file

@ -984,3 +984,4 @@ SDL_DYNAPI_PROC(int,SDL_DestroyWindowSurface,(SDL_Window *a),(a),return)
#if defined(__GDK__)
SDL_DYNAPI_PROC(int,SDL_GDKGetDefaultUser,(XUserHandle *a),(a),return)
#endif
SDL_DYNAPI_PROC(Uint64,SDL_GameControllerGetSteamHandle,(SDL_GameController *a),(a),return)

View file

@ -425,6 +425,9 @@ static void SDL_LogEvent(const SDL_Event *event)
SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMAPPED)
PRINT_CONTROLLERDEV_EVENT(event);
break;
SDL_EVENT_CASE(SDL_CONTROLLERSTEAMHANDLEUPDATED)
PRINT_CONTROLLERDEV_EVENT(event);
break;
#undef PRINT_CONTROLLERDEV_EVENT
#define PRINT_CTOUCHPAD_EVENT(event) \

View file

@ -27,6 +27,7 @@
#include "SDL_timer.h"
#include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
#include "SDL_gamecontrollerdb.h"
#include "controller_type.h"
#include "usb_ids.h"
@ -822,7 +823,7 @@ SDL_COMPILE_TIME_ASSERT(map_StringForGameControllerType, SDL_arraysize(map_Strin
/*
* convert a string to its enum equivalent
*/
static SDL_GameControllerType SDL_GetGameControllerTypeFromString(const char *str)
SDL_GameControllerType SDL_GetGameControllerTypeFromString(const char *str)
{
int i;
@ -2675,7 +2676,8 @@ const char *SDL_GameControllerName(SDL_GameController *gamecontroller)
{
CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL);
if (SDL_strcmp(gamecontroller->name, "*") == 0) {
if (SDL_strcmp(gamecontroller->name, "*") == 0 ||
gamecontroller->joystick->steam_handle != 0) {
retval = SDL_JoystickName(gamecontroller->joystick);
} else {
retval = gamecontroller->name;
@ -2698,15 +2700,27 @@ const char *SDL_GameControllerPath(SDL_GameController *gamecontroller)
SDL_GameControllerType SDL_GameControllerGetType(SDL_GameController *gamecontroller)
{
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller);
SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
SDL_Joystick *joystick;
const SDL_SteamVirtualGamepadInfo *info;
if (!joystick) {
return SDL_CONTROLLER_TYPE_UNKNOWN;
SDL_LockJoysticks();
{
CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_CONTROLLER_TYPE_UNKNOWN);
joystick = gamecontroller->joystick;
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
type = info->type;
} else if (gamecontroller->type != SDL_CONTROLLER_TYPE_UNKNOWN) {
type = gamecontroller->type;
} else {
type = SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetGUID(joystick), SDL_JoystickName(joystick));
}
}
if (gamecontroller->type != SDL_CONTROLLER_TYPE_UNKNOWN) {
return gamecontroller->type;
}
return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetGUID(joystick), SDL_JoystickName(joystick));
SDL_UnlockJoysticks();
return type;
}
int SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller)
@ -2782,6 +2796,21 @@ const char * SDL_GameControllerGetSerial(SDL_GameController *gamecontroller)
return SDL_JoystickGetSerial(joystick);
}
Uint64 SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller)
{
Uint64 handle = 0;
SDL_LockJoysticks();
{
CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0);
handle = gamecontroller->joystick->steam_handle;
}
SDL_UnlockJoysticks();
return handle;
}
/*
* Return if the controller in question is currently attached to the system,
* \return 0 if not plugged in, 1 if still present.

View file

@ -28,6 +28,7 @@
#include "SDL_sysjoystick.h"
#include "SDL_hints.h"
#include "../SDL_hints_c.h"
#include "SDL_steam_virtual_gamepad.h"
#ifndef SDL_EVENTS_DISABLED
#include "../events/SDL_events_c.h"
@ -622,6 +623,8 @@ int SDL_JoystickInit(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) {
@ -660,6 +663,19 @@ SDL_JoystickID SDL_GetNextJoystickInstanceID()
return SDL_AtomicIncRef(&SDL_next_joystick_instance_id);
}
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(SDL_JoystickGetDeviceIndexFromInstanceID(instance_id), &driver, &device_index)) {
info = SDL_GetSteamVirtualGamepadInfo(driver->GetDeviceSteamVirtualGamepadSlot(device_index));
}
return info;
}
/*
* Get the implementation dependent name of a joystick
*/
@ -667,9 +683,13 @@ const char *SDL_JoystickNameForIndex(int device_index)
{
SDL_JoystickDriver *driver;
const char *name = NULL;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
info = SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickGetDeviceInstanceID(device_index));
if (info) {
name = info->name;
} else if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
name = driver->GetDeviceName(device_index);
}
SDL_UnlockJoysticks();
@ -750,6 +770,7 @@ SDL_Joystick *SDL_JoystickOpen(int device_index)
const char *joystickname = NULL;
const char *joystickpath = NULL;
SDL_JoystickPowerLevel initial_power_level;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
@ -839,6 +860,12 @@ SDL_Joystick *SDL_JoystickOpen(int device_index)
joystick->is_game_controller = SDL_IsGameController(device_index);
/* Get the Steam Input API handle */
info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id);
if (info) {
joystick->steam_handle = info->handle;
}
/* Add joystick to list */
++joystick->ref_count;
/* Link the joystick in the list */
@ -1282,15 +1309,20 @@ SDL_Joystick *SDL_JoystickFromPlayerIndex(int player_index)
const char *SDL_JoystickName(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;
}
@ -1609,6 +1641,8 @@ void SDL_JoystickQuit(void)
SDL_QuitSubSystem(SDL_INIT_EVENTS);
#endif
SDL_QuitSteamVirtualGamepadInfo();
SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
SDL_JoystickAllowBackgroundEventsChanged, NULL);
@ -1709,7 +1743,10 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
}
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
player_index = driver->GetDevicePlayerIndex(driver_device_index);
player_index = driver->GetDeviceSteamVirtualGamepadSlot(driver_device_index);
if (player_index < 0) {
player_index = driver->GetDevicePlayerIndex(driver_device_index);
}
}
if (player_index < 0 && SDL_IsGameController(device_index)) {
player_index = SDL_FindFreePlayerIndex();
@ -2064,6 +2101,43 @@ int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
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_game_controller) {
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_CONTROLLERSTEAMHANDLEUPDATED;
event.common.timestamp = 0;
event.cdevice.which = joystick->instance_id;
SDL_PushEvent(&event);
}
}
}
void SDL_JoystickUpdate(void)
{
int i;
@ -2076,6 +2150,10 @@ void SDL_JoystickUpdate(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();
@ -2906,18 +2984,38 @@ SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
Uint16 SDL_JoystickGetDeviceVendor(int device_index)
{
Uint16 vendor;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickGetDeviceInstanceID(device_index));
if (info) {
vendor = info->vendor_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
return vendor;
}
Uint16 SDL_JoystickGetDeviceProduct(int device_index)
{
Uint16 product;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickGetDeviceInstanceID(device_index));
if (info) {
product = info->product_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
return product;
}
@ -2995,18 +3093,38 @@ SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick *joystick)
Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick)
{
Uint16 vendor;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
vendor = info->vendor_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
return vendor;
}
Uint16 SDL_JoystickGetProduct(SDL_Joystick *joystick)
{
Uint16 product;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
product = info->product_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
return product;
}

View file

@ -34,6 +34,7 @@ extern "C" {
#endif
struct _SDL_JoystickDriver;
struct SDL_SteamVirtualGamepadInfo;
extern char SDL_joystick_magic;
/* Initialization and shutdown functions */
@ -179,6 +180,9 @@ extern int SDL_PrivateJoystickSensor(SDL_Joystick *joystick,
extern void SDL_PrivateJoystickBatteryLevel(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_PrivateJoystickValid(SDL_Joystick *joystick);

View file

@ -0,0 +1,252 @@
/*
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_hints.h"
#include "SDL_timer.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"
extern SDL_GameControllerType SDL_GetGameControllerTypeFromString(const char *str);
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 Uint32 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;
Uint32 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 &&
!SDL_TICKS_PASSED(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_GetGameControllerTypeFromString(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_GameControllerType 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

@ -79,6 +79,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;
@ -167,6 +168,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

@ -542,6 +542,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;
@ -682,6 +687,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = {
ANDROID_JoystickDetect,
ANDROID_JoystickGetDeviceName,
ANDROID_JoystickGetDevicePath,
ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot,
ANDROID_JoystickGetDevicePlayerIndex,
ANDROID_JoystickSetDevicePlayerIndex,
ANDROID_JoystickGetDeviceGUID,

View file

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

View file

@ -407,6 +407,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;
@ -487,6 +500,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) {
@ -714,6 +728,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;
@ -1059,6 +1079,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

@ -52,6 +52,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;
@ -131,6 +136,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = {
DUMMY_JoystickDetect,
DUMMY_JoystickGetDeviceName,
DUMMY_JoystickGetDevicePath,
DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot,
DUMMY_JoystickGetDevicePlayerIndex,
DUMMY_JoystickSetDevicePlayerIndex,
DUMMY_JoystickGetDeviceGUID,

View file

@ -274,6 +274,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;
@ -421,6 +426,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = {
EMSCRIPTEN_JoystickDetect,
EMSCRIPTEN_JoystickGetDeviceName,
EMSCRIPTEN_JoystickGetDevicePath,
EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot,
EMSCRIPTEN_JoystickGetDevicePlayerIndex,
EMSCRIPTEN_JoystickSetDevicePlayerIndex,
EMSCRIPTEN_JoystickGetDeviceGUID,

View file

@ -102,6 +102,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;
@ -299,6 +304,7 @@ extern "C"
HAIKU_JoystickDetect,
HAIKU_JoystickGetDeviceName,
HAIKU_JoystickGetDevicePath,
HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot,
HAIKU_JoystickGetDevicePlayerIndex,
HAIKU_JoystickSetDevicePlayerIndex,
HAIKU_JoystickGetDeviceGUID,

View file

@ -1373,6 +1373,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;
@ -1651,6 +1656,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = {
HIDAPI_JoystickDetect,
HIDAPI_JoystickGetDeviceName,
HIDAPI_JoystickGetDevicePath,
HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot,
HIDAPI_JoystickGetDevicePlayerIndex,
HIDAPI_JoystickSetDevicePlayerIndex,
HIDAPI_JoystickGetDeviceGUID,

View file

@ -668,6 +668,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;
@ -712,6 +716,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;
}
@ -905,6 +910,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
@ -2163,6 +2173,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = {
IOS_JoystickDetect,
IOS_JoystickGetDeviceName,
IOS_JoystickGetDevicePath,
IOS_JoystickGetDeviceSteamVirtualGamepadSlot,
IOS_JoystickGetDevicePlayerIndex,
IOS_JoystickSetDevicePlayerIndex,
IOS_JoystickGetDeviceGUID,

View file

@ -221,14 +221,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;
@ -441,7 +445,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);
@ -456,7 +459,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)) {
@ -483,7 +486,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;
@ -501,8 +503,10 @@ static void MaybeAddDevice(const char *path)
goto done;
}
close(fd);
done:
if (fd >= 0) {
close(fd);
}
SDL_UnlockJoysticks();
}
@ -870,7 +874,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;
@ -885,8 +888,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];
@ -1112,11 +1114,16 @@ static const char *LINUX_JoystickGetDevicePath(int device_index)
return JoystickByDevIndex(device_index)->path;
}
static int LINUX_JoystickGetDevicePlayerIndex(int device_index)
static int LINUX_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return JoystickByDevIndex(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)
{
}
@ -2736,6 +2743,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = {
LINUX_JoystickDetect,
LINUX_JoystickGetDeviceName,
LINUX_JoystickGetDevicePath,
LINUX_JoystickGetDeviceSteamVirtualGamepadSlot,
LINUX_JoystickGetDevicePlayerIndex,
LINUX_JoystickSetDevicePlayerIndex,
LINUX_JoystickGetDeviceGUID,

View file

@ -234,6 +234,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;
@ -274,6 +279,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

@ -160,6 +160,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)
{
@ -343,6 +349,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = {
PS2_JoystickDetect,
PS2_JoystickGetDeviceName,
PS2_JoystickGetDevicePath,
PS2_JoystickGetDeviceSteamVirtualGamepadSlot,
PS2_JoystickGetDevicePlayerIndex,
PS2_JoystickSetDevicePlayerIndex,
PS2_JoystickGetDeviceGUID,

View file

@ -124,6 +124,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;
@ -255,6 +260,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = {
PSP_JoystickDetect,
PSP_JoystickGetDeviceName,
PSP_JoystickGetDevicePath,
PSP_JoystickGetDeviceSteamVirtualGamepadSlot,
PSP_JoystickGetDevicePlayerIndex,
PSP_JoystickSetDevicePlayerIndex,
PSP_JoystickGetDeviceGUID,

View file

@ -362,6 +362,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;
@ -722,6 +727,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = {
VIRTUAL_JoystickDetect,
VIRTUAL_JoystickGetDeviceName,
VIRTUAL_JoystickGetDevicePath,
VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot,
VIRTUAL_JoystickGetDevicePlayerIndex,
VIRTUAL_JoystickSetDevicePlayerIndex,
VIRTUAL_JoystickGetDeviceGUID,

View file

@ -187,6 +187,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;
@ -377,6 +382,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = {
VITA_JoystickDetect,
VITA_JoystickGetDeviceName,
VITA_JoystickGetDevicePath,
VITA_JoystickGetDeviceSteamVirtualGamepadSlot,
VITA_JoystickGetDevicePlayerIndex,
VITA_JoystickSetDevicePlayerIndex,
VITA_JoystickGetDeviceGUID,

View file

@ -437,6 +437,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)
{
@ -489,10 +500,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

@ -119,6 +119,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;
@ -836,6 +837,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) \
@ -877,6 +891,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;
@ -1183,6 +1198,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;
@ -2175,6 +2195,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = {
RAWINPUT_JoystickDetect,
RAWINPUT_JoystickGetDeviceName,
RAWINPUT_JoystickGetDevicePath,
RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,
RAWINPUT_JoystickGetDevicePlayerIndex,
RAWINPUT_JoystickSetDevicePlayerIndex,
RAWINPUT_JoystickGetDeviceGUID,

View file

@ -64,6 +64,7 @@ typedef struct WindowsGamingInputControllerState
int naxes;
int nhats;
int nbuttons;
int steam_virtual_gamepad_slot;
} WindowsGamingInputControllerState;
static struct
@ -385,6 +386,50 @@ 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_IRawGameController2, (void **)&controller2);
if (SUCCEEDED(hr)) {
HSTRING hString;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_NonRoamableId(controller2, &hString);
if (SUCCEEDED(hr)) {
typedef PCWSTR(WINAPI * WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 * length);
typedef HRESULT(WINAPI * WindowsDeleteString_t)(HSTRING string);
WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = NULL;
WindowsDeleteString_t WindowsDeleteStringFunc = NULL;
#ifdef __WINRT__
WindowsGetStringRawBufferFunc = WindowsGetStringRawBuffer;
WindowsDeleteStringFunc = WindowsDeleteString;
#else
{
WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)WIN_LoadComBaseFunction("WindowsGetStringRawBuffer");
WindowsDeleteStringFunc = (WindowsDeleteString_t)WIN_LoadComBaseFunction("WindowsDeleteString");
}
#endif /* __WINRT__ */
if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) {
PCWSTR string = WindowsGetStringRawBufferFunc(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);
}
}
WindowsDeleteStringFunc(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;
@ -502,6 +547,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_get_ButtonCount(controller, &state->nbuttons);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(controller, &state->naxes);
@ -688,6 +734,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;
@ -1004,6 +1055,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = {
WGI_JoystickDetect,
WGI_JoystickGetDeviceName,
WGI_JoystickGetDevicePath,
WGI_JoystickGetDeviceSteamVirtualGamepadSlot,
WGI_JoystickGetDevicePlayerIndex,
WGI_JoystickSetDevicePlayerIndex,
WGI_JoystickGetDeviceGUID,

View file

@ -618,6 +618,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;
@ -676,12 +693,10 @@ 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_malloc(sizeof(struct joystick_hwdata));
joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata));
if (!joystick->hwdata) {
return SDL_OutOfMemory();
}
SDL_zerop(joystick->hwdata);
joystick->hwdata->guid = device->guid;
if (device->bXInputDevice) {
@ -800,6 +815,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = {
WINDOWS_JoystickDetect,
WINDOWS_JoystickGetDeviceName,
WINDOWS_JoystickGetDevicePath,
WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot,
WINDOWS_JoystickGetDevicePlayerIndex,
WINDOWS_JoystickSetDevicePlayerIndex,
WINDOWS_JoystickGetDeviceGUID,

View file

@ -43,6 +43,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

@ -129,13 +129,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