Skip to content

Commit c1a55e5

Browse files
committed
sinput: allow dynamic loading, defining of subtypes/states for controllers
Add a controller type for sinput to allow loading the driver dynamically via an environment variable override. Then, cleanup the mapping code in SDL_gamepad.c and SDL_hidapi_sinput.c by placing the vid:pid and subtype logic in HIDAPI_DriverSInput_GetControllerType. This function can arbitrarily decide the layout and face style of a controller based on its vid, pid, version, and subtype. This allows for up to 65336 different combinations of controller types/face styles per vid:pid. Then, add 8 controller layouts and face styles for the vid:pid pair 0x16d0:0x145b that will be used to virtually test the sinput driver. To defer making a decision, for other vid:pid pairs, FullMapping will always be used, except for the generic sinput pid, which will load different face styles based on the upper three bits of subtype.
1 parent ae5ce25 commit c1a55e5

File tree

7 files changed

+282
-96
lines changed

7 files changed

+282
-96
lines changed

src/joystick/SDL_gamepad.c

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "controller_type.h"
3131
#include "usb_ids.h"
3232
#include "hidapi/SDL_hidapi_nintendo.h"
33+
#include "hidapi/SDL_hidapi_sinput.h"
3334
#include "../events/SDL_events_c.h"
3435

3536

@@ -697,10 +698,11 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
697698
char mapping_string[1024];
698699
Uint16 vendor;
699700
Uint16 product;
701+
Uint16 version;
700702

701703
SDL_strlcpy(mapping_string, "none,*,", sizeof(mapping_string));
702704

703-
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
705+
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, &version, NULL);
704706

705707
if (SDL_IsJoystickWheel(vendor, product)) {
706708
// We don't want to pick up Logitech FFB wheels here
@@ -799,52 +801,63 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
799801
// This controller has no guide button
800802
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));
801803
} else if (SDL_IsJoystickSInputController(vendor, product)) {
802-
Uint8 face_style = (guid.data[15] & 0xE0) >> 5;
803-
Uint8 sinput_id = guid.data[15] & 0x1F;
804-
805-
switch (product) {
806-
case USB_PRODUCT_HANDHELDLEGEND_PROGCC:
807-
// ProGCC Mapping
804+
ESinputControllerType controller_type;
805+
ESinputFaceStyle face_style;
806+
HIDAPI_DriverSInput_GetControllerType(vendor, product, version, guid.data[15], &controller_type, &face_style);
807+
808+
// Apply mapping profile for type
809+
switch (controller_type) {
810+
case k_eSInputControllerType_XInputOnly:
811+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,start:b8,back:b9,guide:b10,", sizeof(mapping_string));
812+
break;
813+
case k_eSInputControllerType_XInputShareNone:
814+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,start:b8,back:b9,guide:b10,misc1:b11,", sizeof(mapping_string));
815+
break;
816+
case k_eSInputControllerType_XInputShareDual:
817+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,paddle1:b8,paddle2:b9,start:b10,back:b11,guide:b12,misc1:b13,", sizeof(mapping_string));
818+
break;
819+
case k_eSInputControllerType_XInputShareQuad:
820+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,paddle1:b8,paddle2:b9,start:b10,back:b11,guide:b12,misc1:b13,paddle3:b14,paddle4:b15,", sizeof(mapping_string));
821+
break;
822+
case k_eSInputControllerType_XInputShareNoneClick:
823+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,start:b8,back:b9,guide:b10,misc1:b11,touchpad:b12,", sizeof(mapping_string));
824+
break;
825+
case k_eSInputControllerType_XInputShareDualClick:
826+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,paddle1:b8,paddle2:b9,start:b10,back:b11,guide:b12,misc1:b13,touchpad:b14,", sizeof(mapping_string));
827+
break;
828+
case k_eSInputControllerType_XInputShareQuadClick:
829+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,paddle1:b8,paddle2:b9,start:b10,back:b11,guide:b12,misc1:b13,paddle3:b14,paddle4:b15,touchpad:b16,", sizeof(mapping_string));
830+
break;
831+
case k_eSInputControllerType_HHL_PROGCC:
808832
SDL_strlcat(mapping_string, "a:b1,b:b0,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b4,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
809833
break;
810-
811-
case USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE:
812-
// GC Ultimate Map
834+
case k_eSInputControllerType_HHL_GCCULT:
813835
SDL_strlcat(mapping_string, "a:b0,b:b2,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b4,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b13,misc2:b14,rightshoulder:b7,rightstick:b5,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b1,y:b3,misc3:b8,misc4:b9,hint:!SDL_GAMECONTROLLER_USE_GAMECUBE_LABELS:=1,", sizeof(mapping_string));
814836
break;
815-
816-
case USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC:
817-
// Apply mapping profile for type
818-
switch (sinput_id) {
819-
default:
820-
case 0:
821-
// Default Fully Exposed Mapping
822-
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,paddle1:b10,paddle2:b11,start:b12,back:b13,guide:b14,misc1:b15,paddle3:b16,paddle4:b17,touchpad:b18,misc2:b19,misc3:b20,misc4:b21,misc5:b22,misc6:b23", sizeof(mapping_string));
823-
break;
824-
}
825-
826-
// Apply face style
827-
switch (face_style) {
828-
default:
829-
case 1:
830-
SDL_strlcat(mapping_string, "face:abxy,", sizeof(mapping_string));
831-
break;
832-
case 2:
833-
SDL_strlcat(mapping_string, "face:axby,", sizeof(mapping_string));
834-
break;
835-
case 3:
836-
SDL_strlcat(mapping_string, "face:bayx,", sizeof(mapping_string));
837-
break;
838-
case 4:
839-
SDL_strlcat(mapping_string, "face:sony,", sizeof(mapping_string));
840-
break;
841-
}
837+
default:
838+
case k_eSInputControllerType_FullMapping:
839+
// Default Fully Exposed Mapping
840+
SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,paddle1:b10,paddle2:b11,start:b12,back:b13,guide:b14,misc1:b15,paddle3:b16,paddle4:b17,touchpad:b18,misc2:b19,misc3:b20,misc4:b21,misc5:b22,misc6:b23", sizeof(mapping_string));
842841
break;
842+
}
843843

844+
// Apply face style
845+
switch (face_style) {
846+
case k_eSInputFaceStyle_abxy:
847+
SDL_strlcat(mapping_string, "face:abxy,", sizeof(mapping_string));
848+
break;
849+
case k_eSInputFaceStyle_axby:
850+
SDL_strlcat(mapping_string, "face:axby,", sizeof(mapping_string));
851+
break;
852+
case k_eSInputFaceStyle_bayx:
853+
SDL_strlcat(mapping_string, "face:bayx,", sizeof(mapping_string));
854+
break;
855+
case k_eSInputFaceStyle_sony:
856+
SDL_strlcat(mapping_string, "face:sony,", sizeof(mapping_string));
857+
break;
858+
case k_eSInputFaceStyle_ukwn:
844859
default:
845-
case USB_PRODUCT_BONJIRICHANNEL_FIREBIRD:
846-
// Unmapped devices
847-
return NULL;
860+
break;
848861
}
849862
} else {
850863
// All other gamepads have the standard set of 19 buttons and 6 axes

src/joystick/SDL_joystick.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3216,7 +3216,9 @@ bool SDL_IsJoystickSInputController(Uint16 vendor_id, Uint16 product_id)
32163216
return true;
32173217
}
32183218
}
3219-
return false;
3219+
3220+
EControllerType eType = GuessControllerType(vendor_id, product_id);
3221+
return eType == k_eControllerType_Sinput;
32203222
}
32213223

