mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-10 02:55:36 +00:00
Add support for whammy and tilt on PS4/5 guitars
PS4/5 controllers put device specific data into a specific region in the report, so we have to extract it separately. No known guitars use the right stick on the guitar, so to keep things working similarly to PS3, i have opted to map whammy and tilt the same way as the PS3 rb guitars.
This commit is contained in:
@@ -98,6 +98,7 @@ typedef struct
|
||||
Uint8 rgucTouchpadData1[3];
|
||||
Uint8 ucTouchpadCounter2;
|
||||
Uint8 rgucTouchpadData2[3];
|
||||
Uint8 rgucDeviceSpecific[12];
|
||||
} PS4StatePacket_t;
|
||||
|
||||
typedef struct
|
||||
@@ -146,6 +147,9 @@ typedef struct
|
||||
bool vibration_supported;
|
||||
bool touchpad_supported;
|
||||
bool effects_supported;
|
||||
bool guitar_whammy_supported;
|
||||
bool guitar_tilt_supported;
|
||||
bool guitar_effects_selector_supported;
|
||||
HIDAPI_PS4_EnhancedReportHint enhanced_report_hint;
|
||||
bool enhanced_reports;
|
||||
bool enhanced_mode;
|
||||
@@ -347,6 +351,7 @@ static bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
|
||||
if (size == 48 && data[2] == 0x27) {
|
||||
Uint8 capabilities = data[4];
|
||||
Uint8 device_type = data[5];
|
||||
Uint8 device_specific_capabilities = data[24];
|
||||
Uint16 gyro_numerator = LOAD16(data[10], data[11]);
|
||||
Uint16 gyro_denominator = LOAD16(data[12], data[13]);
|
||||
Uint16 accel_numerator = LOAD16(data[14], data[15]);
|
||||
@@ -374,6 +379,15 @@ static bool HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
|
||||
break;
|
||||
case 0x01:
|
||||
joystick_type = SDL_JOYSTICK_TYPE_GUITAR;
|
||||
if (device_specific_capabilities & 0x01) {
|
||||
ctx->guitar_effects_selector_supported = true;
|
||||
}
|
||||
if (device_specific_capabilities & 0x02) {
|
||||
ctx->guitar_tilt_supported = true;
|
||||
}
|
||||
if (device_specific_capabilities & 0x04) {
|
||||
ctx->guitar_whammy_supported = true;
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT;
|
||||
@@ -716,6 +730,10 @@ static void HIDAPI_DriverPS4_SetEnhancedModeAvailable(SDL_DriverPS4_Context *ctx
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, (float)(1000 / ctx->report_interval));
|
||||
}
|
||||
|
||||
if (ctx->guitar_tilt_supported) {
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, (float)(1000 / ctx->report_interval));
|
||||
}
|
||||
|
||||
if (ctx->official_controller) {
|
||||
ctx->report_battery = true;
|
||||
}
|
||||
@@ -983,7 +1001,7 @@ static bool HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device
|
||||
|
||||
HIDAPI_DriverPS4_UpdateEnhancedModeOnApplicationUsage(ctx);
|
||||
|
||||
if (!ctx->sensors_supported || (enabled && !ctx->enhanced_mode)) {
|
||||
if ((!ctx->sensors_supported || (enabled && !ctx->enhanced_mode)) && !ctx->guitar_tilt_supported) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
@@ -1154,6 +1172,30 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
|
||||
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, data, 3);
|
||||
}
|
||||
|
||||
if (ctx->guitar_whammy_supported) {
|
||||
axis = ((int)packet->rgucDeviceSpecific[1] * 257) - 32768;
|
||||
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
|
||||
}
|
||||
|
||||
if (ctx->guitar_effects_selector_supported) {
|
||||
// Align pickup selector mappings with PS3 instruments
|
||||
static const Sint16 effects_mappings[] = {24576, 11008, -1792, -13568, -26880};
|
||||
if (packet->rgucDeviceSpecific[0] < SDL_arraysize(effects_mappings)) {
|
||||
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, effects_mappings[packet->rgucDeviceSpecific[0]]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->guitar_tilt_supported) {
|
||||
float sensor_data[3];
|
||||
sensor_data[0] = ((float)packet->rgucDeviceSpecific[2] / 255) * SDL_STANDARD_GRAVITY;
|
||||
sensor_data[1] = 0;
|
||||
sensor_data[2] = 0;
|
||||
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data));
|
||||
|
||||
// Align tilt mappings with PS3 instruments
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, packet->rgucDeviceSpecific[2] > 0xF0);
|
||||
}
|
||||
|
||||
SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
|
||||
}
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ typedef struct
|
||||
Uint8 rgucTouchpadData1[3]; // 32 - X/Y, 12 bits per axis
|
||||
Uint8 ucTouchpadCounter2; // 35 - high bit clear + counter
|
||||
Uint8 rgucTouchpadData2[3]; // 36 - X/Y, 12 bits per axis
|
||||
Uint8 rgucDeviceSpecific[8]; // 40
|
||||
|
||||
// There's more unknown data at the end, and a 32-bit CRC on Bluetooth
|
||||
} PS5StatePacketAlt_t;
|
||||
@@ -232,6 +233,9 @@ typedef struct
|
||||
bool playerled_supported;
|
||||
bool touchpad_supported;
|
||||
bool effects_supported;
|
||||
bool guitar_whammy_supported;
|
||||
bool guitar_tilt_supported;
|
||||
bool guitar_effects_selector_supported;
|
||||
HIDAPI_PS5_EnhancedReportHint enhanced_report_hint;
|
||||
bool enhanced_reports;
|
||||
bool enhanced_mode;
|
||||
@@ -448,6 +452,7 @@ static bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
|
||||
if (size == 48 && data[2] == 0x28) {
|
||||
Uint8 capabilities = data[4];
|
||||
Uint8 capabilities2 = data[20];
|
||||
Uint8 device_specific_capabilities = data[24];
|
||||
Uint8 device_type = data[5];
|
||||
|
||||
#ifdef DEBUG_PS5_PROTOCOL
|
||||
@@ -475,6 +480,15 @@ static bool HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
|
||||
break;
|
||||
case 0x01:
|
||||
joystick_type = SDL_JOYSTICK_TYPE_GUITAR;
|
||||
if (device_specific_capabilities & 0x01) {
|
||||
ctx->guitar_effects_selector_supported = true;
|
||||
}
|
||||
if (device_specific_capabilities & 0x02) {
|
||||
ctx->guitar_tilt_supported = true;
|
||||
}
|
||||
if (device_specific_capabilities & 0x04) {
|
||||
ctx->guitar_whammy_supported = true;
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
joystick_type = SDL_JOYSTICK_TYPE_DRUM_KIT;
|
||||
@@ -836,6 +850,11 @@ static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, update_rate);
|
||||
}
|
||||
|
||||
if (ctx->guitar_tilt_supported) {
|
||||
float update_rate = 250.0f;
|
||||
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, update_rate);
|
||||
}
|
||||
|
||||
ctx->report_battery = true;
|
||||
|
||||
HIDAPI_UpdateDeviceProperties(ctx->device);
|
||||
@@ -1127,7 +1146,7 @@ static bool HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device
|
||||
|
||||
HIDAPI_DriverPS5_UpdateEnhancedModeOnApplicationUsage(ctx);
|
||||
|
||||
if (!ctx->sensors_supported || (enabled && !ctx->enhanced_mode)) {
|
||||
if ((!ctx->sensors_supported || (enabled && !ctx->enhanced_mode)) && !ctx->guitar_tilt_supported) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
@@ -1432,6 +1451,7 @@ static void HIDAPI_DriverPS5_HandleStatePacketAlt(SDL_Joystick *joystick, SDL_hi
|
||||
static const float TOUCHPAD_SCALEY = 9.34579439e-4f; // 1.0f / 1070
|
||||
bool touchpad_down;
|
||||
int touchpad_x, touchpad_y;
|
||||
Sint16 axis;
|
||||
|
||||
if (ctx->report_touchpad) {
|
||||
touchpad_down = ((packet->ucTouchpadCounter1 & 0x80) == 0);
|
||||
@@ -1447,6 +1467,30 @@ static void HIDAPI_DriverPS5_HandleStatePacketAlt(SDL_Joystick *joystick, SDL_hi
|
||||
|
||||
HIDAPI_DriverPS5_HandleStatePacketCommon(joystick, dev, ctx, (PS5StatePacketCommon_t *)packet, timestamp);
|
||||
|
||||
if (ctx->guitar_whammy_supported) {
|
||||
axis = ((int)packet->rgucDeviceSpecific[1] * 257) - 32768;
|
||||
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
|
||||
}
|
||||
|
||||
if (ctx->guitar_effects_selector_supported) {
|
||||
// Align pickup selector mappings with PS3 instruments
|
||||
static const Sint16 effects_mappings[] = {24576, 11008, -1792, -13568, -26880};
|
||||
if (packet->rgucDeviceSpecific[0] < SDL_arraysize(effects_mappings)) {
|
||||
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, effects_mappings[packet->rgucDeviceSpecific[0]]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->guitar_tilt_supported) {
|
||||
float sensor_data[3];
|
||||
sensor_data[0] = ((float)packet->rgucDeviceSpecific[2] / 255) * SDL_STANDARD_GRAVITY;
|
||||
sensor_data[1] = 0;
|
||||
sensor_data[2] = 0;
|
||||
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data));
|
||||
|
||||
// Align tilt mappings with PS3 instruments
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, packet->rgucDeviceSpecific[2] > 0xF0);
|
||||
}
|
||||
|
||||
SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
|
||||
}
|
||||
|
||||
|
||||
@@ -174,6 +174,8 @@ bool HIDAPI_SupportsPlaystationDetection(Uint16 vendor, Uint16 product)
|
||||
}
|
||||
|
||||
switch (vendor) {
|
||||
case USB_VENDOR_CRKD:
|
||||
return true;
|
||||
case USB_VENDOR_DRAGONRISE:
|
||||
return true;
|
||||
case USB_VENDOR_HORI:
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#define USB_VENDOR_ASTRO 0x9886
|
||||
#define USB_VENDOR_ASUS 0x0b05
|
||||
#define USB_VENDOR_BACKBONE 0x358a
|
||||
#define USB_VENDOR_CRKD 0x3651
|
||||
#define USB_VENDOR_GAMESIR 0x3537
|
||||
#define USB_VENDOR_DRAGONRISE 0x0079
|
||||
#define USB_VENDOR_FLYDIGI_V1 0x04b4
|
||||
|
||||
Reference in New Issue
Block a user