Skip to content

Implement SInput Device Support #13343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Jul 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7b5f404
WIP on Hoja Gamepad Implementation
mitchellcairns Jun 25, 2025
4ba4b45
Check-in
mitchellcairns Jun 25, 2025
e7f6477
SInput Name Change
mitchellcairns Jul 4, 2025
17d58cd
Change feature and command
mitchellcairns Jul 6, 2025
b39fb97
SInput Power States
mitchellcairns Jul 8, 2025
7cccaeb
Log Message define guards
mitchellcairns Jul 8, 2025
93a01c4
Fix PIDs
mitchellcairns Jul 8, 2025
41843fa
Fix Misc 2 mapping
mitchellcairns Jul 8, 2025
3a3424e
Cleanup
mitchellcairns Jul 8, 2025
17c92d1
Fix Hint Naming Scheme
mitchellcairns Jul 8, 2025
e9007fa
GDK Inclusion
mitchellcairns Jul 8, 2025
9c84288
Xcode Inclusion
mitchellcairns Jul 8, 2025
a903d06
Match Mac file formatting
mitchellcairns Jul 8, 2025
85951c6
Update usb_ids.h
mitchellcairns Jul 9, 2025
61cbe74
Update src/joystick/SDL_gamepad.c
mitchellcairns Jul 9, 2025
0950b43
Bitfield Removal
mitchellcairns Jul 9, 2025
415a05d
Implement Firebird mapping
mitchellcairns Jul 10, 2025
9c48fea
Implement Firebird mapping
mitchellcairns Jul 10, 2025
050c2a4
Merge remote-tracking branch 'origin/sinput' into sinput
mitchellcairns Jul 10, 2025
1bd309c
Merge remote-tracking branch 'origin/main' into sinput
mitchellcairns Jul 11, 2025
fe578cf
Code Review 1 Changes
mitchellcairns Jul 12, 2025
067f2a4
Remove unused functions
mitchellcairns Jul 12, 2025
4c115dd
Review Changes
mitchellcairns Jul 12, 2025
7c0f37f
GC Ultimate mapping change
mitchellcairns Jul 12, 2025
b28f600
Review Changes
mitchellcairns Jul 13, 2025
0902f81
Merge remote-tracking branch 'origin/main' into sinput
mitchellcairns Jul 15, 2025
67de7e4
Sub-ID Update
mitchellcairns Jul 15, 2025
7eb44ff
NULL return for incomplete mappings
mitchellcairns Jul 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions VisualC-GDK/SDL/SDL.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps5.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_shield.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_sinput.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
Expand Down
1 change: 1 addition & 0 deletions VisualC-GDK/SDL/SDL.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps5.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_shield.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_sinput.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
Expand Down
3 changes: 2 additions & 1 deletion VisualC/SDL/SDL.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps5.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_shield.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_sinput.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam.c" />
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
Expand Down Expand Up @@ -774,4 +775,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
5 changes: 4 additions & 1 deletion VisualC/SDL/SDL.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,9 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_shield.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_sinput.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_stadia.c">
<Filter>joystick\hidapi</Filter>
</ClCompile>
Expand Down Expand Up @@ -1615,4 +1618,4 @@
<ItemGroup>
<ResourceCompile Include="..\..\src\core\windows\version.rc" />
</ItemGroup>
</Project>
</Project>
4 changes: 4 additions & 0 deletions Xcode/SDL/SDL.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
89E580242D03606400DAF6D3 /* SDL_hidapihaptic_lg4ff.c in Sources */ = {isa = PBXBuildFile; fileRef = 89E580212D03606400DAF6D3 /* SDL_hidapihaptic_lg4ff.c */; };
89E580252D03606400DAF6D3 /* SDL_hidapihaptic_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 89E580202D03606400DAF6D3 /* SDL_hidapihaptic_c.h */; };
9846B07C287A9020000C35C8 /* SDL_hidapi_shield.c in Sources */ = {isa = PBXBuildFile; fileRef = 9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */; };
02D6A1C228A84B8F00A7F002 /* SDL_hidapi_sinput.c in Sources */ = {isa = PBXBuildFile; fileRef = 02D6A1C128A84B8F00A7F001 /* SDL_hidapi_sinput.c */; };
A1626A3E2617006A003F1973 /* SDL_triangle.c in Sources */ = {isa = PBXBuildFile; fileRef = A1626A3D2617006A003F1973 /* SDL_triangle.c */; };
A1626A522617008D003F1973 /* SDL_triangle.h in Headers */ = {isa = PBXBuildFile; fileRef = A1626A512617008C003F1973 /* SDL_triangle.h */; };
A1BB8B6327F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
Expand Down Expand Up @@ -620,6 +621,7 @@
89E580202D03606400DAF6D3 /* SDL_hidapihaptic_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_hidapihaptic_c.h; sourceTree = "<group>"; };
89E580212D03606400DAF6D3 /* SDL_hidapihaptic_lg4ff.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_hidapihaptic_lg4ff.c; sourceTree = "<group>"; };
9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_shield.c; sourceTree = "<group>"; };
02D6A1C128A84B8F00A7F001 /* SDL_hidapi_sinput.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_sinput.c; sourceTree = "<group>"; };
A1626A3D2617006A003F1973 /* SDL_triangle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_triangle.c; sourceTree = "<group>"; };
A1626A512617008C003F1973 /* SDL_triangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_triangle.h; sourceTree = "<group>"; };
A1BB8B6127F6CF320057CFA8 /* SDL_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_list.c; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1943,6 +1945,7 @@
A75FDBC323EA380300529352 /* SDL_hidapi_rumble.h */,
A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */,
9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */,
02D6A1C128A84B8F00A7F001 /* SDL_hidapi_sinput.c */,
F3984CCF25BCC92800374F43 /* SDL_hidapi_stadia.c */,
A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */,
F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */,
Expand Down Expand Up @@ -2877,6 +2880,7 @@
A7D8B62F23E2514300DCD162 /* SDL_sysfilesystem.m in Sources */,
A7D8B41C23E2514300DCD162 /* SDL_systls.c in Sources */,
9846B07C287A9020000C35C8 /* SDL_hidapi_shield.c in Sources */,
02D6A1C228A84B8F00A7F002 /* SDL_hidapi_sinput.c in Sources */,
F31013C72C24E98200FBE946 /* SDL_keymap.c in Sources */,
F3A9AE992C8A13C100AAC390 /* SDL_render_gpu.c in Sources */,
A7D8BBD923E2574800DCD162 /* SDL_uikitmessagebox.m in Sources */,
Expand Down
12 changes: 12 additions & 0 deletions include/SDL3/SDL_hints.h
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,18 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_8BITDO "SDL_JOYSTICK_HIDAPI_8BITDO"

