It takes 2 packets to stop audio haptics and start emulated rumble on the PS5 controller

This commit is contained in:
Sam Lantinga 2020-11-20 13:24:49 -08:00
parent 082558db33
commit 549010f2a0
2 changed files with 40 additions and 10 deletions

View File

@ -128,6 +128,7 @@ typedef struct
typedef enum { typedef enum {
k_EDS5EffectNone, k_EDS5EffectNone,
k_EDS5EffectRumbleStart,
k_EDS5EffectRumble, k_EDS5EffectRumble,
k_EDS5EffectLED, k_EDS5EffectLED,
k_EDS5EffectPadLights, k_EDS5EffectPadLights,
@ -342,6 +343,10 @@ HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
DS5EffectsState_t *effects; DS5EffectsState_t *effects;
Uint8 data[78]; Uint8 data[78];
int report_size, offset; int report_size, offset;
Uint8 *pending_data;
int *pending_size;
int maximum_size;
SDL_zero(data); SDL_zero(data);
@ -364,13 +369,16 @@ HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
effects->ucEnableBits1 |= 0x02; /* Disable audio haptics */ effects->ucEnableBits1 |= 0x02; /* Disable audio haptics */
/* Shift to reduce effective rumble strength to match Xbox controllers */ /* Shift to reduce effective rumble strength to match Xbox controllers */
effects->ucRumbleLeft = ctx->rumble_left >> 2; effects->ucRumbleLeft = ctx->rumble_left >> 1;
effects->ucRumbleRight = ctx->rumble_right >> 2; effects->ucRumbleRight = ctx->rumble_right >> 1;
} else { } else {
/* Leaving emulated rumble bits off will restore audio haptics */ /* Leaving emulated rumble bits off will restore audio haptics */
} }
switch (effect) { switch (effect) {
case k_EDS5EffectRumbleStart:
effects->ucEnableBits1 |= 0x02; /* Disable audio haptics */
break;
case k_EDS5EffectRumble: case k_EDS5EffectRumble:
/* Already handled above */ /* Already handled above */
break; break;
@ -409,10 +417,24 @@ HIDAPI_DriverPS5_UpdateEffects(SDL_HIDAPI_Device *device, EDS5Effect effect)
SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC)); SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
} }
if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) { if (SDL_HIDAPI_LockRumble() < 0) {
return SDL_SetError("Couldn't send rumble packet"); return -1;
} }
/* 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 0;
}
}
return SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size);
} }
static void 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; 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_left = (low_frequency_rumble >> 8);
ctx->rumble_right = (high_frequency_rumble >> 8); ctx->rumble_right = (high_frequency_rumble >> 8);

View File

@ -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_bool SDL_HIDAPI_GetPendingRumbleLocked(SDL_HIDAPI_Device *device, Uint8 **data, int **size, int *maximum_size)
{ {
SDL_HIDAPI_RumbleContext *ctx = &rumble_context; 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) { for (request = ctx->requests_tail; request; request = request->prev) {
if (request->device == device) { if (request->device == device) {
*data = request->data; found = request;
*size = &request->size;
*maximum_size = sizeof(request->data);
return SDL_TRUE;
} }
} }
if (found) {
*data = found->data;
*size = &found->size;
*maximum_size = sizeof(found->data);
return SDL_TRUE;
}
return SDL_FALSE; return SDL_FALSE;
} }