mirror of https://github.com/encounter/SDL.git
Greatly improved Nintendo Joy-Con support using the HIDAPI driver
* Added support for mini-gamepad mode for Joy-Con controllers, matching the mapping for hid-nintendo on Linux and iOS 16 * Added the ability to merge left and right Joy-Con controllers into a single Pro-style controller * Added the hint SDL_HINT_JOYSTICK_HIDAPI_SWITCH_COMBINE_JOY_CONS to control this merging functionality * Removed the hint SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS
This commit is contained in:
parent
def60ce6fe
commit
2fa2f9ff77
|
@ -89,7 +89,7 @@ SRCS+= SDL_systimer.c
|
||||||
SRCS+= SDL_sysloadso.c
|
SRCS+= SDL_sysloadso.c
|
||||||
SRCS+= SDL_sysfilesystem.c
|
SRCS+= SDL_sysfilesystem.c
|
||||||
SRCS+= SDL_os2joystick.c SDL_syshaptic.c SDL_sysjoystick.c SDL_virtualjoystick.c
|
SRCS+= SDL_os2joystick.c SDL_syshaptic.c SDL_sysjoystick.c SDL_virtualjoystick.c
|
||||||
SRCS+= SDL_hidapijoystick.c SDL_hidapi_rumble.c SDL_hidapi_gamecube.c SDL_hidapi_luna.c SDL_hidapi_ps4.c SDL_hidapi_ps5.c SDL_hidapi_shield.c SDL_hidapi_stadia.c SDL_hidapi_switch.c SDL_hidapi_xbox360.c SDL_hidapi_xbox360w.c SDL_hidapi_xboxone.c SDL_hidapi_steam.c
|
SRCS+= SDL_hidapijoystick.c SDL_hidapi_rumble.c SDL_hidapi_combined.c SDL_hidapi_gamecube.c SDL_hidapi_luna.c SDL_hidapi_ps4.c SDL_hidapi_ps5.c SDL_hidapi_shield.c SDL_hidapi_stadia.c SDL_hidapi_switch.c SDL_hidapi_xbox360.c SDL_hidapi_xbox360w.c SDL_hidapi_xboxone.c SDL_hidapi_steam.c
|
||||||
SRCS+= SDL_dummyaudio.c SDL_diskaudio.c
|
SRCS+= SDL_dummyaudio.c SDL_diskaudio.c
|
||||||
SRCS+= SDL_nullvideo.c SDL_nullframebuffer.c SDL_nullevents.c
|
SRCS+= SDL_nullvideo.c SDL_nullframebuffer.c SDL_nullevents.c
|
||||||
SRCS+= SDL_dummysensor.c
|
SRCS+= SDL_dummysensor.c
|
||||||
|
|
|
@ -65,7 +65,7 @@ SRCS+= SDL_systimer.c
|
||||||
SRCS+= SDL_sysloadso.c
|
SRCS+= SDL_sysloadso.c
|
||||||
SRCS+= SDL_sysfilesystem.c
|
SRCS+= SDL_sysfilesystem.c
|
||||||
SRCS+= SDL_syshaptic.c SDL_sysjoystick.c SDL_virtualjoystick.c
|
SRCS+= SDL_syshaptic.c SDL_sysjoystick.c SDL_virtualjoystick.c
|
||||||
SRCS+= SDL_hidapijoystick.c SDL_hidapi_rumble.c SDL_hidapi_gamecube.c SDL_hidapi_luna.c SDL_hidapi_ps4.c SDL_hidapi_ps5.c SDL_hidapi_shield.c SDL_hidapi_stadia.c SDL_hidapi_switch.c SDL_hidapi_xbox360.c SDL_hidapi_xbox360w.c SDL_hidapi_xboxone.c SDL_hidapi_steam.c
|
SRCS+= SDL_hidapijoystick.c SDL_hidapi_rumble.c SDL_hidapi_combined.c SDL_hidapi_gamecube.c SDL_hidapi_luna.c SDL_hidapi_ps4.c SDL_hidapi_ps5.c SDL_hidapi_shield.c SDL_hidapi_stadia.c SDL_hidapi_switch.c SDL_hidapi_xbox360.c SDL_hidapi_xbox360w.c SDL_hidapi_xboxone.c SDL_hidapi_steam.c
|
||||||
SRCS+= SDL_dummyaudio.c SDL_diskaudio.c
|
SRCS+= SDL_dummyaudio.c SDL_diskaudio.c
|
||||||
SRCS+= SDL_nullvideo.c SDL_nullframebuffer.c SDL_nullevents.c
|
SRCS+= SDL_nullvideo.c SDL_nullframebuffer.c SDL_nullevents.c
|
||||||
SRCS+= SDL_dummysensor.c
|
SRCS+= SDL_dummysensor.c
|
||||||
|
|
|
@ -592,6 +592,7 @@
|
||||||
<ClCompile Include="..\..\src\joystick\controller_type.c" />
|
<ClCompile Include="..\..\src\joystick\controller_type.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
|
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
||||||
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
||||||
|
|
|
@ -1054,7 +1054,7 @@
|
||||||
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c">
|
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c">
|
||||||
<Filter>joystick\dummy</Filter>
|
<Filter>joystick\dummy</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c">
|
||||||
<Filter>joystick\hidapi</Filter>
|
<Filter>joystick\hidapi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c">
|
||||||
|
@ -1087,6 +1087,9 @@
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360w.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360w.c">
|
||||||
<Filter>joystick\hidapi</Filter>
|
<Filter>joystick\hidapi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c">
|
||||||
|
<Filter>joystick\hidapi</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c">
|
||||||
<Filter>joystick\hidapi</Filter>
|
<Filter>joystick\hidapi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -483,6 +483,7 @@
|
||||||
<ClCompile Include="..\..\src\joystick\controller_type.c" />
|
<ClCompile Include="..\..\src\joystick\controller_type.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
|
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c" />
|
||||||
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_luna.c" />
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_ps4.c" />
|
||||||
|
|
|
@ -1047,7 +1047,7 @@
|
||||||
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c">
|
<ClCompile Include="..\..\src\joystick\dummy\SDL_sysjoystick.c">
|
||||||
<Filter>joystick\dummy</Filter>
|
<Filter>joystick\dummy</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_combined.c">
|
||||||
<Filter>joystick\hidapi</Filter>
|
<Filter>joystick\hidapi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_gamecube.c">
|
||||||
|
@ -1080,6 +1080,9 @@
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360w.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360w.c">
|
||||||
<Filter>joystick\hidapi</Filter>
|
<Filter>joystick\hidapi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c">
|
||||||
|
<Filter>joystick\hidapi</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c">
|
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c">
|
||||||
<Filter>joystick\hidapi</Filter>
|
<Filter>joystick\hidapi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -20,6 +20,9 @@ General:
|
||||||
the SDL 2.24.0 stable release.
|
the SDL 2.24.0 stable release.
|
||||||
* Added SDL_bsearch() and SDL_utf8strnlen() to the stdlib routines
|
* Added SDL_bsearch() and SDL_utf8strnlen() to the stdlib routines
|
||||||
* Added SDL_size_mul_overflow() and SDL_size_add_overflow() for better size overflow protection
|
* Added SDL_size_mul_overflow() and SDL_size_add_overflow() for better size overflow protection
|
||||||
|
* Added support for mini-gamepad mode for Nintendo Joy-Con controllers using the HIDAPI driver
|
||||||
|
* Added the hint SDL_HINT_JOYSTICK_HIDAPI_SWITCH_COMBINE_JOY_CONS to control whether Joy-Con controllers are automatically merged into a unified gamepad when using the HIDAPI driver. This hint defaults on.
|
||||||
|
* Removed the hint SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS with the new Joy-Con functionality
|
||||||
* Added functions to get the platform dependent name for a joystick or game controller:
|
* Added functions to get the platform dependent name for a joystick or game controller:
|
||||||
* SDL_JoystickPathForIndex()
|
* SDL_JoystickPathForIndex()
|
||||||
* SDL_JoystickPath()
|
* SDL_JoystickPath()
|
||||||
|
|
|
@ -652,17 +652,6 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE "SDL_JOYSTICK_GAMECUBE_RUMBLE_BRAKE"
|
#define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE "SDL_JOYSTICK_GAMECUBE_RUMBLE_BRAKE"
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief A variable controlling whether Switch Joy-Cons should be treated the same as Switch Pro Controllers when using the HIDAPI driver.
|
|
||||||
*
|
|
||||||
* This variable can be set to the following values:
|
|
||||||
* "0" - basic Joy-Con support with no analog input (the default)
|
|
||||||
* "1" - Joy-Cons treated as half full Pro Controllers with analog inputs and sensors
|
|
||||||
*
|
|
||||||
* This does not combine Joy-Cons into a single controller. That's up to the user.
|
|
||||||
*/
|
|
||||||
#define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used.
|
* \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used.
|
||||||
*
|
*
|
||||||
|
@ -789,6 +778,17 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH"
|
#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A variable controlling whether Nintendo Switch Joy-Con controllers will be combined into a single Pro-like controller when using the HIDAPI driver
|
||||||
|
*
|
||||||
|
* This variable can be set to the following values:
|
||||||
|
* "0" - Left and right Joy-Con controllers will not be combined and each will be a mini-gamepad
|
||||||
|
* "1" - Left and right Joy-Con controllers will be combined into a single controller (the default)
|
||||||
|
*
|
||||||
|
* The default is "1"
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_COMBINE_JOY_CONS "SDL_JOYSTICK_HIDAPI_SWITCH_COMBINE_JOY_CONS"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch controller is opened
|
* \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch controller is opened
|
||||||
*
|
*
|
||||||
|
|
|
@ -593,6 +593,10 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI
|
||||||
SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,rightshoulder:b10,righttrigger:a5,start:b6,misc1:b15,", sizeof(mapping_string));
|
SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,rightshoulder:b10,righttrigger:a5,start:b6,misc1:b15,", sizeof(mapping_string));
|
||||||
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
|
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
|
||||||
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,", sizeof(mapping_string));
|
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,", sizeof(mapping_string));
|
||||||
|
} else if (SDL_IsJoystickNintendoSwitchJoyConLeft(vendor, product) ||
|
||||||
|
SDL_IsJoystickNintendoSwitchJoyConRight(vendor, product)) {
|
||||||
|
/* Mini gamepad mode */
|
||||||
|
SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,", sizeof(mapping_string));
|
||||||
} else {
|
} else {
|
||||||
/* All other controllers have the standard set of 19 buttons and 6 axes */
|
/* All other controllers have the standard set of 19 buttons and 6 axes */
|
||||||
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string));
|
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string));
|
||||||
|
@ -619,12 +623,6 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI
|
||||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
|
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
|
||||||
/* Nintendo Switch Pro controllers have a screenshot button */
|
/* Nintendo Switch Pro controllers have a screenshot button */
|
||||||
SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string));
|
SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string));
|
||||||
/* Joy-Cons have extra buttons in the same place as paddles */
|
|
||||||
if (SDL_IsJoystickNintendoSwitchJoyConLeft(vendor, product)) {
|
|
||||||
SDL_strlcat(mapping_string, "paddle2:b17,paddle4:b19,", sizeof(mapping_string));
|
|
||||||
} else if (SDL_IsJoystickNintendoSwitchJoyConRight(vendor, product)) {
|
|
||||||
SDL_strlcat(mapping_string, "paddle1:b16,paddle3:b18,", sizeof(mapping_string));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SDL_CONTROLLER_TYPE_AMAZON_LUNA:
|
case SDL_CONTROLLER_TYPE_AMAZON_LUNA:
|
||||||
/* Amazon Luna Controller has a mic button under the guide button */
|
/* Amazon Luna Controller has a mic button under the guide button */
|
||||||
|
|
|
@ -1960,8 +1960,10 @@ SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const
|
||||||
} else if (vendor == USB_VENDOR_NVIDIA && product == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER) {
|
} else if (vendor == USB_VENDOR_NVIDIA && product == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER) {
|
||||||
type = SDL_CONTROLLER_TYPE_NVIDIA_SHIELD;
|
type = SDL_CONTROLLER_TYPE_NVIDIA_SHIELD;
|
||||||
|
|
||||||
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP) {
|
} else if (vendor == USB_VENDOR_NINTENDO &&
|
||||||
type = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, SDL_FALSE) ? SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO : SDL_CONTROLLER_TYPE_UNKNOWN;
|
(product == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP ||
|
||||||
|
product == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR)) {
|
||||||
|
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch (GuessControllerType(vendor, product)) {
|
switch (GuessControllerType(vendor, product)) {
|
||||||
|
@ -2000,12 +2002,7 @@ SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const
|
||||||
break;
|
break;
|
||||||
case k_eControllerType_SwitchJoyConLeft:
|
case k_eControllerType_SwitchJoyConLeft:
|
||||||
case k_eControllerType_SwitchJoyConRight:
|
case k_eControllerType_SwitchJoyConRight:
|
||||||
/* We always support the Nintendo Online NES Controllers */
|
|
||||||
if (name && SDL_strncmp(name, "NES Controller", 14) == 0) {
|
|
||||||
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
|
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
|
||||||
} else {
|
|
||||||
type = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, SDL_FALSE) ? SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO : SDL_CONTROLLER_TYPE_UNKNOWN;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -359,6 +359,12 @@ HIDAPI_DriverSwitch_IsSupportedDevice(const char *name, SDL_GameControllerType t
|
||||||
if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) {
|
if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We always support the Nintendo Online NES Controllers */
|
||||||
|
if (SDL_strncmp(name, "NES Controller", 14) == 0) {
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE;
|
return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,10 +1054,14 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input_mode == k_eSwitchInputReportIDs_FullControllerState) {
|
if (input_mode == k_eSwitchInputReportIDs_FullControllerState) {
|
||||||
|
/* Use the right sensor in the combined Joy-Con pair */
|
||||||
|
if (!device->parent ||
|
||||||
|
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
||||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 200.0f);
|
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 200.0f);
|
||||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 200.0f);
|
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 200.0f);
|
||||||
ctx->m_bHasSensors = SDL_TRUE;
|
ctx->m_bHasSensors = SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!LoadStickCalibration(ctx, input_mode)) {
|
if (!LoadStickCalibration(ctx, input_mode)) {
|
||||||
SDL_SetError("Couldn't load stick calibration");
|
SDL_SetError("Couldn't load stick calibration");
|
||||||
|
@ -1101,6 +1111,9 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
|
||||||
ctx->m_rgucMACAddress[3],
|
ctx->m_rgucMACAddress[3],
|
||||||
ctx->m_rgucMACAddress[4],
|
ctx->m_rgucMACAddress[4],
|
||||||
ctx->m_rgucMACAddress[5]);
|
ctx->m_rgucMACAddress[5]);
|
||||||
|
if (joystick->serial) {
|
||||||
|
SDL_free(joystick->serial);
|
||||||
|
}
|
||||||
joystick->serial = SDL_strdup(serial);
|
joystick->serial = SDL_strdup(serial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1118,12 +1131,7 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the joystick capabilities */
|
/* Initialize the joystick capabilities */
|
||||||
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
|
|
||||||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
|
||||||
joystick->nbuttons = 20;
|
|
||||||
} else {
|
|
||||||
joystick->nbuttons = 16;
|
joystick->nbuttons = 16;
|
||||||
}
|
|
||||||
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
||||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||||
|
|
||||||
|
@ -1216,6 +1224,16 @@ HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
|
||||||
return SDL_Unsupported();
|
return SDL_Unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (device->parent) {
|
||||||
|
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
|
||||||
|
/* Just handle low frequency rumble */
|
||||||
|
high_frequency_rumble = 0;
|
||||||
|
} else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
||||||
|
/* Just handle high frequency rumble */
|
||||||
|
low_frequency_rumble = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->m_bRumblePending) {
|
if (ctx->m_bRumblePending) {
|
||||||
if (HIDAPI_DriverSwitch_SendPendingRumble(ctx) < 0) {
|
if (HIDAPI_DriverSwitch_SendPendingRumble(ctx) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1508,7 +1526,68 @@ static void SendSensorUpdate(SDL_Joystick *joystick, SDL_DriverSwitch_Context *c
|
||||||
SDL_PrivateJoystickSensor(joystick, type, data, 3);
|
SDL_PrivateJoystickSensor(joystick, type, data, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
|
static void HandleCombinedControllerStateL(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
|
||||||
|
{
|
||||||
|
Sint16 axis;
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[1];
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[2];
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
axis = (data & 0x80) ? 32767 : -32768;
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
|
||||||
|
axis = ApplyStickCalibration(ctx, 0, 0, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
||||||
|
|
||||||
|
axis = ((packet->controllerState.rgucJoystickLeft[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickLeft[2] << 4);
|
||||||
|
axis = ApplyStickCalibration(ctx, 0, 1, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HandleMiniControllerStateL(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
|
||||||
|
{
|
||||||
|
Sint16 axis;
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[1];
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[2] != ctx->m_lastFullState.controllerState.rgucButtons[2]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[2];
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
axis = packet->controllerState.rgucJoystickLeft[0] | ((packet->controllerState.rgucJoystickLeft[1] & 0xF) << 8);
|
||||||
|
axis = ApplyStickCalibration(ctx, 0, 0, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~axis);
|
||||||
|
|
||||||
|
axis = ((packet->controllerState.rgucJoystickLeft[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickLeft[2] << 4);
|
||||||
|
axis = ApplyStickCalibration(ctx, 0, 1, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, ~axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HandleCombinedControllerStateR(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
|
||||||
{
|
{
|
||||||
Sint16 axis;
|
Sint16 axis;
|
||||||
|
|
||||||
|
@ -1518,10 +1597,80 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
|
||||||
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE1, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
axis = (data & 0x80) ? 32767 : -32768;
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE3, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[1];
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
axis = packet->controllerState.rgucJoystickRight[0] | ((packet->controllerState.rgucJoystickRight[1] & 0xF) << 8);
|
||||||
|
axis = ApplyStickCalibration(ctx, 1, 0, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
|
||||||
|
|
||||||
|
axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
|
||||||
|
axis = ApplyStickCalibration(ctx, 1, 1, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HandleMiniControllerStateR(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
|
||||||
|
{
|
||||||
|
Sint16 axis;
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[0];
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[1] != ctx->m_lastFullState.controllerState.rgucButtons[1]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[1];
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
axis = packet->controllerState.rgucJoystickRight[0] | ((packet->controllerState.rgucJoystickRight[1] & 0xF) << 8);
|
||||||
|
axis = ApplyStickCalibration(ctx, 1, 0, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
|
||||||
|
|
||||||
|
axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
|
||||||
|
axis = ApplyStickCalibration(ctx, 1, 1, axis);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
|
||||||
|
{
|
||||||
|
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
|
||||||
|
if (ctx->device->parent) {
|
||||||
|
HandleCombinedControllerStateL(joystick, ctx, packet);
|
||||||
|
} else {
|
||||||
|
HandleMiniControllerStateL(joystick, ctx, packet);
|
||||||
|
}
|
||||||
|
} else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
||||||
|
if (ctx->device->parent) {
|
||||||
|
HandleCombinedControllerStateR(joystick, ctx, packet);
|
||||||
|
} else {
|
||||||
|
HandleMiniControllerStateR(joystick, ctx, packet);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Sint16 axis;
|
||||||
|
|
||||||
|
if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
|
||||||
|
Uint8 data = packet->controllerState.rgucButtons[0];
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
axis = (data & 0x80) ? 32767 : -32768;
|
axis = (data & 0x80) ? 32767 : -32768;
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
||||||
|
@ -1544,10 +1693,6 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE4, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_PADDLE2, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
}
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
axis = (data & 0x80) ? 32767 : -32768;
|
axis = (data & 0x80) ? 32767 : -32768;
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
|
||||||
|
@ -1568,6 +1713,7 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
|
||||||
axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
|
axis = ((packet->controllerState.rgucJoystickRight[1] & 0xF0) >> 4) | (packet->controllerState.rgucJoystickRight[2] << 4);
|
||||||
axis = ApplyStickCalibration(ctx, 1, 1, axis);
|
axis = ApplyStickCalibration(ctx, 1, 1, axis);
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~axis);
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~axis);
|
||||||
|
}
|
||||||
|
|
||||||
/* High nibble of battery/connection byte is battery level, low nibble is connection status
|
/* High nibble of battery/connection byte is battery level, low nibble is connection status
|
||||||
* LSB of connection nibble is USB/Switch connection status
|
* LSB of connection nibble is USB/Switch connection status
|
||||||
|
|
|
@ -80,6 +80,7 @@ static SDL_SpinLock SDL_HIDAPI_spinlock;
|
||||||
static Uint32 SDL_HIDAPI_change_count = 0;
|
static Uint32 SDL_HIDAPI_change_count = 0;
|
||||||
static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
|
static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
|
||||||
static int SDL_HIDAPI_numjoysticks = 0;
|
static int SDL_HIDAPI_numjoysticks = 0;
|
||||||
|
static SDL_bool SDL_HIDAPI_combine_joycons = SDL_TRUE;
|
||||||
static SDL_bool initialized = SDL_FALSE;
|
static SDL_bool initialized = SDL_FALSE;
|
||||||
static SDL_bool shutting_down = SDL_FALSE;
|
static SDL_bool shutting_down = SDL_FALSE;
|
||||||
|
|
||||||
|
@ -224,6 +225,10 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
|
||||||
int i;
|
int i;
|
||||||
SDL_GameControllerType type;
|
SDL_GameControllerType type;
|
||||||
|
|
||||||
|
if (device->num_children > 0) {
|
||||||
|
return &SDL_HIDAPI_DriverCombined;
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
|
if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -250,8 +255,12 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
|
||||||
static SDL_HIDAPI_Device *
|
static SDL_HIDAPI_Device *
|
||||||
HIDAPI_GetDeviceByIndex(int device_index, SDL_JoystickID *pJoystickID)
|
HIDAPI_GetDeviceByIndex(int device_index, SDL_JoystickID *pJoystickID)
|
||||||
{
|
{
|
||||||
SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
|
SDL_HIDAPI_Device *device;
|
||||||
while (device) {
|
|
||||||
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
|
if (device->parent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (device->driver) {
|
if (device->driver) {
|
||||||
if (device_index < device->num_joysticks) {
|
if (device_index < device->num_joysticks) {
|
||||||
if (pJoystickID) {
|
if (pJoystickID) {
|
||||||
|
@ -261,7 +270,6 @@ HIDAPI_GetDeviceByIndex(int device_index, SDL_JoystickID *pJoystickID)
|
||||||
}
|
}
|
||||||
device_index -= device->num_joysticks;
|
device_index -= device->num_joysticks;
|
||||||
}
|
}
|
||||||
device = device->next;
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -269,39 +277,17 @@ HIDAPI_GetDeviceByIndex(int device_index, SDL_JoystickID *pJoystickID)
|
||||||
static SDL_HIDAPI_Device *
|
static SDL_HIDAPI_Device *
|
||||||
HIDAPI_GetJoystickByInfo(const char *path, Uint16 vendor_id, Uint16 product_id)
|
HIDAPI_GetJoystickByInfo(const char *path, Uint16 vendor_id, Uint16 product_id)
|
||||||
{
|
{
|
||||||
SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
|
SDL_HIDAPI_Device *device;
|
||||||
while (device) {
|
|
||||||
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
if (device->vendor_id == vendor_id && device->product_id == product_id &&
|
if (device->vendor_id == vendor_id && device->product_id == product_id &&
|
||||||
SDL_strcmp(device->path, path) == 0) {
|
SDL_strcmp(device->path, path) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
device = device->next;
|
|
||||||
}
|
}
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
|
|
||||||
{
|
|
||||||
if (device->driver) {
|
|
||||||
return; /* Already setup */
|
|
||||||
}
|
|
||||||
|
|
||||||
device->driver = HIDAPI_GetDeviceDriver(device);
|
|
||||||
if (device->driver) {
|
|
||||||
const char *name = device->driver->GetDeviceName(device->name, device->vendor_id, device->product_id);
|
|
||||||
if (name && name != device->name) {
|
|
||||||
SDL_free(device->name);
|
|
||||||
device->name = SDL_strdup(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the device, which may cause a connected event */
|
|
||||||
if (device->driver && !device->driver->InitDevice(device)) {
|
|
||||||
device->driver = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
|
HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
|
||||||
{
|
{
|
||||||
|
@ -318,6 +304,38 @@ HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
|
||||||
device->driver = NULL;
|
device->driver = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
|
||||||
|
{
|
||||||
|
if (device->driver) {
|
||||||
|
SDL_bool enabled;
|
||||||
|
|
||||||
|
if (device->vendor_id == USB_VENDOR_NINTENDO && device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR) {
|
||||||
|
enabled = SDL_HIDAPI_combine_joycons;
|
||||||
|
} else {
|
||||||
|
enabled = device->driver->enabled;
|
||||||
|
}
|
||||||
|
if (!enabled) {
|
||||||
|
HIDAPI_CleanupDeviceDriver(device);
|
||||||
|
}
|
||||||
|
return; /* Already setup */
|
||||||
|
}
|
||||||
|
|
||||||
|
device->driver = HIDAPI_GetDeviceDriver(device);
|
||||||
|
if (device->driver) {
|
||||||
|
const char *name = device->driver->GetDeviceName(device->name, device->vendor_id, device->product_id);
|
||||||
|
if (name && name != device->name) {
|
||||||
|
SDL_free(device->name);
|
||||||
|
device->name = SDL_strdup(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the device, which may cause a connected event */
|
||||||
|
if (device->driver && !device->driver->InitDevice(device)) {
|
||||||
|
device->driver = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void SDLCALL
|
static void SDLCALL
|
||||||
SDL_HIDAPIDriverHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
SDL_HIDAPIDriverHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||||
{
|
{
|
||||||
|
@ -330,6 +348,8 @@ SDL_HIDAPIDriverHintChanged(void *userdata, const char *name, const char *oldVal
|
||||||
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
||||||
driver->enabled = SDL_GetHintBoolean(driver->hint, enabled);
|
driver->enabled = SDL_GetHintBoolean(driver->hint, enabled);
|
||||||
}
|
}
|
||||||
|
} else if (SDL_strcmp(name, SDL_HINT_JOYSTICK_HIDAPI_SWITCH_COMBINE_JOY_CONS) == 0) {
|
||||||
|
SDL_HIDAPI_combine_joycons = enabled;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
|
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
|
||||||
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
||||||
|
@ -351,12 +371,12 @@ SDL_HIDAPIDriverHintChanged(void *userdata, const char *name, const char *oldVal
|
||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
|
|
||||||
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
if (device->driver && !device->driver->enabled) {
|
|
||||||
HIDAPI_CleanupDeviceDriver(device);
|
|
||||||
}
|
|
||||||
HIDAPI_SetupDeviceDriver(device);
|
HIDAPI_SetupDeviceDriver(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the device list again to pick up any new devices */
|
||||||
|
SDL_HIDAPI_change_count = 0;
|
||||||
|
|
||||||
SDL_UnlockJoysticks();
|
SDL_UnlockJoysticks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,6 +419,8 @@ HIDAPI_JoystickInit(void)
|
||||||
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
||||||
SDL_AddHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
|
SDL_AddHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
|
||||||
}
|
}
|
||||||
|
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_COMBINE_JOY_CONS,
|
||||||
|
SDL_HIDAPIDriverHintChanged, NULL);
|
||||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
|
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
|
||||||
SDL_HIDAPIDriverHintChanged, NULL);
|
SDL_HIDAPIDriverHintChanged, NULL);
|
||||||
HIDAPI_JoystickDetect();
|
HIDAPI_JoystickDetect();
|
||||||
|
@ -409,18 +431,70 @@ HIDAPI_JoystickInit(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool
|
static SDL_bool
|
||||||
HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
|
HIDAPI_AddJoystickInstanceToDevice(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
|
||||||
{
|
{
|
||||||
SDL_JoystickID joystickID;
|
|
||||||
SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1)*sizeof(*device->joysticks));
|
SDL_JoystickID *joysticks = (SDL_JoystickID *)SDL_realloc(device->joysticks, (device->num_joysticks + 1)*sizeof(*device->joysticks));
|
||||||
if (!joysticks) {
|
if (!joysticks) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
joystickID = SDL_GetNextJoystickInstanceID();
|
|
||||||
device->joysticks = joysticks;
|
device->joysticks = joysticks;
|
||||||
device->joysticks[device->num_joysticks++] = joystickID;
|
device->joysticks[device->num_joysticks++] = joystickID;
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_bool
|
||||||
|
HIDAPI_DelJoystickInstanceFromDevice(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
|
||||||
|
{
|
||||||
|
int i, size;
|
||||||
|
|
||||||
|
for (i = 0; i < device->num_joysticks; ++i) {
|
||||||
|
if (device->joysticks[i] == joystickID) {
|
||||||
|
size = (device->num_joysticks - i - 1) * sizeof(SDL_JoystickID);
|
||||||
|
SDL_memmove(&device->joysticks[i], &device->joysticks[i+1], size);
|
||||||
|
--device->num_joysticks;
|
||||||
|
if (device->num_joysticks == 0) {
|
||||||
|
SDL_free(device->joysticks);
|
||||||
|
device->joysticks = NULL;
|
||||||
|
}
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_bool
|
||||||
|
HIDAPI_JoystickInstanceIsUnique(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
|
||||||
|
{
|
||||||
|
if (device->parent && device->num_joysticks == 1 && device->parent->num_joysticks == 1 &&
|
||||||
|
device->joysticks[0] == device->parent->joysticks[0]) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_bool
|
||||||
|
HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
SDL_JoystickID joystickID;
|
||||||
|
|
||||||
|
for (i = 0; i < device->num_children; ++i) {
|
||||||
|
SDL_HIDAPI_Device *child = device->children[i];
|
||||||
|
for (j = child->num_joysticks; j--; ) {
|
||||||
|
HIDAPI_JoystickDisconnected(child, child->joysticks[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
joystickID = SDL_GetNextJoystickInstanceID();
|
||||||
|
HIDAPI_AddJoystickInstanceToDevice(device, joystickID);
|
||||||
|
|
||||||
|
for (i = 0; i < device->num_children; ++i) {
|
||||||
|
SDL_HIDAPI_Device *child = device->children[i];
|
||||||
|
HIDAPI_AddJoystickInstanceToDevice(child, joystickID);
|
||||||
|
}
|
||||||
|
|
||||||
++SDL_HIDAPI_numjoysticks;
|
++SDL_HIDAPI_numjoysticks;
|
||||||
|
|
||||||
SDL_PrivateJoystickAdded(joystickID);
|
SDL_PrivateJoystickAdded(joystickID);
|
||||||
|
@ -434,29 +508,38 @@ HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
|
||||||
void
|
void
|
||||||
HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
|
HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
|
||||||
{
|
{
|
||||||
int i, size;
|
int i, j;
|
||||||
|
SDL_bool unique = HIDAPI_JoystickInstanceIsUnique(device, joystickID);
|
||||||
|
|
||||||
|
if (!unique) {
|
||||||
|
/* Disconnecting a child always disconnects the parent */
|
||||||
|
device = device->parent;
|
||||||
|
unique = SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < device->num_joysticks; ++i) {
|
for (i = 0; i < device->num_joysticks; ++i) {
|
||||||
if (device->joysticks[i] == joystickID) {
|
if (device->joysticks[i] == joystickID) {
|
||||||
|
if (unique) {
|
||||||
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(joystickID);
|
SDL_Joystick *joystick = SDL_JoystickFromInstanceID(joystickID);
|
||||||
if (joystick) {
|
if (joystick) {
|
||||||
HIDAPI_JoystickClose(joystick);
|
HIDAPI_JoystickClose(joystick);
|
||||||
}
|
}
|
||||||
|
|
||||||
size = (device->num_joysticks - i - 1) * sizeof(SDL_JoystickID);
|
|
||||||
SDL_memmove(&device->joysticks[i], &device->joysticks[i+1], size);
|
|
||||||
--device->num_joysticks;
|
|
||||||
|
|
||||||
--SDL_HIDAPI_numjoysticks;
|
|
||||||
if (device->num_joysticks == 0) {
|
|
||||||
SDL_free(device->joysticks);
|
|
||||||
device->joysticks = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HIDAPI_DelJoystickInstanceFromDevice(device, joystickID);
|
||||||
|
|
||||||
|
for (j = 0; j < device->num_children; ++j) {
|
||||||
|
SDL_HIDAPI_Device *child = device->children[j];
|
||||||
|
HIDAPI_DelJoystickInstanceFromDevice(child, joystickID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unique) {
|
||||||
|
--SDL_HIDAPI_numjoysticks;
|
||||||
|
|
||||||
if (!shutting_down) {
|
if (!shutting_down) {
|
||||||
SDL_PrivateJoystickRemoved(joystickID);
|
SDL_PrivateJoystickRemoved(joystickID);
|
||||||
}
|
}
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,8 +571,8 @@ HIDAPI_ConvertString(const wchar_t *wide_string)
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static SDL_HIDAPI_Device *
|
||||||
HIDAPI_AddDevice(struct SDL_hid_device_info *info)
|
HIDAPI_AddDevice(const struct SDL_hid_device_info *info, int num_children, SDL_HIDAPI_Device **children)
|
||||||
{
|
{
|
||||||
SDL_HIDAPI_Device *device;
|
SDL_HIDAPI_Device *device;
|
||||||
SDL_HIDAPI_Device *curr, *last = NULL;
|
SDL_HIDAPI_Device *curr, *last = NULL;
|
||||||
|
@ -500,12 +583,12 @@ HIDAPI_AddDevice(struct SDL_hid_device_info *info)
|
||||||
|
|
||||||
device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device));
|
device = (SDL_HIDAPI_Device *)SDL_calloc(1, sizeof(*device));
|
||||||
if (!device) {
|
if (!device) {
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
device->path = SDL_strdup(info->path);
|
device->path = SDL_strdup(info->path);
|
||||||
if (!device->path) {
|
if (!device->path) {
|
||||||
SDL_free(device);
|
SDL_free(device);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
device->seen = SDL_TRUE;
|
device->seen = SDL_TRUE;
|
||||||
device->vendor_id = info->vendor_id;
|
device->vendor_id = info->vendor_id;
|
||||||
|
@ -564,7 +647,17 @@ HIDAPI_AddDevice(struct SDL_hid_device_info *info)
|
||||||
SDL_free(device->serial);
|
SDL_free(device->serial);
|
||||||
SDL_free(device->path);
|
SDL_free(device->path);
|
||||||
SDL_free(device);
|
SDL_free(device);
|
||||||
return;
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_children > 0) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
device->num_children = num_children;
|
||||||
|
device->children = children;
|
||||||
|
for (i = 0; i < num_children; ++i) {
|
||||||
|
children[i]->parent = device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,9 +670,12 @@ HIDAPI_AddDevice(struct SDL_hid_device_info *info)
|
||||||
|
|
||||||
HIDAPI_SetupDeviceDriver(device);
|
HIDAPI_SetupDeviceDriver(device);
|
||||||
|
|
||||||
|
#define DEBUG_HIDAPI
|
||||||
#ifdef DEBUG_HIDAPI
|
#ifdef DEBUG_HIDAPI
|
||||||
SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->hint : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
|
SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->hint : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -617,6 +713,62 @@ HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDL_bool
|
||||||
|
HIDAPI_CreateCombinedJoyCons()
|
||||||
|
{
|
||||||
|
SDL_HIDAPI_Device *device, *combined;
|
||||||
|
SDL_HIDAPI_Device *joycons[2] = { NULL, NULL };
|
||||||
|
|
||||||
|
if (!SDL_HIDAPI_combine_joycons) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
|
if (!device->driver) {
|
||||||
|
/* Unsupported device */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (device->parent) {
|
||||||
|
/* This device is already part of a combined device */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!joycons[0] && SDL_IsJoystickNintendoSwitchJoyConLeft(device->vendor_id, device->product_id)) {
|
||||||
|
joycons[0] = device;
|
||||||
|
}
|
||||||
|
if (!joycons[1] && SDL_IsJoystickNintendoSwitchJoyConRight(device->vendor_id, device->product_id)) {
|
||||||
|
joycons[1] = device;
|
||||||
|
}
|
||||||
|
if (joycons[0] && joycons[1]) {
|
||||||
|
SDL_hid_device_info info;
|
||||||
|
SDL_HIDAPI_Device **children = (SDL_HIDAPI_Device **)SDL_malloc(2 * sizeof(SDL_HIDAPI_Device *));
|
||||||
|
if (!children) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
children[0] = joycons[0];
|
||||||
|
children[1] = joycons[1];
|
||||||
|
|
||||||
|
SDL_zero(info);
|
||||||
|
info.path = "nintendo_joycons_combined";
|
||||||
|
info.vendor_id = USB_VENDOR_NINTENDO;
|
||||||
|
info.product_id = USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR;
|
||||||
|
info.interface_number = -1;
|
||||||
|
info.usage_page = USB_USAGEPAGE_GENERIC_DESKTOP;
|
||||||
|
info.usage = USB_USAGE_GENERIC_GAMEPAD;
|
||||||
|
info.manufacturer_string = L"Nintendo";
|
||||||
|
info.product_string = L"Switch Joy-Con (L/R)";
|
||||||
|
|
||||||
|
combined = HIDAPI_AddDevice(&info, 2, children);
|
||||||
|
if (combined && combined->driver) {
|
||||||
|
return SDL_TRUE;
|
||||||
|
} else {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
HIDAPI_UpdateDeviceList(void)
|
HIDAPI_UpdateDeviceList(void)
|
||||||
{
|
{
|
||||||
|
@ -626,10 +778,11 @@ HIDAPI_UpdateDeviceList(void)
|
||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
|
|
||||||
/* Prepare the existing device list */
|
/* Prepare the existing device list */
|
||||||
device = SDL_HIDAPI_devices;
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
while (device) {
|
if (device->children) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
device->seen = SDL_FALSE;
|
device->seen = SDL_FALSE;
|
||||||
device = device->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enumerate the devices */
|
/* Enumerate the devices */
|
||||||
|
@ -641,7 +794,7 @@ HIDAPI_UpdateDeviceList(void)
|
||||||
if (device) {
|
if (device) {
|
||||||
device->seen = SDL_TRUE;
|
device->seen = SDL_TRUE;
|
||||||
} else {
|
} else {
|
||||||
HIDAPI_AddDevice(info);
|
HIDAPI_AddDevice(info, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SDL_hid_free_enumeration(devs);
|
SDL_hid_free_enumeration(devs);
|
||||||
|
@ -649,17 +802,39 @@ HIDAPI_UpdateDeviceList(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove any devices that weren't seen or have been disconnected due to read errors */
|
/* Remove any devices that weren't seen or have been disconnected due to read errors */
|
||||||
|
check_removed:
|
||||||
device = SDL_HIDAPI_devices;
|
device = SDL_HIDAPI_devices;
|
||||||
while (device) {
|
while (device) {
|
||||||
SDL_HIDAPI_Device *next = device->next;
|
SDL_HIDAPI_Device *next = device->next;
|
||||||
|
|
||||||
if (!device->seen ||
|
if (!device->seen ||
|
||||||
(device->driver && device->num_joysticks == 0 && !device->dev)) {
|
(device->driver && device->num_joysticks == 0 && !device->dev)) {
|
||||||
|
if (device->parent) {
|
||||||
|
/* When a child device goes away, so does the parent */
|
||||||
|
int i;
|
||||||
|
device = device->parent;
|
||||||
|
for (i = 0; i < device->num_children; ++i) {
|
||||||
|
HIDAPI_DelDevice(device->children[i]);
|
||||||
|
}
|
||||||
|
HIDAPI_DelDevice(device);
|
||||||
|
|
||||||
|
/* Update the device list again to pick up any children left */
|
||||||
|
SDL_HIDAPI_change_count = 0;
|
||||||
|
|
||||||
|
/* We deleted more than one device here, restart the loop */
|
||||||
|
goto check_removed;
|
||||||
|
} else {
|
||||||
HIDAPI_DelDevice(device);
|
HIDAPI_DelDevice(device);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
device = next;
|
device = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See if we can create any combined Joy-Con controllers */
|
||||||
|
while (HIDAPI_CreateCombinedJoyCons()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_UnlockJoysticks();
|
SDL_UnlockJoysticks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,14 +885,12 @@ HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type)
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
device = SDL_HIDAPI_devices;
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
while (device) {
|
|
||||||
if (device->driver &&
|
if (device->driver &&
|
||||||
SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == type) {
|
SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == type) {
|
||||||
result = SDL_TRUE;
|
result = SDL_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
device = device->next;
|
|
||||||
}
|
}
|
||||||
SDL_UnlockJoysticks();
|
SDL_UnlockJoysticks();
|
||||||
|
|
||||||
|
@ -764,14 +937,12 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons
|
||||||
and we have something similar in our device list, mark it as present.
|
and we have something similar in our device list, mark it as present.
|
||||||
*/
|
*/
|
||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
device = SDL_HIDAPI_devices;
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
while (device) {
|
|
||||||
if (device->driver &&
|
if (device->driver &&
|
||||||
HIDAPI_IsEquivalentToDevice(vendor_id, product_id, device)) {
|
HIDAPI_IsEquivalentToDevice(vendor_id, product_id, device)) {
|
||||||
result = SDL_TRUE;
|
result = SDL_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
device = device->next;
|
|
||||||
}
|
}
|
||||||
SDL_UnlockJoysticks();
|
SDL_UnlockJoysticks();
|
||||||
|
|
||||||
|
@ -787,8 +958,8 @@ HIDAPI_JoystickDetect(void)
|
||||||
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
|
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
|
||||||
Uint32 count = SDL_hid_device_change_count();
|
Uint32 count = SDL_hid_device_change_count();
|
||||||
if (SDL_HIDAPI_change_count != count) {
|
if (SDL_HIDAPI_change_count != count) {
|
||||||
HIDAPI_UpdateDeviceList();
|
|
||||||
SDL_HIDAPI_change_count = count;
|
SDL_HIDAPI_change_count = count;
|
||||||
|
HIDAPI_UpdateDeviceList();
|
||||||
}
|
}
|
||||||
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
|
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
|
||||||
}
|
}
|
||||||
|
@ -803,8 +974,10 @@ HIDAPI_UpdateDevices(void)
|
||||||
|
|
||||||
/* Prepare the existing device list */
|
/* Prepare the existing device list */
|
||||||
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
|
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
|
||||||
device = SDL_HIDAPI_devices;
|
for (device = SDL_HIDAPI_devices; device; device = device->next) {
|
||||||
while (device) {
|
if (device->parent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (device->driver) {
|
if (device->driver) {
|
||||||
if (SDL_TryLockMutex(device->dev_lock) == 0) {
|
if (SDL_TryLockMutex(device->dev_lock) == 0) {
|
||||||
device->updating = SDL_TRUE;
|
device->updating = SDL_TRUE;
|
||||||
|
@ -813,7 +986,6 @@ HIDAPI_UpdateDevices(void)
|
||||||
SDL_UnlockMutex(device->dev_lock);
|
SDL_UnlockMutex(device->dev_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
device = device->next;
|
|
||||||
}
|
}
|
||||||
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
|
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1237,18 @@ HIDAPI_JoystickQuit(void)
|
||||||
SDL_HIDAPI_QuitRumble();
|
SDL_HIDAPI_QuitRumble();
|
||||||
|
|
||||||
while (SDL_HIDAPI_devices) {
|
while (SDL_HIDAPI_devices) {
|
||||||
HIDAPI_DelDevice(SDL_HIDAPI_devices);
|
SDL_HIDAPI_Device *device = SDL_HIDAPI_devices;
|
||||||
|
if (device->parent) {
|
||||||
|
/* When a child device goes away, so does the parent */
|
||||||
|
int i;
|
||||||
|
device = device->parent;
|
||||||
|
for (i = 0; i < device->num_children; ++i) {
|
||||||
|
HIDAPI_DelDevice(device->children[i]);
|
||||||
|
}
|
||||||
|
HIDAPI_DelDevice(device);
|
||||||
|
} else {
|
||||||
|
HIDAPI_DelDevice(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the drivers cleaned up properly */
|
/* Make sure the drivers cleaned up properly */
|
||||||
|
@ -1075,6 +1258,8 @@ HIDAPI_JoystickQuit(void)
|
||||||
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
||||||
SDL_DelHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
|
SDL_DelHintCallback(driver->hint, SDL_HIDAPIDriverHintChanged, NULL);
|
||||||
}
|
}
|
||||||
|
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_COMBINE_JOY_CONS,
|
||||||
|
SDL_HIDAPIDriverHintChanged, NULL);
|
||||||
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
|
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
|
||||||
SDL_HIDAPIDriverHintChanged, NULL);
|
SDL_HIDAPIDriverHintChanged, NULL);
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,10 @@ typedef struct _SDL_HIDAPI_Device
|
||||||
/* Used to flag that the device is being updated */
|
/* Used to flag that the device is being updated */
|
||||||
SDL_bool updating;
|
SDL_bool updating;
|
||||||
|
|
||||||
|
struct _SDL_HIDAPI_Device *parent;
|
||||||
|
int num_children;
|
||||||
|
struct _SDL_HIDAPI_Device **children;
|
||||||
|
|
||||||
struct _SDL_HIDAPI_Device *next;
|
struct _SDL_HIDAPI_Device *next;
|
||||||
} SDL_HIDAPI_Device;
|
} SDL_HIDAPI_Device;
|
||||||
|
|
||||||
|
@ -110,6 +114,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
|
||||||
|
|
||||||
|
|
||||||
/* HIDAPI device support */
|
/* HIDAPI device support */
|
||||||
|
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverCombined;
|
||||||
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube;
|
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube;
|
||||||
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna;
|
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna;
|
||||||
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield;
|
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield;
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#define USB_PRODUCT_NINTENDO_SWITCH_PRO 0x2009
|
#define USB_PRODUCT_NINTENDO_SWITCH_PRO 0x2009
|
||||||
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_LEFT 0x2006
|
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_LEFT 0x2006
|
||||||
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT 0x2007
|
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT 0x2007
|
||||||
|
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_PAIR 0x2008 /* Used by joycond */
|
||||||
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP 0x200e
|
#define USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_GRIP 0x200e
|
||||||
#define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019
|
#define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019
|
||||||
#define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e
|
#define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e
|
||||||
|
|
|
@ -764,7 +764,6 @@ main(int argc, char *argv[])
|
||||||
char guid[64];
|
char guid[64];
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
|
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
|
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
|
||||||
SDL_SetHint(SDL_HINT_JOYSTICK_ROG_CHAKRAM, "1");
|
SDL_SetHint(SDL_HINT_JOYSTICK_ROG_CHAKRAM, "1");
|
||||||
|
|
Loading…
Reference in New Issue