/**
* A variable controlling whether the HIDAPI driver for SInput controllers
* should be used. More info - https://github.com/HandHeldLegend/SInput-HID
*
* This variable can be set to the following values:
*
* "0" - HIDAPI driver is not used. "1" - HIDAPI driver is used.
*
* The default is the value of SDL_HINT_JOYSTICK_HIDAPI
*/
#define SDL_HINT_JOYSTICK_HIDAPI_SINPUT "SDL_JOYSTICK_HIDAPI_SINPUT"

/**
* A variable controlling whether the HIDAPI driver for Flydigi controllers
* should be used.
Expand Down
49 changes: 49 additions & 0 deletions src/joystick/SDL_gamepad.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,54 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
product == USB_PRODUCT_8BITDO_SF30_PRO_BT)) {
// This controller has no guide button
SDL_strlcat(mapping_string, "a:b1,b:b0,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
} else if (SDL_IsJoystickSInputController(vendor, product)) {
Uint8 face_style = (guid.data[15] & 0xF0) >> 4;
Uint8 u_id = guid.data[15] & 0x0F;

switch (product) {
case USB_PRODUCT_HANDHELDLEGEND_PROGCC:
// ProGCC Mapping
SDL_strlcat(mapping_string, "a:b1,b:b0,back:b15,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b8,lefttrigger:b12,leftx:a0,lefty:a1,misc1:b17,rightshoulder:b11,rightstick:b9,righttrigger:b13,rightx:a2,righty:a3,start:b14,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
break;

case USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE:
// GC Ultimate Map
SDL_strlcat(mapping_string, "a:b0,b:b2,back:b15,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b8,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b17,misc3:b18,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a5,rightx:a2,righty:a3,start:b14,x:b1,y:b3,hint:!SDL_GAMECONTROLLER_USE_GAMECUBE_LABELS:=1,", sizeof(mapping_string));
break;

case USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC:
if (u_id != 1) {
return NULL;
}

// SuperGamepad+ Map
if (u_id == 1) {
SDL_strlcat(mapping_string, "a:b1,b:b0,back:b11,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,leftshoulder:b8,rightshoulder:b9,start:b10,x:b3,y:b2,", sizeof(mapping_string));
}

// Apply face style
switch (face_style) {
default:
case 1:
SDL_strlcat(mapping_string, "face:abxy,", sizeof(mapping_string));
break;
case 2:
SDL_strlcat(mapping_string, "face:axby,", sizeof(mapping_string));
break;
case 3:
SDL_strlcat(mapping_string, "face:bayx,", sizeof(mapping_string));
break;
case 4:
SDL_strlcat(mapping_string, "face:sony,", sizeof(mapping_string));
break;
}
break;

default:
case USB_PRODUCT_BONJIRICHANNEL_FIREBIRD:
// Unmapped devices
return NULL;
}
} else {
// All other gamepads have the standard set of 19 buttons and 6 axes
if (SDL_IsJoystickGameCube(vendor, product)) {
Expand Down Expand Up @@ -1235,6 +1283,7 @@ static bool SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char *szG
if (SDL_strstr(gamepad->mapping->mapping, ",hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1") != NULL) {
baxy_mapping = true;
}

// FIXME: We fix these up when loading the mapping, does this ever get hit?
//SDL_assert(!axby_mapping && !baxy_mapping);

Expand Down
11 changes: 11 additions & 0 deletions src/joystick/SDL_joystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -3201,6 +3201,17 @@ bool SDL_IsJoystickHoriSteamController(Uint16 vendor_id, Uint16 product_id)
return vendor_id == USB_VENDOR_HORI && (product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER || product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER_BT);
}

bool SDL_IsJoystickSInputController(Uint16 vendor_id, Uint16 product_id)
{
bool vendor_match = (vendor_id == USB_VENDOR_RASPBERRYPI);
bool product_match =
(product_id == USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC) |
(product_id == USB_PRODUCT_HANDHELDLEGEND_PROGCC) |
(product_id == USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE) |
(product_id == USB_PRODUCT_BONJIRICHANNEL_FIREBIRD);
return (vendor_match && product_match);
}

bool SDL_IsJoystickFlydigiController(Uint16 vendor_id, Uint16 product_id)
{
return vendor_id == USB_VENDOR_FLYDIGI && product_id == USB_PRODUCT_FLYDIGI_GAMEPAD;
Expand Down
3 changes: 3 additions & 0 deletions src/joystick/SDL_joystick_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ extern bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id);
// Function to return whether a joystick is a HORI Steam controller
extern bool SDL_IsJoystickHoriSteamController(Uint16 vendor_id, Uint16 product_id);

// Function to return whether a joystick is an SInput (Open Format) controller
extern bool SDL_IsJoystickSInputController(Uint16 vendor_id, Uint16 product_id);

// Function to return whether a joystick is a Flydigi controller
extern bool SDL_IsJoystickFlydigiController(Uint16 vendor_id, Uint16 product_id);

Expand Down
Loading
Loading