mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-05 23:44:05 +02:00
Added enhanced support for the Flydigi Vader 5 Pro controller
This commit is contained in:
@@ -445,6 +445,7 @@ char *SDL_CreateDeviceName(Uint16 vendor, Uint16 product, const char *vendor_nam
|
||||
const char *prefix;
|
||||
const char *replacement;
|
||||
} replacements[] = {
|
||||
{ "(Standard system devices) ", "" },
|
||||
{ "8BitDo Tech Ltd", "8BitDo" },
|
||||
{ "ASTRO Gaming", "ASTRO" },
|
||||
{ "Bensussen Deutsch & Associates,Inc.(BDA)", "BDA" },
|
||||
|
||||
@@ -1258,6 +1258,10 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
|
||||
if (guid.data[15] >= SDL_FLYDIGI_VADER2) {
|
||||
// Vader series of controllers have C/Z buttons
|
||||
SDL_strlcat(mapping_string, "misc2:b15,misc3:b16,", sizeof(mapping_string));
|
||||
if (guid.data[15] == SDL_FLYDIGI_VADER5_PRO) {
|
||||
// Vader 5 has additional shoulder macro buttons and a circle button
|
||||
SDL_strlcat(mapping_string, "misc4:b17,misc5:b18,misc6:b19", sizeof(mapping_string));
|
||||
}
|
||||
} else if (guid.data[15] == SDL_FLYDIGI_APEX5) {
|
||||
// Apex 5 has additional shoulder macro buttons
|
||||
SDL_strlcat(mapping_string, "misc2:b15,misc3:b16,", sizeof(mapping_string));
|
||||
|
||||
@@ -53,6 +53,9 @@ enum
|
||||
/* Rate of IMU Sensor Packets over wired connection observed in testcontroller at 500hz */
|
||||
#define SENSOR_INTERVAL_VADER4_PRO_WIRED_RATE_HZ 500
|
||||
#define SENSOR_INTERVAL_VADER4_PRO_WIRED_NS (SDL_NS_PER_SECOND / SENSOR_INTERVAL_VADER4_PRO_WIRED_RATE_HZ)
|
||||
/* Rate of IMU Sensor Packets over wired connection observed in testcontroller at 500hz */
|
||||
#define SENSOR_INTERVAL_VADER5_PRO_RATE_HZ 500
|
||||
#define SENSOR_INTERVAL_VADER5_PRO_NS (SDL_NS_PER_SECOND / SENSOR_INTERVAL_VADER5_PRO_RATE_HZ)
|
||||
|
||||
/* Rate of IMU Sensor Packets over wireless dongle observed in testcontroller at 295hz */
|
||||
#define SENSOR_INTERVAL_APEX5_DONGLE_RATE_HZ 295
|
||||
@@ -86,6 +89,7 @@ typedef struct
|
||||
bool available;
|
||||
bool has_cz;
|
||||
bool has_lmrm;
|
||||
bool has_circle;
|
||||
bool wireless;
|
||||
bool sensors_supported;
|
||||
bool sensors_enabled;
|
||||
@@ -117,7 +121,19 @@ static bool HIDAPI_DriverFlydigi_IsEnabled(void)
|
||||
|
||||
static bool HIDAPI_DriverFlydigi_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
|
||||
{
|
||||
return SDL_IsJoystickFlydigiController(vendor_id, product_id) && interface_number == 2;
|
||||
if (SDL_IsJoystickFlydigiController(vendor_id, product_id)) {
|
||||
if (vendor_id == USB_VENDOR_FLYDIGI_V1) {
|
||||
if (interface_number == 2) {
|
||||
// Early controllers have their custom protocol on interface 2
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Newer controllers have their custom protocol on interface 1 or 2, but
|
||||
// only expose one HID interface, so we'll accept any interface we see.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool HIDAPI_DriverFlydigi_InitControllerV1(SDL_HIDAPI_Device *device)
|
||||
@@ -217,8 +233,15 @@ static bool GetReply(SDL_HIDAPI_Device* device, Uint8 command, Uint8* data, size
|
||||
HIDAPI_DumpPacket("Flydigi packet: size = %d", data, size);
|
||||
#endif
|
||||
|
||||
if (size == 32 && data[1] == FLYDIGI_V2_MAGIC1 && data[2] == FLYDIGI_V2_MAGIC2 && data[3] == command) {
|
||||
return true;
|
||||
if (size == 32) {
|
||||
if (data[1] == FLYDIGI_V2_MAGIC1 && data[2] == FLYDIGI_V2_MAGIC2) {
|
||||
// Skip the report ID
|
||||
SDL_memmove(&data[0], &data[1], size - 1);
|
||||
data[size - 1] = 0;
|
||||
}
|
||||
if (data[0] == FLYDIGI_V2_MAGIC1 && data[1] == FLYDIGI_V2_MAGIC2 && data[2] == command) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -264,12 +287,27 @@ static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
|
||||
// Check the firmware version
|
||||
ctx->firmware_version = LOAD16(data[17], data[16]);
|
||||
if (ctx->firmware_version < 0x7031) {
|
||||
Uint16 min_firmware_version;
|
||||
ctx->firmware_version = LOAD16(data[16], data[15]);
|
||||
switch (device->product_id) {
|
||||
case USB_PRODUCT_FLYDIGI_V2_APEX:
|
||||
// Minimum supported firmware version, Apex 5
|
||||
min_firmware_version = 0x7031;
|
||||
break;
|
||||
case USB_PRODUCT_FLYDIGI_V2_VADER:
|
||||
// Minimum supported firmware version, Vader 5 Pro
|
||||
min_firmware_version = 0x7141;
|
||||
break;
|
||||
default:
|
||||
// Unknown product, presumably this version is okay?
|
||||
min_firmware_version = 0;
|
||||
break;
|
||||
}
|
||||
if (ctx->firmware_version < min_firmware_version) {
|
||||
return SDL_SetError("Unsupported firmware version");
|
||||
}
|
||||
|
||||
switch (data[7]) {
|
||||
switch (data[6]) {
|
||||
case 1:
|
||||
// Wired connection
|
||||
ctx->wireless = false;
|
||||
@@ -281,7 +319,7 @@ static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ctx->deviceID = data[6];
|
||||
ctx->deviceID = data[5];
|
||||
|
||||
// See whether we can acquire the controller
|
||||
const Uint8 query_status[] = { FLYDIGI_V2_CMD_REPORT_ID, FLYDIGI_V2_MAGIC1, FLYDIGI_V2_MAGIC2, FLYDIGI_V2_GET_STATUS_COMMAND };
|
||||
@@ -291,7 +329,7 @@ static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device)
|
||||
if (!GetReply(device, FLYDIGI_V2_GET_STATUS_COMMAND, data, sizeof(data))) {
|
||||
return SDL_SetError("Couldn't get controller status");
|
||||
}
|
||||
if (data[10] == 1) {
|
||||
if (data[9] == 1) {
|
||||
ctx->available = true;
|
||||
} else {
|
||||
// Click "Allow third-party apps to take over mappings" in the FlyDigi Space Station app
|
||||
@@ -338,19 +376,26 @@ static void HIDAPI_DriverFlydigi_UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
|
||||
break;
|
||||
case 128:
|
||||
case 129:
|
||||
controller_type = SDL_FLYDIGI_APEX5;
|
||||
break;
|
||||
case 130:
|
||||
controller_type = SDL_FLYDIGI_VADER5_PRO;
|
||||
break;
|
||||
case 133:
|
||||
case 134:
|
||||
controller_type = SDL_FLYDIGI_APEX5;
|
||||
break;
|
||||
default:
|
||||
// Try to guess from the name of the controller
|
||||
if (SDL_strstr(device->name, "VADER") != NULL) {
|
||||
if (SDL_strcasestr(device->name, "VADER") != NULL) {
|
||||
if (SDL_strstr(device->name, "VADER2") != NULL) {
|
||||
controller_type = SDL_FLYDIGI_VADER2;
|
||||
} else if (SDL_strstr(device->name, "VADER3") != NULL) {
|
||||
controller_type = SDL_FLYDIGI_VADER3;
|
||||
} else if (SDL_strstr(device->name, "VADER4") != NULL) {
|
||||
controller_type = SDL_FLYDIGI_VADER4;
|
||||
controller_type = SDL_FLYDIGI_VADER4_PRO;
|
||||
} else if (SDL_strstr(device->name, "Vader 5") != NULL) {
|
||||
controller_type = SDL_FLYDIGI_VADER5_PRO;
|
||||
}
|
||||
} else if (SDL_strstr(device->name, "APEX") != NULL) {
|
||||
if (SDL_strstr(device->name, "APEX2") != NULL) {
|
||||
@@ -410,7 +455,6 @@ static void HIDAPI_DriverFlydigi_UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
|
||||
ctx->accelScale = SDL_STANDARD_GRAVITY / 256.0f;
|
||||
ctx->sensor_timestamp_step_ns = ctx->wireless ? SENSOR_INTERVAL_VADER4_PRO_DONGLE_NS : SENSOR_INTERVAL_VADER4_PRO_WIRED_NS;
|
||||
break;
|
||||
case SDL_FLYDIGI_VADER4:
|
||||
case SDL_FLYDIGI_VADER4_PRO:
|
||||
HIDAPI_SetDeviceName(device, "Flydigi Vader 4 Pro");
|
||||
ctx->has_cz = true;
|
||||
@@ -418,6 +462,16 @@ static void HIDAPI_DriverFlydigi_UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
|
||||
ctx->accelScale = SDL_STANDARD_GRAVITY / 256.0f;
|
||||
ctx->sensor_timestamp_step_ns = ctx->wireless ? SENSOR_INTERVAL_VADER4_PRO_DONGLE_NS : SENSOR_INTERVAL_VADER4_PRO_WIRED_NS;
|
||||
break;
|
||||
case SDL_FLYDIGI_VADER5_PRO:
|
||||
HIDAPI_SetDeviceName(device, "Flydigi Vader 5 Pro");
|
||||
ctx->has_cz = true;
|
||||
ctx->has_lmrm = true;
|
||||
ctx->has_circle = true;
|
||||
ctx->sensors_supported = true;
|
||||
ctx->accelScale = SDL_STANDARD_GRAVITY / 4096.0f;
|
||||
ctx->gyroScale = DEG2RAD(2000.0f);
|
||||
ctx->sensor_timestamp_step_ns = SENSOR_INTERVAL_VADER5_PRO_NS;
|
||||
break;
|
||||
default:
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Unknown FlyDigi controller with ID %d, name '%s'", ctx->deviceID, device->name);
|
||||
break;
|
||||
@@ -479,6 +533,9 @@ static bool HIDAPI_DriverFlydigi_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
if (ctx->has_lmrm) {
|
||||
joystick->nbuttons += 2;
|
||||
}
|
||||
if (ctx->has_circle) {
|
||||
joystick->nbuttons += 1;
|
||||
}
|
||||
joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
|
||||
joystick->nhats = 1;
|
||||
|
||||
@@ -748,17 +805,28 @@ static void HIDAPI_DriverFlydigi_HandleStatePacketV2(SDL_Joystick *joystick, SDL
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_FLYDIGI_M2, ((data[13] & 0x08) != 0));
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_FLYDIGI_M3, ((data[13] & 0x10) != 0));
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_FLYDIGI_M4, ((data[13] & 0x20) != 0));
|
||||
if (ctx->has_cz) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, extra_button_index++, ((data[13] & 0x01) != 0));
|
||||
SDL_SendJoystickButton(timestamp, joystick, extra_button_index++, ((data[13] & 0x02) != 0));
|
||||
}
|
||||
if (ctx->has_lmrm) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, extra_button_index++, ((data[13] & 0x40) != 0));
|
||||
SDL_SendJoystickButton(timestamp, joystick, extra_button_index++, ((data[13] & 0x80) != 0));
|
||||
}
|
||||
} else {
|
||||
if (ctx->has_cz) {
|
||||
extra_button_index += 2;
|
||||
}
|
||||
if (ctx->has_lmrm) {
|
||||
extra_button_index += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->last_state[14] != data[14]) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[14] & 0x08) != 0));
|
||||
SDL_SendJoystickButton(timestamp, joystick, extra_button_index++, ((data[14] & 0x01) != 0));
|
||||
// The '-' button is only available on the Vader 2, for simplicity let's ignore that
|
||||
SDL_SendJoystickButton(timestamp, joystick, extra_button_index++, ((data[8] & 0x10) != 0));
|
||||
if (ctx->has_circle) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, extra_button_index++, ((data[14] & 0x01) != 0));
|
||||
}
|
||||
}
|
||||
|
||||
axis = LOAD16(data[3], data[4]);
|
||||
@@ -813,7 +881,7 @@ static void HIDAPI_DriverFlydigi_HandleStatePacketV2(SDL_Joystick *joystick, SDL
|
||||
|
||||
static void HIDAPI_DriverFlydigi_HandleStatusUpdate(SDL_HIDAPI_Device *device, Uint8 *data, int size)
|
||||
{
|
||||
if (data[9] == 1) {
|
||||
if (data[9] & 0x01) {
|
||||
// We can now acquire the controller
|
||||
HIDAPI_DriverFlydigi_SetAvailable(device, true);
|
||||
} else {
|
||||
|
||||
@@ -32,7 +32,7 @@ typedef enum
|
||||
SDL_FLYDIGI_VADER2_PRO,
|
||||
SDL_FLYDIGI_VADER3,
|
||||
SDL_FLYDIGI_VADER3_PRO,
|
||||
SDL_FLYDIGI_VADER4,
|
||||
SDL_FLYDIGI_VADER4_PRO,
|
||||
SDL_FLYDIGI_VADER5_PRO,
|
||||
} SDL_FlyDigiControllerType;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user