It takes 2 packets to stop audio haptics and start emulated rumble on the PS5 controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index afef4ef..152559d 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -128,6 +128,7 @@ typedef struct
typedef enum {
k_EDS5EffectNone,
+ k_EDS5EffectRumbleStart,
k_EDS5EffectRumble,
k_EDS5EffectLED,
k_EDS5EffectPadLights,
@@ -342,6 +343,10 @@ HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
DS5EffectsState_t *effects;
Uint8 data[78];
int report_size, offset;
+ Uint8 *pending_data;
+ int *pending_size;
+ int maximum_size;
+
SDL_zero(data);
@@ -364,13 +369,16 @@ HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
effects->ucEnableBits1 |= 0x02; /* Disable audio haptics */
/* Shift to reduce effective rumble strength to match Xbox controllers */
- effects->ucRumbleLeft = ctx->rumble_left >> 2;
- effects->ucRumbleRight = ctx->rumble_right >> 2;
+ effects->ucRumbleLeft = ctx->rumble_left >> 1;
+ effects->ucRumbleRight = ctx->rumble_right >> 1;
} else {
/* Leaving emulated rumble bits off will restore audio haptics */
}
switch (effect) {
+ case k_EDS5EffectRumbleStart:
+ effects->ucEnableBits1 |= 0x02; /* Disable audio haptics */
+ break;
case k_EDS5EffectRumble:
/* Already handled above */
break;
@@ -409,10 +417,24 @@ HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
}
- if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) {
- return SDL_SetError("Couldn't send rumble packet");
+ if (SDL_HIDAPI_LockRumble() < 0) {
+ return -1;
}
- return 0;
+
+ /* See if we can update an existing pending request */
+ if (SDL_HIDAPI_GetPendingRumbleLocked(device, &pending_data, &pending_size, &maximum_size)) {
+ DS5EffectsState_t *pending_effects = (DS5EffectsState_t *)&pending_data[offset];
+ if (report_size == *pending_size &&
+ effects->ucEnableBits1 == pending_effects->ucEnableBits1 &&
+ effects->ucEnableBits2 == pending_effects->ucEnableBits2) {
+ /* We're simply updating the data for this request */
+ SDL_memcpy(pending_data, data, report_size);
+ SDL_HIDAPI_UnlockRumble();
+ return 0;
+ }
+ }
+
+ return SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size);
}
static void
@@ -495,6 +517,10 @@ HIDAPI_DriverPS5_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
{
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
+ if (!ctx->rumble_left && !ctx->rumble_right) {
+ HIDAPI_DriverPS5_UpdateEffects(device, k_EDS5EffectRumbleStart);
+ }
+
ctx->rumble_left = (low_frequency_rumble >> 8);
ctx->rumble_right = (high_frequency_rumble >> 8);
diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.c b/src/joystick/hidapi/SDL_hidapi_rumble.c
index c0d932b..9aae15e 100644
--- a/src/joystick/hidapi/SDL_hidapi_rumble.c
+++ b/src/joystick/hidapi/SDL_hidapi_rumble.c
@@ -157,16 +157,20 @@ int SDL_HIDAPI_LockRumble(void)
SDL_bool SDL_HIDAPI_GetPendingRumbleLocked(SDL_HIDAPI_Device *device, Uint8 **data, int **size, int *maximum_size)
{
SDL_HIDAPI_RumbleContext *ctx = &rumble_context;
- SDL_HIDAPI_RumbleRequest *request;
+ SDL_HIDAPI_RumbleRequest *request, *found;
+ found = NULL;
for (request = ctx->requests_tail; request; request = request->prev) {
if (request->device == device) {
- *data = request->data;
- *size = &request->size;
- *maximum_size = sizeof(request->data);
- return SDL_TRUE;
+ found = request;
}
}
+ if (found) {
+ *data = found->data;
+ *size = &found->size;
+ *maximum_size = sizeof(found->data);
+ return SDL_TRUE;
+ }
return SDL_FALSE;
}