mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-04 00:46:25 +00:00
Added an "auto" mode for PS4 and PS5 controller rumble hints
This allows the controllers to report that they have sensors and enhanced capabilities, but not actually switch into enhanced mode (breaking DirectInput) unless the application tries to use them.
This commit is contained in:
@@ -30,10 +30,14 @@
|
||||
#ifdef SDL_JOYSTICK_HIDAPI_PS5
|
||||
|
||||
/* Define this if you want to log all packets from the controller */
|
||||
/*#define DEBUG_PS5_PROTOCOL*/
|
||||
#if 0
|
||||
#define DEBUG_PS5_PROTOCOL
|
||||
#endif
|
||||
|
||||
/* Define this if you want to log calibration data */
|
||||
/*#define DEBUG_PS5_CALIBRATION*/
|
||||
#if 0
|
||||
#define DEBUG_PS5_CALIBRATION
|
||||
#endif
|
||||
|
||||
#define GYRO_RES_PER_DEGREE 1024.0f
|
||||
#define ACCEL_RES_PER_G 8192.0f
|
||||
@@ -219,8 +223,10 @@ typedef struct
|
||||
SDL_bool touchpad_supported;
|
||||
SDL_bool effects_supported;
|
||||
SDL_bool enhanced_mode;
|
||||
SDL_bool enhanced_mode_available;
|
||||
SDL_bool report_sensors;
|
||||
SDL_bool report_touchpad;
|
||||
SDL_bool report_battery;
|
||||
SDL_bool hardware_calibration;
|
||||
IMUCalibrationData calibration[6];
|
||||
Uint16 firmware_version;
|
||||
@@ -388,13 +394,17 @@ static SDL_bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
|
||||
ctx->enhanced_mode = SDL_TRUE;
|
||||
} else {
|
||||
/* Connected over Bluetooth, using simple reports (DirectInput enabled) */
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
ctx->enhanced_mode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE,
|
||||
SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, SDL_FALSE));
|
||||
const char *hint = SDL_GetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE);
|
||||
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 && SDL_strcasecmp(hint, "auto") != 0) {
|
||||
ctx->enhanced_mode = SDL_GetStringBoolean(hint, SDL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->enhanced_mode) {
|
||||
@@ -630,14 +640,8 @@ static int HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, int effect_
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
DS5EffectsState_t effects;
|
||||
|
||||
if (!ctx->enhanced_mode || !ctx->effects_supported) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
SDL_zero(effects);
|
||||
|
||||
/* Make sure the Bluetooth connection sequence has completed before sending LED color change */
|
||||
if (device->is_bluetooth &&
|
||||
if (device->is_bluetooth && ctx->enhanced_mode &&
|
||||
(effect_mask & (k_EDS5EffectLED | k_EDS5EffectPadLights)) != 0) {
|
||||
if (ctx->led_reset_state != k_EDS5LEDResetStateComplete) {
|
||||
ctx->led_reset_state = k_EDS5LEDResetStatePending;
|
||||
@@ -645,6 +649,8 @@ static int HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, int effect_
|
||||
}
|
||||
}
|
||||
|
||||
SDL_zero(effects);
|
||||
|
||||
if (ctx->vibration_supported) {
|
||||
if (ctx->rumble_left || ctx->rumble_right) {
|
||||
if (ctx->firmware_version < 0x0224) {
|
||||
@@ -763,33 +769,52 @@ static void HIDAPI_DriverPS5_TickleBluetooth(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS5_SetEnhancedMode(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx)
|
||||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
if (!ctx->effects_supported) {
|
||||
/* We shouldn't be sending any packets to the controller */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
ctx->enhanced_mode_available = SDL_TRUE;
|
||||
|
||||
if (ctx->touchpad_supported) {
|
||||
SDL_PrivateJoystickAddTouchpad(ctx->joystick, 2);
|
||||
}
|
||||
if (ctx->sensors_supported) {
|
||||
if (ctx->device->is_bluetooth) {
|
||||
/* Bluetooth sensor update rate appears to be 1000 Hz */
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 1000.0f);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 1000.0f);
|
||||
} else {
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 250.0f);
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 250.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverPS5_SetEnhancedMode(SDL_DriverPS5_Context *ctx)
|
||||
{
|
||||
if (!ctx->enhanced_mode_available) {
|
||||
HIDAPI_DriverPS5_SetEnhancedModeAvailable(ctx);
|
||||
}
|
||||
|
||||
if (!ctx->enhanced_mode && ctx->enhanced_mode_available) {
|
||||
ctx->enhanced_mode = SDL_TRUE;
|
||||
|
||||
if (ctx->touchpad_supported) {
|
||||
SDL_PrivateJoystickAddTouchpad(joystick, 2);
|
||||
ctx->report_touchpad = SDL_TRUE;
|
||||
}
|
||||
if (ctx->sensors_supported) {
|
||||
if (device->is_bluetooth) {
|
||||
/* Bluetooth sensor update rate appears to be 1000 Hz */
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 1000.0f);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 1000.0f);
|
||||
} else {
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 250.0f);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 250.0f);
|
||||
}
|
||||
|
||||
if (ctx->device->is_bluetooth) {
|
||||
ctx->report_battery = SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Switch into enhanced report mode */
|
||||
HIDAPI_DriverPS5_UpdateEffects(device, 0);
|
||||
HIDAPI_DriverPS5_UpdateEffects(ctx->device, 0);
|
||||
|
||||
/* Update the light effects */
|
||||
HIDAPI_DriverPS5_UpdateEffects(device, (k_EDS5EffectLED | k_EDS5EffectPadLights));
|
||||
HIDAPI_DriverPS5_UpdateEffects(ctx->device, (k_EDS5EffectLED | k_EDS5EffectPadLights));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -797,9 +822,12 @@ static void SDLCALL SDL_PS5RumbleHintChanged(void *userdata, const char *name, c
|
||||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)userdata;
|
||||
|
||||
/* This is a one-way trip, you can't switch the controller back to simple report mode */
|
||||
if (SDL_GetStringBoolean(hint, SDL_FALSE)) {
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx->device, ctx->joystick);
|
||||
if (SDL_strcasecmp(hint, "auto") == 0) {
|
||||
/* Mark the controller as enhanced mode capable, but wait for API calls to enable it */
|
||||
HIDAPI_DriverPS5_SetEnhancedModeAvailable(ctx);
|
||||
} else if (SDL_GetStringBoolean(hint, SDL_FALSE)) {
|
||||
/* This is a one-way trip, you can't switch the controller back to simple report mode */
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -858,13 +886,18 @@ static SDL_bool HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
joystick->nbuttons = 15;
|
||||
}
|
||||
joystick->naxes = SDL_GAMEPAD_AXIS_MAX;
|
||||
joystick->epowerlevel = device->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
|
||||
if (device->is_bluetooth) {
|
||||
/* We'll update this once we're in enhanced mode */
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
|
||||
} else {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
}
|
||||
joystick->firmware_version = ctx->firmware_version;
|
||||
|
||||
if (ctx->enhanced_mode) {
|
||||
/* Force initialization when opening the joystick */
|
||||
ctx->enhanced_mode = SDL_FALSE;
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx);
|
||||
} else {
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE,
|
||||
SDL_PS5RumbleHintChanged, ctx);
|
||||
@@ -903,7 +936,7 @@ static Uint32 HIDAPI_DriverPS5_GetJoystickCapabilities(SDL_HIDAPI_Device *device
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
Uint32 result = 0;
|
||||
|
||||
if (ctx->enhanced_mode) {
|
||||
if (ctx->enhanced_mode_available) {
|
||||
if (ctx->lightbar_supported) {
|
||||
result |= SDL_JOYCAP_LED;
|
||||
}
|
||||
@@ -940,12 +973,12 @@ static int HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Jo
|
||||
int *pending_size;
|
||||
int maximum_size;
|
||||
|
||||
if (!ctx->effects_supported) {
|
||||
if (!ctx->enhanced_mode_available) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx);
|
||||
}
|
||||
|
||||
SDL_zeroa(data);
|
||||
@@ -1003,11 +1036,12 @@ static int HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device,
|
||||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
if (!ctx->enhanced_mode_available) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx);
|
||||
HIDAPI_DriverPS5_LoadCalibrationData(device);
|
||||
}
|
||||
ctx->report_sensors = enabled;
|
||||
@@ -1274,13 +1308,7 @@ static void HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
|
||||
SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, touchpad_state, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_state ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
/* A check of packet->ucBatteryLevel & 0x10 should work as a check for BT vs USB but doesn't
|
||||
* seem to always work. Possibly related to being 100% charged?
|
||||
*/
|
||||
if (!ctx->device->is_bluetooth) {
|
||||
/* 0x20 set means fully charged */
|
||||
SDL_SendJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
|
||||
} else {
|
||||
if (ctx->report_battery) {
|
||||
/* Battery level ranges from 0 to 10 */
|
||||
int level = (packet->ucBatteryLevel & 0xF);
|
||||
if (level == 0) {
|
||||
@@ -1396,7 +1424,7 @@ static SDL_bool HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
case k_EPS5ReportIdBluetoothState:
|
||||
if (!ctx->enhanced_mode) {
|
||||
/* This is the extended report, we can enable effects now */
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx);
|
||||
}
|
||||
HIDAPI_DriverPS5_HandleStatePacketCommon(joystick, device->dev, ctx, (PS5StatePacketCommon_t *)&data[2]);
|
||||
if (ctx->use_alternate_report) {
|
||||
|
Reference in New Issue
Block a user