mirror of https://github.com/encounter/SDL.git
Make it possible to turn on PS4 rumble effects at runtime using the hint
This commit is contained in:
parent
390b2cf0d3
commit
a30adae567
|
@ -30,6 +30,7 @@
|
|||
#include "SDL_timer.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_gamecontroller.h"
|
||||
#include "../../SDL_hints_c.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "SDL_hidapijoystick_c.h"
|
||||
#include "SDL_hidapi_rumble.h"
|
||||
|
@ -119,11 +120,14 @@ typedef struct {
|
|||
} IMUCalibrationData;
|
||||
|
||||
typedef struct {
|
||||
SDL_HIDAPI_Device *device;
|
||||
SDL_Joystick *joystick;
|
||||
SDL_bool is_dongle;
|
||||
SDL_bool is_bluetooth;
|
||||
SDL_bool official_controller;
|
||||
SDL_bool audio_supported;
|
||||
SDL_bool effects_supported;
|
||||
SDL_bool enhanced_mode;
|
||||
SDL_bool report_sensors;
|
||||
SDL_bool hardware_calibration;
|
||||
IMUCalibrationData calibration[6];
|
||||
|
@ -387,6 +391,10 @@ HIDAPI_DriverPS4_UpdateEffects(SDL_HIDAPI_Device *device)
|
|||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
SDL_zero(data);
|
||||
|
||||
if (ctx->is_bluetooth) {
|
||||
|
@ -432,6 +440,32 @@ HIDAPI_DriverPS4_UpdateEffects(SDL_HIDAPI_Device *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverPS4_SetEnhancedMode(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
ctx->enhanced_mode = SDL_TRUE;
|
||||
|
||||
SDL_PrivateJoystickAddTouchpad(joystick, 2);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL);
|
||||
|
||||
HIDAPI_DriverPS4_UpdateEffects(device);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_PS4RumbleHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_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_DriverPS4_SetEnhancedMode(ctx->device, ctx->joystick);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
|
||||
{
|
||||
|
@ -451,12 +485,15 @@ static SDL_bool
|
|||
HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx;
|
||||
SDL_bool enhanced_mode = SDL_FALSE;
|
||||
|
||||
ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
SDL_OutOfMemory();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
ctx->device = device;
|
||||
ctx->joystick = joystick;
|
||||
|
||||
device->dev = hid_open_path(device->path, 0);
|
||||
if (!device->dev) {
|
||||
|
@ -471,6 +508,7 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
|||
if (ctx->is_dongle) {
|
||||
ctx->is_bluetooth = SDL_FALSE;
|
||||
ctx->official_controller = SDL_TRUE;
|
||||
enhanced_mode = SDL_TRUE;
|
||||
} else if (device->vendor_id == USB_VENDOR_SONY) {
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
int size;
|
||||
|
@ -484,13 +522,30 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
|||
data[6], data[5], data[4], data[3], data[2], data[1]);
|
||||
joystick->serial = SDL_strdup(serial);
|
||||
ctx->is_bluetooth = SDL_FALSE;
|
||||
enhanced_mode = SDL_TRUE;
|
||||
} else {
|
||||
ctx->is_bluetooth = SDL_TRUE;
|
||||
|
||||
/* Read a report to see if we're in enhanced mode */
|
||||
size = hid_read_timeout(device->dev, data, sizeof(data), 16);
|
||||
#ifdef DEBUG_PS4_PROTOCOL
|
||||
if (size > 0) {
|
||||
HIDAPI_DumpPacket("PS4 first packet: size = %d", data, size);
|
||||
} else {
|
||||
SDL_Log("PS4 first packet: size = %d\n", size);
|
||||
}
|
||||
#endif
|
||||
if (size > 0 &&
|
||||
data[0] >= k_EPS4ReportIdBluetoothState1 &&
|
||||
data[0] <= k_EPS4ReportIdBluetoothState9) {
|
||||
enhanced_mode = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
ctx->official_controller = SDL_TRUE;
|
||||
} else {
|
||||
/* Third party controllers appear to all be wired */
|
||||
ctx->is_bluetooth = SDL_FALSE;
|
||||
enhanced_mode = SDL_TRUE;
|
||||
}
|
||||
#ifdef DEBUG_PS4
|
||||
SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", ctx->is_bluetooth ? "TRUE" : "FALSE");
|
||||
|
@ -503,28 +558,42 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
|||
}
|
||||
|
||||
if (HIDAPI_DriverPS4_CanRumble(device->vendor_id, device->product_id)) {
|
||||
if (ctx->is_bluetooth) {
|
||||
ctx->effects_supported = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, SDL_FALSE);
|
||||
} else {
|
||||
ctx->effects_supported = SDL_TRUE;
|
||||
ctx->effects_supported = SDL_TRUE;
|
||||
}
|
||||
|
||||
if (!joystick->serial && device->serial && SDL_strlen(device->serial) == 12) {
|
||||
int i, j;
|
||||
char serial[18];
|
||||
|
||||
j = -1;
|
||||
for (i = 0; i < 12; i += 2) {
|
||||
j += 1;
|
||||
SDL_memcpy(&serial[j], &device->serial[i], 2);
|
||||
j += 2;
|
||||
serial[j] = '-';
|
||||
}
|
||||
serial[j] = '\0';
|
||||
|
||||
joystick->serial = SDL_strdup(serial);
|
||||
}
|
||||
|
||||
/* Initialize player index (needed for setting LEDs) */
|
||||
ctx->player_index = SDL_JoystickGetPlayerIndex(joystick);
|
||||
|
||||
/* Initialize LED and effect state */
|
||||
HIDAPI_DriverPS4_UpdateEffects(device);
|
||||
|
||||
/* Initialize the joystick capabilities */
|
||||
/* Initialize the joystick capabilities
|
||||
*
|
||||
* We can't dynamically add the touchpad button, so always report it here
|
||||
*/
|
||||
joystick->nbuttons = 16;
|
||||
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
|
||||
SDL_PrivateJoystickAddTouchpad(joystick, 2);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL);
|
||||
joystick->epowerlevel = ctx->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
|
||||
|
||||
if (enhanced_mode) {
|
||||
HIDAPI_DriverPS4_SetEnhancedMode(device, joystick);
|
||||
} else {
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE,
|
||||
SDL_PS4RumbleHintChanged, ctx);
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
|
@ -569,6 +638,10 @@ HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti
|
|||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
|
||||
|
||||
if (!ctx->enhanced_mode) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
HIDAPI_DriverPS4_LoadCalibrationData(device);
|
||||
}
|
||||
|
@ -729,7 +802,7 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
|
||||
SDL_Joystick *joystick = NULL;
|
||||
Uint8 data[USB_PACKET_LENGTH];
|
||||
Uint8 data[USB_PACKET_LENGTH*2];
|
||||
int size;
|
||||
|
||||
if (device->num_joysticks > 0) {
|
||||
|
@ -756,6 +829,10 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
case k_EPS4ReportIdBluetoothState7:
|
||||
case k_EPS4ReportIdBluetoothState8:
|
||||
case k_EPS4ReportIdBluetoothState9:
|
||||
if (!ctx->enhanced_mode) {
|
||||
/* This is the extended report, we can enable effects now */
|
||||
HIDAPI_DriverPS4_SetEnhancedMode(device, joystick);
|
||||
}
|
||||
/* Bluetooth state packets have two additional bytes at the beginning, the first notes if HID is present */
|
||||
if (data[1] & 0x80) {
|
||||
HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t*)&data[3]);
|
||||
|
@ -779,6 +856,11 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
static void
|
||||
HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE,
|
||||
SDL_PS4RumbleHintChanged, ctx);
|
||||
|
||||
hid_close(device->dev);
|
||||
device->dev = NULL;
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ typedef struct {
|
|||
SDL_HIDAPI_Device *device;
|
||||
SDL_Joystick *joystick;
|
||||
SDL_bool is_bluetooth;
|
||||
SDL_bool effects_supported;
|
||||
SDL_bool enhanced_mode;
|
||||
SDL_bool report_sensors;
|
||||
SDL_bool hardware_calibration;
|
||||
IMUCalibrationData calibration[6];
|
||||
|
@ -382,7 +382,7 @@ HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
|
|||
int *pending_size;
|
||||
int maximum_size;
|
||||
|
||||
if (!ctx->effects_supported) {
|
||||
if (!ctx->enhanced_mode) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
|
@ -508,12 +508,12 @@ HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device)
|
|||
}
|
||||
|
||||
static void
|
||||
HIDAPI_DriverPS5_SetEffectsSupported(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
|
||||
if (!ctx->effects_supported) {
|
||||
ctx->effects_supported = SDL_TRUE;
|
||||
if (!ctx->enhanced_mode) {
|
||||
ctx->enhanced_mode = SDL_TRUE;
|
||||
|
||||
SDL_PrivateJoystickAddTouchpad(joystick, 2);
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO);
|
||||
|
@ -530,7 +530,7 @@ static void SDLCALL SDL_PS5RumbleHintChanged(void *userdata, const char *name, c
|
|||
|
||||
/* 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_SetEffectsSupported(ctx->device, ctx->joystick);
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(ctx->device, ctx->joystick);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,7 +556,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
|||
SDL_DriverPS5_Context *ctx;
|
||||
Uint8 data[USB_PACKET_LENGTH*2];
|
||||
int size;
|
||||
SDL_bool effects_supported = SDL_FALSE;
|
||||
SDL_bool enhanced_mode = SDL_FALSE;
|
||||
|
||||
ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
|
@ -587,18 +587,18 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
|||
if (size == 64) {
|
||||
/* Connected over USB */
|
||||
ctx->is_bluetooth = SDL_FALSE;
|
||||
effects_supported = SDL_TRUE;
|
||||
enhanced_mode = SDL_TRUE;
|
||||
} else if (size > 0 && data[0] == k_EPS5ReportIdBluetoothEffects) {
|
||||
/* Connected over Bluetooth, using enhanced reports */
|
||||
ctx->is_bluetooth = SDL_TRUE;
|
||||
effects_supported = SDL_TRUE;
|
||||
enhanced_mode = SDL_TRUE;
|
||||
} else {
|
||||
/* Connected over Bluetooth, using simple reports (DirectInput enabled) */
|
||||
ctx->is_bluetooth = SDL_TRUE;
|
||||
effects_supported = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, SDL_FALSE);
|
||||
enhanced_mode = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, SDL_FALSE);
|
||||
}
|
||||
|
||||
if (effects_supported) {
|
||||
if (enhanced_mode) {
|
||||
/* Read the serial number (Bluetooth address in reverse byte order)
|
||||
This will also enable enhanced reports over Bluetooth
|
||||
*/
|
||||
|
@ -636,9 +636,10 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
|||
*/
|
||||
joystick->nbuttons = 17;
|
||||
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
||||
joystick->epowerlevel = ctx->is_bluetooth ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
|
||||
|
||||
if (effects_supported) {
|
||||
HIDAPI_DriverPS5_SetEffectsSupported(device, joystick);
|
||||
if (enhanced_mode) {
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
|
||||
} else {
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE,
|
||||
SDL_PS5RumbleHintChanged, ctx);
|
||||
|
@ -691,7 +692,7 @@ HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti
|
|||
{
|
||||
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
|
||||
|
||||
if (!ctx->effects_supported) {
|
||||
if (!ctx->enhanced_mode) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
|
@ -969,9 +970,9 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
}
|
||||
break;
|
||||
case k_EPS5ReportIdBluetoothState:
|
||||
if (!ctx->effects_supported) {
|
||||
if (!ctx->enhanced_mode) {
|
||||
/* This is the extended report, we can enable effects now */
|
||||
HIDAPI_DriverPS5_SetEffectsSupported(device, joystick);
|
||||
HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
|
||||
}
|
||||
if (ctx->led_reset_state == k_EDS5LEDResetStatePending) {
|
||||
HIDAPI_DriverPS5_CheckPendingLEDReset(device);
|
||||
|
|
Loading…
Reference in New Issue