32223224
bool SDL_IsJoystickFlydigiController(Uint16 vendor_id, Uint16 product_id)

src/joystick/controller_list.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,4 +598,7 @@ static const ControllerDescription_t arrControllers[] = {
598598
{ MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB)
599599
{ MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB)
600600
{ MAKE_CONTROLLER_ID( 0x28de, 0x1205 ), k_eControllerType_SteamControllerNeptune, NULL }, // Valve Steam Deck Builtin Controller
601+
602+
// Sinput controllers
603+
{ MAKE_CONTROLLER_ID( 0x16d0, 0x145b ), k_eControllerType_Sinput, NULL },
601604
};

src/joystick/controller_type.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ EControllerType GuessControllerType( int nVID, int nPID )
106106
{
107107
return k_eControllerType_SteamController;
108108
}
109+
if ( SDL_strncasecmp( pszOverride, "sinput", 5 ) == 0 )
110+
{
111+
return k_eControllerType_Sinput;
112+
}
109113
return k_eControllerType_UnknownNonSteamController;
110114
}
111115

src/joystick/controller_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ typedef enum
5757
k_eControllerType_XInputSwitchController = 44, // Client-side only, used to mark Nintendo Switch style controllers as using XInput instead of the Nintendo Switch protocol
5858
k_eControllerType_PS5Controller = 45,
5959
k_eControllerType_XInputPS4Controller = 46, // Client-side only, used to mark DualShock 4 style controllers using XInput instead of the DualShock 4 controller protocol
60+
k_eControllerType_Sinput = 47,
6061
k_eControllerType_LastController, // Don't add game controllers below this enumeration - this enumeration can change value
6162

6263
// Keyboards and Mice

0 commit comments

Comments
 (0)