mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-13 13:25:59 +00:00
Added SDL_HINT_JOYSTICK_ENHANCED_REPORTS
This hint defaults on, enabling advanced controller features. This replaces SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE and SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, and is supported by PlayStation and Nintendo Switch controllers. Fixes https://github.com/libsdl-org/SDL/issues/10086
This commit is contained in:
@@ -129,18 +129,16 @@ typedef struct
|
||||
} IMUCalibrationData;
|
||||
|
||||
/* Rumble hint mode:
|
||||
* default: enhanced features are available if the controller is using enhanced reports
|
||||
* "0": enhanced features are never used
|
||||
* "1": enhanced features are always used
|
||||
* "auto": enhanced features are advertised to the application, but SDL doesn't touch the controller state unless the application explicitly requests it.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PS4_RUMBLE_HINT_DEFAULT,
|
||||
PS4_RUMBLE_HINT_OFF,
|
||||
PS4_RUMBLE_HINT_ON,
|
||||
PS4_RUMBLE_HINT_AUTO
|
||||
} SDL_PS4_RumbleHintMode;
|
||||
PS4_ENHANCED_REPORT_HINT_OFF,
|
||||
PS4_ENHANCED_REPORT_HINT_ON,
|
||||
PS4_ENHANCED_REPORT_HINT_AUTO
|
||||
} HIDAPI_PS4_EnhancedReportHint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -154,7 +152,7 @@ typedef struct
|
||||
bool vibration_supported;
|
||||
bool touchpad_supported;
|
||||
bool effects_supported;
|
||||
SDL_PS4_RumbleHintMode rumble_hint;
|
||||
HIDAPI_PS4_EnhancedReportHint enhanced_report_hint;
|
||||
bool enhanced_reports;
|
||||
bool enhanced_mode;
|
||||
bool enhanced_mode_available;
|
||||
@@ -696,7 +694,7 @@ static void HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
|
||||
SDL_HIDAPI_SendRumbleAndUnlock(device, data, sizeof(data));
|
||||
}
|
||||
} else {
|
||||
#if 0 /* The 8BitDo Zero 2 has perfect emulation of a PS4 controllers, except it
|
||||
#if 0 /* The 8BitDo Zero 2 has perfect emulation of a PS4 controller, except it
|
||||
* only sends reports when the state changes, so we can't disconnect here.
|
||||
*/
|
||||
// We can't even send an invalid effects packet, or it will put the controller in enhanced mode
|
||||
@@ -709,6 +707,9 @@ static void HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
|
||||
|
||||
static void HIDAPI_DriverPS4_SetEnhancedModeAvailable(SDL_DriverPS4_Context *ctx)
|
||||
{
|
||||
if (ctx->enhanced_mode_available) {
|
||||
return;
|
||||
}
|
||||
ctx->enhanced_mode_available = true;
|
||||
|
||||
if (ctx->touchpad_supported) {
|
||||
@@ -730,9 +731,7 @@ static void HIDAPI_DriverPS4_SetEnhancedModeAvailable(SDL_DriverPS4_Context *ctx
|
||||
|
||||
static void HIDAPI_DriverPS4_SetEnhancedMode(SDL_DriverPS4_Context *ctx)
|
||||
{
|
||||
if (!ctx->enhanced_mode_available) {
|
||||
HIDAPI_DriverPS4_SetEnhancedModeAvailable(ctx);
|
||||
}
|
||||
HIDAPI_DriverPS4_SetEnhancedModeAvailable(ctx);
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
ctx->enhanced_mode = true;
|
||||
@@ -742,55 +741,52 @@ static void HIDAPI_DriverPS4_SetEnhancedMode(SDL_DriverPS4_Context *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS4_SetRumbleHintMode(SDL_DriverPS4_Context *ctx, SDL_PS4_RumbleHintMode rumble_hint)
|
||||
static void HIDAPI_DriverPS4_SetEnhancedReportHint(SDL_DriverPS4_Context *ctx, HIDAPI_PS4_EnhancedReportHint enhanced_report_hint)
|
||||
{
|
||||
switch (rumble_hint) {
|
||||
case PS4_RUMBLE_HINT_DEFAULT:
|
||||
if (ctx->enhanced_reports) {
|
||||
HIDAPI_DriverPS4_SetEnhancedMode(ctx);
|
||||
}
|
||||
break;
|
||||
case PS4_RUMBLE_HINT_OFF:
|
||||
switch (enhanced_report_hint) {
|
||||
case PS4_ENHANCED_REPORT_HINT_OFF:
|
||||
// Nothing to do, enhanced mode is a one-way ticket
|
||||
break;
|
||||
case PS4_RUMBLE_HINT_ON:
|
||||
case PS4_ENHANCED_REPORT_HINT_ON:
|
||||
HIDAPI_DriverPS4_SetEnhancedMode(ctx);
|
||||
break;
|
||||
case PS4_RUMBLE_HINT_AUTO:
|
||||
case PS4_ENHANCED_REPORT_HINT_AUTO:
|
||||
HIDAPI_DriverPS4_SetEnhancedModeAvailable(ctx);
|
||||
break;
|
||||
}
|
||||
ctx->rumble_hint = rumble_hint;
|
||||
ctx->enhanced_report_hint = enhanced_report_hint;
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS4_UpdateEnhancedModeOnEnhancedReport(SDL_DriverPS4_Context *ctx)
|
||||
{
|
||||
ctx->enhanced_reports = true;
|
||||
|
||||
if (ctx->rumble_hint == PS4_RUMBLE_HINT_DEFAULT) {
|
||||
HIDAPI_DriverPS4_SetRumbleHintMode(ctx, PS4_RUMBLE_HINT_ON);
|
||||
if (ctx->enhanced_report_hint == PS4_ENHANCED_REPORT_HINT_AUTO) {
|
||||
HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS4_UpdateEnhancedModeOnApplicationUsage(SDL_DriverPS4_Context *ctx)
|
||||
{
|
||||
if (ctx->rumble_hint == PS4_RUMBLE_HINT_AUTO) {
|
||||
HIDAPI_DriverPS4_SetRumbleHintMode(ctx, PS4_RUMBLE_HINT_ON);
|
||||
if (ctx->enhanced_report_hint == PS4_ENHANCED_REPORT_HINT_AUTO) {
|
||||
HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_PS4RumbleHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
static void SDLCALL SDL_PS4EnhancedReportsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)userdata;
|
||||
|
||||
if (!hint) {
|
||||
HIDAPI_DriverPS4_SetRumbleHintMode(ctx, PS4_RUMBLE_HINT_DEFAULT);
|
||||
} else if (SDL_strcasecmp(hint, "auto") == 0) {
|
||||
HIDAPI_DriverPS4_SetRumbleHintMode(ctx, PS4_RUMBLE_HINT_AUTO);
|
||||
} else if (SDL_GetStringBoolean(hint, false)) {
|
||||
HIDAPI_DriverPS4_SetRumbleHintMode(ctx, PS4_RUMBLE_HINT_ON);
|
||||
if (ctx->device->is_bluetooth) {
|
||||
if (hint && SDL_strcasecmp(hint, "auto") == 0) {
|
||||
HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_AUTO);
|
||||
} else if (SDL_GetStringBoolean(hint, true)) {
|
||||
HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
|
||||
} else {
|
||||
HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_OFF);
|
||||
}
|
||||
} else {
|
||||
HIDAPI_DriverPS4_SetRumbleHintMode(ctx, PS4_RUMBLE_HINT_OFF);
|
||||
HIDAPI_DriverPS4_SetEnhancedReportHint(ctx, PS4_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -868,8 +864,8 @@ static bool HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystic
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL,
|
||||
SDL_PS4ReportIntervalHintChanged, ctx);
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE,
|
||||
SDL_PS4RumbleHintChanged, ctx);
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
|
||||
SDL_PS4EnhancedReportsChanged, ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1287,7 +1283,7 @@ static bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
case k_EPS4ReportIdBluetoothState7:
|
||||
case k_EPS4ReportIdBluetoothState8:
|
||||
case k_EPS4ReportIdBluetoothState9:
|
||||
// This is the extended report, we can enable effects now in default mode
|
||||
// This is the extended report, we can enable effects now in auto mode
|
||||
HIDAPI_DriverPS4_UpdateEnhancedModeOnEnhancedReport(ctx);
|
||||
|
||||
// Bluetooth state packets have two additional bytes at the beginning, the first notes if HID is present
|
||||
@@ -1353,8 +1349,8 @@ static void HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joysti
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL,
|
||||
SDL_PS4ReportIntervalHintChanged, ctx);
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE,
|
||||
SDL_PS4RumbleHintChanged, ctx);
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
|
||||
SDL_PS4EnhancedReportsChanged, ctx);
|
||||
|
||||
ctx->joystick = NULL;
|
||||
}
|
||||
|
@@ -215,18 +215,16 @@ typedef struct
|
||||
} IMUCalibrationData;
|
||||
|
||||
/* Rumble hint mode:
|
||||
* default: enhanced features are available if the controller is using enhanced reports
|
||||
* "0": enhanced features are never used
|
||||
* "1": enhanced features are always used
|
||||
* "auto": enhanced features are advertised to the application, but SDL doesn't touch the controller state unless the application explicitly requests it.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PS5_RUMBLE_HINT_DEFAULT,
|
||||
PS5_RUMBLE_HINT_OFF,
|
||||
PS5_RUMBLE_HINT_ON,
|
||||
PS5_RUMBLE_HINT_AUTO
|
||||
} SDL_PS5_RumbleHintMode;
|
||||
PS5_ENHANCED_REPORT_HINT_OFF,
|
||||
PS5_ENHANCED_REPORT_HINT_ON,
|
||||
PS5_ENHANCED_REPORT_HINT_AUTO
|
||||
} HIDAPI_PS5_EnhancedReportHint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -240,7 +238,7 @@ typedef struct
|
||||
bool playerled_supported;
|
||||
bool touchpad_supported;
|
||||
bool effects_supported;
|
||||
SDL_PS5_RumbleHintMode rumble_hint;
|
||||
HIDAPI_PS5_EnhancedReportHint enhanced_report_hint;
|
||||
bool enhanced_reports;
|
||||
bool enhanced_mode;
|
||||
bool enhanced_mode_available;
|
||||
@@ -803,6 +801,9 @@ static void HIDAPI_DriverPS5_TickleBluetooth(SDL_HIDAPI_Device *device)
|
||||
|
||||
static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx)
|
||||
{
|
||||
if (ctx->enhanced_mode_available) {
|
||||
return;
|
||||
}
|
||||
ctx->enhanced_mode_available = true;
|
||||
|
||||
if (ctx->touchpad_supported) {
|
||||
@@ -828,11 +829,9 @@ static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx
|
||||
|
||||
static void HIDAPI_DriverPS5_SetEnhancedMode(SDL_DriverPS5_Context *ctx)
|
||||
{
|
||||
if (!ctx->enhanced_mode_available) {
|
||||
HIDAPI_DriverPS5_SetEnhancedModeAvailable(ctx);
|
||||
}
|
||||
HIDAPI_DriverPS5_SetEnhancedModeAvailable(ctx);
|
||||
|
||||
if (!ctx->enhanced_mode && ctx->enhanced_mode_available) {
|
||||
if (!ctx->enhanced_mode) {
|
||||
ctx->enhanced_mode = true;
|
||||
|
||||
// Switch into enhanced report mode
|
||||
@@ -843,63 +842,52 @@ static void HIDAPI_DriverPS5_SetEnhancedMode(SDL_DriverPS5_Context *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS5_SetRumbleHintMode(SDL_DriverPS5_Context *ctx, SDL_PS5_RumbleHintMode rumble_hint)
|
||||
static void HIDAPI_DriverPS5_SetEnhancedReportHint(SDL_DriverPS5_Context *ctx, HIDAPI_PS5_EnhancedReportHint enhanced_report_hint)
|
||||
{
|
||||
switch (rumble_hint) {
|
||||
case PS5_RUMBLE_HINT_DEFAULT:
|
||||
if (ctx->enhanced_reports) {
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx);
|
||||
}
|
||||
break;
|
||||
case PS5_RUMBLE_HINT_OFF:
|
||||
switch (enhanced_report_hint) {
|
||||
case PS5_ENHANCED_REPORT_HINT_OFF:
|
||||
// Nothing to do, enhanced mode is a one-way ticket
|
||||
break;
|
||||
case PS5_RUMBLE_HINT_ON:
|
||||
case PS5_ENHANCED_REPORT_HINT_ON:
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx);
|
||||
break;
|
||||
case PS5_RUMBLE_HINT_AUTO:
|
||||
case PS5_ENHANCED_REPORT_HINT_AUTO:
|
||||
HIDAPI_DriverPS5_SetEnhancedModeAvailable(ctx);
|
||||
break;
|
||||
}
|
||||
ctx->rumble_hint = rumble_hint;
|
||||
ctx->enhanced_report_hint = enhanced_report_hint;
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS5_UpdateEnhancedModeOnEnhancedReport(SDL_DriverPS5_Context *ctx)
|
||||
{
|
||||
ctx->enhanced_reports = true;
|
||||
|
||||
if (ctx->rumble_hint == PS5_RUMBLE_HINT_DEFAULT) {
|
||||
HIDAPI_DriverPS5_SetRumbleHintMode(ctx, PS5_RUMBLE_HINT_ON);
|
||||
if (ctx->enhanced_report_hint == PS5_ENHANCED_REPORT_HINT_AUTO) {
|
||||
HIDAPI_DriverPS5_SetEnhancedReportHint(ctx, PS5_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS5_UpdateEnhancedModeOnApplicationUsage(SDL_DriverPS5_Context *ctx)
|
||||
{
|
||||
if (ctx->rumble_hint == PS5_RUMBLE_HINT_AUTO) {
|
||||
HIDAPI_DriverPS5_SetRumbleHintMode(ctx, PS5_RUMBLE_HINT_ON);
|
||||
if (ctx->enhanced_report_hint == PS5_ENHANCED_REPORT_HINT_AUTO) {
|
||||
HIDAPI_DriverPS5_SetEnhancedReportHint(ctx, PS5_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_PS5RumbleHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
static void SDLCALL SDL_PS5EnhancedReportsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)userdata;
|
||||
|
||||
if (!hint) {
|
||||
/* Games written prior the introduction of PS5 controller support in SDL will not be aware of
|
||||
SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, but they did know SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE.
|
||||
To support apps that only knew about the PS4 hint, we'll use the PS4 hint as the default.
|
||||
*/
|
||||
hint = SDL_GetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE);
|
||||
}
|
||||
|
||||
if (!hint) {
|
||||
HIDAPI_DriverPS5_SetRumbleHintMode(ctx, PS5_RUMBLE_HINT_DEFAULT);
|
||||
} else if (SDL_strcasecmp(hint, "auto") == 0) {
|
||||
HIDAPI_DriverPS5_SetRumbleHintMode(ctx, PS5_RUMBLE_HINT_AUTO);
|
||||
} else if (SDL_GetStringBoolean(hint, false)) {
|
||||
HIDAPI_DriverPS5_SetRumbleHintMode(ctx, PS5_RUMBLE_HINT_ON);
|
||||
if (ctx->device->is_bluetooth) {
|
||||
if (hint && SDL_strcasecmp(hint, "auto") == 0) {
|
||||
HIDAPI_DriverPS5_SetEnhancedReportHint(ctx, PS5_ENHANCED_REPORT_HINT_AUTO);
|
||||
} else if (SDL_GetStringBoolean(hint, true)) {
|
||||
HIDAPI_DriverPS5_SetEnhancedReportHint(ctx, PS5_ENHANCED_REPORT_HINT_ON);
|
||||
} else {
|
||||
HIDAPI_DriverPS5_SetEnhancedReportHint(ctx, PS5_ENHANCED_REPORT_HINT_OFF);
|
||||
}
|
||||
} else {
|
||||
HIDAPI_DriverPS5_SetRumbleHintMode(ctx, PS5_RUMBLE_HINT_OFF);
|
||||
HIDAPI_DriverPS5_SetEnhancedReportHint(ctx, PS5_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,9 +950,9 @@ static bool HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystic
|
||||
joystick->nhats = 1;
|
||||
joystick->firmware_version = ctx->firmware_version;
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE,
|
||||
SDL_PS5RumbleHintChanged, ctx);
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED,
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
|
||||
SDL_PS5EnhancedReportsChanged, ctx);
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
|
||||
SDL_PS5PlayerLEDHintChanged, ctx);
|
||||
|
||||
return true;
|
||||
@@ -1529,7 +1517,7 @@ static bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
break;
|
||||
case k_EPS5ReportIdBluetoothState:
|
||||
// This is the extended report, we can enable effects now in default mode
|
||||
// This is the extended report, we can enable effects now in auto mode
|
||||
HIDAPI_DriverPS5_UpdateEnhancedModeOnEnhancedReport(ctx);
|
||||
|
||||
if (ctx->use_alternate_report) {
|
||||
@@ -1592,8 +1580,8 @@ static void HIDAPI_DriverPS5_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joysti
|
||||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE,
|
||||
SDL_PS5RumbleHintChanged, ctx);
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
|
||||
SDL_PS5EnhancedReportsChanged, ctx);
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED,
|
||||
SDL_PS5PlayerLEDHintChanged, ctx);
|
||||
|
@@ -268,6 +268,18 @@ typedef struct
|
||||
} SwitchProprietaryOutputPacket_t;
|
||||
#pragma pack()
|
||||
|
||||
/* Enhanced report hint mode:
|
||||
* "0": enhanced features are never used
|
||||
* "1": enhanced features are always used
|
||||
* "auto": enhanced features are advertised to the application, but SDL doesn't touch the controller state unless the application explicitly requests it.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SWITCH_ENHANCED_REPORT_HINT_OFF,
|
||||
SWITCH_ENHANCED_REPORT_HINT_ON,
|
||||
SWITCH_ENHANCED_REPORT_HINT_AUTO
|
||||
} HIDAPI_Switch_EnhancedReportHint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
@@ -283,6 +295,9 @@ typedef struct
|
||||
Uint8 m_nCurrentInputMode;
|
||||
Uint8 m_rgucMACAddress[6];
|
||||
Uint8 m_nCommandNumber;
|
||||
HIDAPI_Switch_EnhancedReportHint m_eEnhancedReportHint;
|
||||
bool m_bEnhancedMode;
|
||||
bool m_bEnhancedModeAvailable;
|
||||
SwitchCommonOutputPacket_t m_RumblePacket;
|
||||
Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength];
|
||||
bool m_bRumbleActive;
|
||||
@@ -290,6 +305,7 @@ typedef struct
|
||||
bool m_bRumblePending;
|
||||
bool m_bRumbleZeroPending;
|
||||
Uint32 m_unRumblePending;
|
||||
bool m_bSensorsSupported;
|
||||
bool m_bReportSensors;
|
||||
bool m_bHasSensorData;
|
||||
Uint64 m_ulLastInput;
|
||||
@@ -777,24 +793,25 @@ static Uint8 GetDefaultInputMode(SDL_DriverSwitch_Context *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
/* The official Nintendo Switch Pro Controller supports FullControllerState over Bluetooth
|
||||
* just fine. We really should use that, or else the epowerlevel code in HandleFullControllerState
|
||||
* is completely pointless. We need full state if we want battery level and we only care about
|
||||
* battery level over Bluetooth anyway.
|
||||
*/
|
||||
if (ctx->device->vendor_id == USB_VENDOR_NINTENDO) {
|
||||
// However, switching to full controller state breaks DirectInput, so let's not do that
|
||||
#if 0
|
||||
input_mode = k_eSwitchInputReportIDs_FullControllerState;
|
||||
#endif
|
||||
|
||||
/* However, Joy-Con controllers switch their thumbsticks into D-pad mode in simple mode,
|
||||
* so let's enable full controller state for them.
|
||||
*/
|
||||
if (ctx->device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT ||
|
||||
ctx->device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
|
||||
switch (ctx->m_eEnhancedReportHint) {
|
||||
case SWITCH_ENHANCED_REPORT_HINT_OFF:
|
||||
input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
|
||||
break;
|
||||
case SWITCH_ENHANCED_REPORT_HINT_ON:
|
||||
if (input_mode == k_eSwitchInputReportIDs_SimpleControllerState) {
|
||||
input_mode = k_eSwitchInputReportIDs_FullControllerState;
|
||||
}
|
||||
break;
|
||||
case SWITCH_ENHANCED_REPORT_HINT_AUTO:
|
||||
/* Joy-Con controllers switch their thumbsticks into D-pad mode in simple mode,
|
||||
* so let's enable full controller state for them.
|
||||
*/
|
||||
if (ctx->device->vendor_id == USB_VENDOR_NINTENDO &&
|
||||
(ctx->device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT ||
|
||||
ctx->device->product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT)) {
|
||||
input_mode = k_eSwitchInputReportIDs_FullControllerState;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return input_mode;
|
||||
}
|
||||
@@ -813,6 +830,103 @@ static Uint8 GetSensorInputMode(SDL_DriverSwitch_Context *ctx)
|
||||
return input_mode;
|
||||
}
|
||||
|
||||
static void UpdateInputMode(SDL_DriverSwitch_Context *ctx)
|
||||
{
|
||||
Uint8 input_mode;
|
||||
|
||||
if (ctx->m_bReportSensors) {
|
||||
input_mode = GetSensorInputMode(ctx);
|
||||
} else {
|
||||
input_mode = GetDefaultInputMode(ctx);
|
||||
}
|
||||
SetInputMode(ctx, input_mode);
|
||||
}
|
||||
|
||||
static void SetEnhancedModeAvailable(SDL_DriverSwitch_Context *ctx)
|
||||
{
|
||||
if (ctx->m_bEnhancedModeAvailable) {
|
||||
return;
|
||||
}
|
||||
ctx->m_bEnhancedModeAvailable = true;
|
||||
|
||||
if (ctx->m_bSensorsSupported) {
|
||||
// Use the right sensor in the combined Joy-Con pair
|
||||
if (!ctx->device->parent ||
|
||||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 200.0f);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 200.0f);
|
||||
}
|
||||
if (ctx->device->parent &&
|
||||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO_L, 200.0f);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL_L, 200.0f);
|
||||
}
|
||||
if (ctx->device->parent &&
|
||||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO_R, 200.0f);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL_R, 200.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetEnhancedMode(SDL_DriverSwitch_Context *ctx, bool bEnabled)
|
||||
{
|
||||
if (bEnabled) {
|
||||
SetEnhancedModeAvailable(ctx);
|
||||
}
|
||||
|
||||
if (bEnabled != ctx->m_bEnhancedMode) {
|
||||
ctx->m_bEnhancedMode = bEnabled;
|
||||
|
||||
UpdateInputMode(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetEnhancedReportHint(SDL_DriverSwitch_Context *ctx, HIDAPI_Switch_EnhancedReportHint eEnhancedReportHint)
|
||||
{
|
||||
switch (eEnhancedReportHint) {
|
||||
case SWITCH_ENHANCED_REPORT_HINT_OFF:
|
||||
SetEnhancedMode(ctx, false);
|
||||
break;
|
||||
case SWITCH_ENHANCED_REPORT_HINT_ON:
|
||||
SetEnhancedMode(ctx, true);
|
||||
break;
|
||||
case SWITCH_ENHANCED_REPORT_HINT_AUTO:
|
||||
SetEnhancedModeAvailable(ctx);
|
||||
break;
|
||||
}
|
||||
ctx->m_eEnhancedReportHint = eEnhancedReportHint;
|
||||
|
||||
UpdateInputMode(ctx);
|
||||
}
|
||||
|
||||
static void UpdateEnhancedModeOnEnhancedReport(SDL_DriverSwitch_Context *ctx)
|
||||
{
|
||||
if (ctx->m_eEnhancedReportHint == SWITCH_ENHANCED_REPORT_HINT_AUTO) {
|
||||
SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateEnhancedModeOnApplicationUsage(SDL_DriverSwitch_Context *ctx)
|
||||
{
|
||||
if (ctx->m_eEnhancedReportHint == SWITCH_ENHANCED_REPORT_HINT_AUTO) {
|
||||
SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_EnhancedReportsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata;
|
||||
|
||||
if (hint && SDL_strcasecmp(hint, "auto") == 0) {
|
||||
SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_AUTO);
|
||||
} else if (SDL_GetStringBoolean(hint, true)) {
|
||||
SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_ON);
|
||||
} else {
|
||||
SetEnhancedReportHint(ctx, SWITCH_ENHANCED_REPORT_HINT_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
static bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, bool enabled)
|
||||
{
|
||||
Uint8 imu_data = enabled ? 1 : 0;
|
||||
@@ -1432,35 +1546,16 @@ static bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joys
|
||||
ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_N64 &&
|
||||
ctx->m_eControllerType != k_eSwitchDeviceInfoControllerType_SEGA_Genesis) {
|
||||
if (LoadIMUCalibration(ctx)) {
|
||||
// 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_ACCEL, 200.0f);
|
||||
}
|
||||
if (device->parent &&
|
||||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_L, 200.0f);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 200.0f);
|
||||
}
|
||||
if (device->parent &&
|
||||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_R, 200.0f);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_R, 200.0f);
|
||||
}
|
||||
ctx->m_bSensorsSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetVibrationEnabled(ctx, 1)) {
|
||||
SDL_SetError("Couldn't enable vibration");
|
||||
return false;
|
||||
}
|
||||
// Enable vibration
|
||||
SetVibrationEnabled(ctx, 1);
|
||||
|
||||
// Set desired input mode
|
||||
if (!SetInputMode(ctx, GetDefaultInputMode(ctx))) {
|
||||
SDL_SetError("Couldn't set input mode");
|
||||
return false;
|
||||
}
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
|
||||
SDL_EnhancedReportsChanged, ctx);
|
||||
|
||||
// Start sending USB reports
|
||||
if (!device->is_bluetooth) {
|
||||
@@ -1694,20 +1789,20 @@ static bool HIDAPI_DriverSwitch_SendJoystickEffect(SDL_HIDAPI_Device *device, SD
|
||||
static bool HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
|
||||
{
|
||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
|
||||
Uint8 input_mode;
|
||||
|
||||
if (enabled) {
|
||||
input_mode = GetSensorInputMode(ctx);
|
||||
} else {
|
||||
input_mode = GetDefaultInputMode(ctx);
|
||||
UpdateEnhancedModeOnApplicationUsage(ctx);
|
||||
|
||||
if (!ctx->m_bSensorsSupported || (enabled && !ctx->m_bEnhancedMode)) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
SetInputMode(ctx, input_mode);
|
||||
|
||||
SetIMUEnabled(ctx, enabled);
|
||||
ctx->m_bReportSensors = enabled;
|
||||
ctx->m_unIMUSamples = 0;
|
||||
ctx->m_ulIMUSampleTimestampNS = SDL_GetTicksNS();
|
||||
|
||||
UpdateInputMode(ctx);
|
||||
SetIMUEnabled(ctx, enabled);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2585,6 +2680,9 @@ static bool HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
break;
|
||||
case k_eSwitchInputReportIDs_FullControllerState:
|
||||
case k_eSwitchInputReportIDs_FullControllerAndMcuState:
|
||||
// This is the extended report, we can enable sensors now in auto mode
|
||||
UpdateEnhancedModeOnEnhancedReport(ctx);
|
||||
|
||||
HandleFullControllerState(joystick, ctx, (SwitchStatePacket_t *)&ctx->m_rgucReadBuffer[1]);
|
||||
break;
|
||||
default:
|
||||
@@ -2652,6 +2750,9 @@ static void HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
}
|
||||
}
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_ENHANCED_REPORTS,
|
||||
SDL_EnhancedReportsChanged, ctx);
|
||||
|
||||
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
|
||||
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED,
|
||||
|
Reference in New Issue
Block a user