Add support for GIP guitars via gameinput (#15301)

This commit is contained in:
Sanjay Govind
2026-04-04 12:02:14 +13:00
committed by GitHub
parent 59602fb473
commit 7f86f9107d
3 changed files with 303 additions and 121 deletions

View File

@@ -1444,6 +1444,26 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_GAMEINPUT "SDL_JOYSTICK_GAMEINPUT"
/**
* A variable controlling whether GameInput should be used for handling
* GIP devices that require raw report processing, but aren't supported
* by HIDRAW, such as Xbox One Guitars.
*
* Note that this is only supported with GameInput 3 or newer.
*
* The variable can be set to the following values:
*
* - "0": GameInput is not used to handle raw GIP devices.
* - "1": GameInput is used.
*
* The default is "1" when using GameInput 3 or newer, and is "0" otherwise.
*
* This hint should be set before SDL is initialized.
*
* \since This hint is available since SDL 3.4.4.
*/
#define SDL_HINT_JOYSTICK_GAMEINPUT_RAW "SDL_JOYSTICK_GAMEINPUT_RAW"
/**
* A variable containing a list of devices known to have a GameCube form
* factor.

View File

@@ -44,6 +44,15 @@ enum
SDL_GAMEPAD_BUTTON_GAMEINPUT_SHARE = 11
};
enum
{
SDL_GAMEINPUT_RAWTYPE_NONE,
SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR,
SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT,
SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR,
SDL_GAMEINPUT_RAWTYPE_LEGACY_ADAPTER,
};
typedef struct GAMEINPUT_InternalDevice
{
IGameInputDevice *device;
@@ -52,6 +61,7 @@ typedef struct GAMEINPUT_InternalDevice
SDL_GUID guid; // generated by SDL
SDL_JoystickID device_instance; // generated by SDL
const GameInputDeviceInfo *info;
int raw_type;
int steam_virtual_gamepad_slot;
bool isAdded;
bool isDeleteRequested;
@@ -89,9 +99,66 @@ static bool GAMEINPUT_InternalIsGamepad(const GameInputDeviceInfo *info)
return false;
}
static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info)
{
#if GAMEINPUT_API_VERSION >= 3
GameInputKind supportedInput = info->supportedInput;
if (supportedInput & GameInputKindRawDeviceReport) {
switch (info->vendorId) {
case USB_VENDOR_MADCATZ:
switch (info->productId) {
case USB_PRODUCT_MADCATZ_XB1_STRATOCASTER_GUITAR:
return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR;
case USB_PRODUCT_MADCATZ_XB1_DRUM_KIT:
return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT;
case USB_PRODUCT_MADCATZ_XB1_LEGACY_ADAPTER:
return SDL_GAMEINPUT_RAWTYPE_LEGACY_ADAPTER;
default:
break;
}
break;
case USB_VENDOR_PDP:
switch (info->productId) {
case USB_PRODUCT_PDP_XB1_JAGUAR_GUITAR:
case USB_PRODUCT_PDP_XB1_RIFFMASTER_GUITAR:
return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR;
case USB_PRODUCT_PDP_XB1_DRUM_KIT:
return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT;
default:
break;
}
break;
case USB_VENDOR_CRKD:
switch (info->productId) {
case USB_PRODUCT_PDP_XB1_JAGUAR_GUITAR:
return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR;
default:
break;
}
break;
case USB_VENDOR_RED_OCTANE:
switch (info->productId) {
case USB_PRODUCT_RED_OCTANE_XB1_GUITAR_HERO_LIVE_GUITAR:
return SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR;
default:
break;
}
break;
}
}
#endif // GAMEINPUT_API_VERSION >= 3
return SDL_GAMEINPUT_RAWTYPE_NONE;
}
static Uint8 GAMEINPUT_GetDeviceSubtype(const GameInputDeviceInfo *info)
{
GameInputKind supportedInput = info->supportedInput;
Uint8 rawType = GAMEINPUT_GetDeviceRawType(info);
if (rawType == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR || rawType == SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR) {
return SDL_JOYSTICK_TYPE_GUITAR;
}
if (rawType == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT) {
return SDL_JOYSTICK_TYPE_DRUM_KIT;
}
if (supportedInput & GameInputKindRacingWheel) {
return SDL_JOYSTICK_TYPE_WHEEL;
}
@@ -132,6 +199,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
const char *product_string = NULL;
Uint8 driver_signature = 'g';
Uint8 subtype = 0;
int raw_type = SDL_GAMEINPUT_RAWTYPE_NONE;
char tmp[4];
int idx = 0;
@@ -154,6 +222,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
product = info->productId;
//version = (info->firmwareVersion.major << 8) | info->firmwareVersion.minor;
subtype = GAMEINPUT_GetDeviceSubtype(info);
raw_type = GAMEINPUT_GetDeviceRawType(info);
#if GAMEINPUT_API_VERSION >= 1
if (info->displayName) {
@@ -177,7 +246,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
}
#endif
if (!GAMEINPUT_InternalIsGamepad(info)) {
if (!GAMEINPUT_InternalIsGamepad(info) && raw_type == SDL_GAMEINPUT_RAWTYPE_NONE) {
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_DIRECTINPUT, true) || SDL_XINPUT_Enabled()) {
// Let other backends handle non-gamepad controllers to possibly avoid bugs and/or regressions.
@@ -226,6 +295,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
elem->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, product_string, driver_signature, subtype);
elem->device_instance = SDL_GetNextObjectID();
elem->info = info;
elem->raw_type = raw_type;
#if GAMEINPUT_API_VERSION >= 1
elem->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(info->pnpPath);
#else
@@ -318,11 +388,20 @@ static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback(
static void GAMEINPUT_JoystickDetect(void);
static void GAMEINPUT_JoystickQuit(void);
static bool GAMEINPUT_IsRawGameInputEnabled(void)
{
#if GAMEINPUT_API_VERSION >= 3
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT_RAW, true);
#else
return false;
#endif
}
static bool GAMEINPUT_JoystickInit(void)
{
HRESULT hr;
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT)) {
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT) && !GAMEINPUT_IsRawGameInputEnabled()) {
return true;
}
@@ -336,8 +415,16 @@ static bool GAMEINPUT_JoystickInit(void)
g_pGameInput->SetFocusPolicy(GameInputEnableBackgroundInput | GameInputEnableBackgroundGuideButton | GameInputEnableBackgroundShareButton);
#endif
GameInputKind kind = GameInputKindUnknown;
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT)) {
kind |= GameInputKindController;
}
if (GAMEINPUT_IsRawGameInputEnabled()) {
kind |= GameInputKindRawDeviceReport;
}
hr = g_pGameInput->RegisterDeviceCallback(NULL,
GameInputKindController,
kind,
GameInputDeviceConnected,
GameInputBlockingEnumeration,
NULL,
@@ -527,7 +614,7 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
hwdata->devref = elem;
joystick->hwdata = hwdata;
if (GAMEINPUT_InternalIsGamepad(info)) {
if (GAMEINPUT_InternalIsGamepad(info) || GAMEINPUT_GetDeviceRawType(info) != SDL_GAMEINPUT_RAWTYPE_NONE) {
joystick->naxes = 6;
joystick->nbuttons = 11;
joystick->nhats = 1;
@@ -612,14 +699,191 @@ static bool GAMEINPUT_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool ena
return true;
}
static void GAMEINPUT_GuitarUpdate(SDL_Joystick *joystick, IGameInputReading *reading, Uint64 timestamp)
{
IGameInputRawDeviceReport* rawState;
if (reading->GetRawReport(&rawState)) {
static WORD s_GuitarButtons[] = {
0x0010, // SDL_GAMEPAD_BUTTON_SOUTH
0x0020, // SDL_GAMEPAD_BUTTON_EAST
0x0040, // SDL_GAMEPAD_BUTTON_WEST
0x0080, // SDL_GAMEPAD_BUTTON_NORTH
0x0008, // SDL_GAMEPAD_BUTTON_BACK
0, // The guide button is not available
0x0004, // SDL_GAMEPAD_BUTTON_START
0, // right joystick click unavailable
0x4000, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
0x1000, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
0, // right shoulder unavailable
};
Uint8 btnidx = 0, hat = 0;
uint8_t rawData[40];
SDL_memset(rawData, 0, sizeof(rawData));
size_t len = rawState->GetRawData(sizeof(rawData), rawData);
uint16_t buttons = rawData[0] | rawData[1] << 8;
if (len >= 10) {
for (btnidx = 0; btnidx < SDL_arraysize(s_GuitarButtons); ++btnidx) {
WORD button_mask = s_GuitarButtons[btnidx];
if (!button_mask) {
continue;
}
bool down = ((buttons & button_mask) != 0);
SDL_SendJoystickButton(timestamp, joystick, btnidx, down);
}
if (buttons & 0x0100) {
hat |= SDL_HAT_UP;
}
if (buttons & 0x0200) {
hat |= SDL_HAT_DOWN;
}
if (buttons & 0x0400) {
hat |= SDL_HAT_LEFT;
}
if (buttons & 0x0800) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, (rawData[3] * 257) - 32768);
// PS3 RB guitars had tilt on right shoulder
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, rawData[2] >= 0xD0);
// PS3 RB guitars send L2 when using solo buttons
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (rawData[6]) ? 32767 : -32768);
// Align pickup selector mappings with PS3 instruments
static const Sint16 effects_mappings[] = {-26880, -13568, -1792, 11008, 24576};
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, effects_mappings[rawData[4] >> 4]);
}
}
}
static void GAMEINPUT_GamepadUpdate(SDL_Joystick *joystick, IGameInputReading *reading, Uint64 timestamp) {
GameInputGamepadState state;
static WORD s_XInputButtons[] = {
GameInputGamepadA, // SDL_GAMEPAD_BUTTON_SOUTH
GameInputGamepadB, // SDL_GAMEPAD_BUTTON_EAST
GameInputGamepadX, // SDL_GAMEPAD_BUTTON_WEST
GameInputGamepadY, // SDL_GAMEPAD_BUTTON_NORTH
GameInputGamepadView, // SDL_GAMEPAD_BUTTON_BACK
0, // The guide button is not available
GameInputGamepadMenu, // SDL_GAMEPAD_BUTTON_START
GameInputGamepadLeftThumbstick, // SDL_GAMEPAD_BUTTON_LEFT_STICK
GameInputGamepadRightThumbstick, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
GameInputGamepadLeftShoulder, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
GameInputGamepadRightShoulder, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
};
Uint8 btnidx = 0, hat = 0;
if (reading->GetGamepadState(&state)) {
for (btnidx = 0; btnidx < SDL_arraysize(s_XInputButtons); ++btnidx) {
WORD button_mask = s_XInputButtons[btnidx];
if (!button_mask) {
continue;
}
bool down = ((state.buttons & button_mask) != 0);
SDL_SendJoystickButton(timestamp, joystick, btnidx, down);
}
if (state.buttons & GameInputGamepadDPadUp) {
hat |= SDL_HAT_UP;
}
if (state.buttons & GameInputGamepadDPadDown) {
hat |= SDL_HAT_DOWN;
}
if (state.buttons & GameInputGamepadDPadLeft) {
hat |= SDL_HAT_LEFT;
}
if (state.buttons & GameInputGamepadDPadRight) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
#define CONVERT_AXIS(v) (Sint16)(((v) < 0.0f) ? ((v)*32768.0f) : ((v)*32767.0f))
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, CONVERT_AXIS(state.leftThumbstickX));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, CONVERT_AXIS(-state.leftThumbstickY));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, CONVERT_AXIS(state.rightThumbstickX));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, CONVERT_AXIS(-state.rightThumbstickY));
#undef CONVERT_AXIS
#define CONVERT_TRIGGER(v) (Sint16)((v)*65535.0f - 32768.0f)
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, CONVERT_TRIGGER(state.leftTrigger));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, CONVERT_TRIGGER(state.rightTrigger));
#undef CONVERT_TRIGGER
}
}
static void GAMEINPUT_ControllerUpdate(SDL_Joystick *joystick, IGameInputReading *reading, Uint64 timestamp)
{
bool *button_state = SDL_stack_alloc(bool, joystick->nbuttons);
float *axis_state = SDL_stack_alloc(float, joystick->naxes);
GameInputSwitchPosition *switch_state = SDL_stack_alloc(GameInputSwitchPosition, joystick->nhats);
if (button_state) {
uint32_t i;
uint32_t button_count = reading->GetControllerButtonState(joystick->nbuttons, button_state);
for (i = 0; i < button_count; ++i) {
SDL_SendJoystickButton(timestamp, joystick, (Uint8)i, button_state[i]);
}
SDL_stack_free(button_state);
}
#define CONVERT_AXIS(v) (Sint16)((v)*65535.0f - 32768.0f)
if (axis_state) {
uint32_t i;
uint32_t axis_count = reading->GetControllerAxisState(joystick->naxes, axis_state);
for (i = 0; i < axis_count; ++i) {
SDL_SendJoystickAxis(timestamp, joystick, (Uint8)i, CONVERT_AXIS(axis_state[i]));
}
SDL_stack_free(axis_state);
}
#undef CONVERT_AXIS
if (switch_state) {
uint32_t i;
uint32_t switch_count = reading->GetControllerSwitchState(joystick->nhats, switch_state);
for (i = 0; i < switch_count; ++i) {
Uint8 hat;
switch (switch_state[i]) {
case GameInputSwitchUp:
hat = SDL_HAT_UP;
break;
case GameInputSwitchUpRight:
hat = SDL_HAT_UP | SDL_HAT_RIGHT;
break;
case GameInputSwitchRight:
hat = SDL_HAT_RIGHT;
break;
case GameInputSwitchDownRight:
hat = SDL_HAT_DOWN | SDL_HAT_RIGHT;
break;
case GameInputSwitchDown:
hat = SDL_HAT_DOWN;
break;
case GameInputSwitchDownLeft:
hat = SDL_HAT_DOWN | SDL_HAT_LEFT;
break;
case GameInputSwitchLeft:
hat = SDL_HAT_LEFT;
break;
case GameInputSwitchUpLeft:
hat = SDL_HAT_UP | SDL_HAT_LEFT;
break;
case GameInputSwitchCenter:
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickHat(timestamp, joystick, (Uint8)i, hat);
}
SDL_stack_free(switch_state);
}
}
static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
{
GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata;
GAMEINPUT_InternalDevice *internal_device = hwdata->devref;
IGameInputDevice *device = hwdata->devref->device;
const GameInputDeviceInfo *info = hwdata->devref->info;
IGameInputReading *reading = NULL;
Uint64 timestamp;
GameInputGamepadState state;
HRESULT hr;
hr = g_pGameInput->GetCurrentReading(info->supportedInput, device, &reading);
@@ -629,122 +893,12 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
}
timestamp = SDL_US_TO_NS(reading->GetTimestamp() + g_GameInputTimestampOffset);
if (GAMEINPUT_InternalIsGamepad(info)) {
static WORD s_XInputButtons[] = {
GameInputGamepadA, // SDL_GAMEPAD_BUTTON_SOUTH
GameInputGamepadB, // SDL_GAMEPAD_BUTTON_EAST
GameInputGamepadX, // SDL_GAMEPAD_BUTTON_WEST
GameInputGamepadY, // SDL_GAMEPAD_BUTTON_NORTH
GameInputGamepadView, // SDL_GAMEPAD_BUTTON_BACK
0, // The guide button is not available
GameInputGamepadMenu, // SDL_GAMEPAD_BUTTON_START
GameInputGamepadLeftThumbstick, // SDL_GAMEPAD_BUTTON_LEFT_STICK
GameInputGamepadRightThumbstick, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
GameInputGamepadLeftShoulder, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
GameInputGamepadRightShoulder, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
};
Uint8 btnidx = 0, hat = 0;
if (reading->GetGamepadState(&state)) {
for (btnidx = 0; btnidx < SDL_arraysize(s_XInputButtons); ++btnidx) {
WORD button_mask = s_XInputButtons[btnidx];
if (!button_mask) {
continue;
}
bool down = ((state.buttons & button_mask) != 0);
SDL_SendJoystickButton(timestamp, joystick, btnidx, down);
}
if (state.buttons & GameInputGamepadDPadUp) {
hat |= SDL_HAT_UP;
}
if (state.buttons & GameInputGamepadDPadDown) {
hat |= SDL_HAT_DOWN;
}
if (state.buttons & GameInputGamepadDPadLeft) {
hat |= SDL_HAT_LEFT;
}
if (state.buttons & GameInputGamepadDPadRight) {
hat |= SDL_HAT_RIGHT;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
#define CONVERT_AXIS(v) (Sint16)(((v) < 0.0f) ? ((v)*32768.0f) : ((v)*32767.0f))
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, CONVERT_AXIS(state.leftThumbstickX));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, CONVERT_AXIS(-state.leftThumbstickY));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, CONVERT_AXIS(state.rightThumbstickX));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, CONVERT_AXIS(-state.rightThumbstickY));
#undef CONVERT_AXIS
#define CONVERT_TRIGGER(v) (Sint16)((v)*65535.0f - 32768.0f)
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, CONVERT_TRIGGER(state.leftTrigger));
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, CONVERT_TRIGGER(state.rightTrigger));
#undef CONVERT_TRIGGER
}
if (internal_device->raw_type == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR) {
GAMEINPUT_GuitarUpdate(joystick, reading, timestamp);
} else if (GAMEINPUT_InternalIsGamepad(info)) {
GAMEINPUT_GamepadUpdate(joystick, reading, timestamp);
} else {
bool *button_state = SDL_stack_alloc(bool, joystick->nbuttons);
float *axis_state = SDL_stack_alloc(float, joystick->naxes);
GameInputSwitchPosition *switch_state = SDL_stack_alloc(GameInputSwitchPosition, joystick->nhats);
if (button_state) {
uint32_t i;
uint32_t button_count = reading->GetControllerButtonState(joystick->nbuttons, button_state);
for (i = 0; i < button_count; ++i) {
SDL_SendJoystickButton(timestamp, joystick, (Uint8)i, button_state[i]);
}
SDL_stack_free(button_state);
}
#define CONVERT_AXIS(v) (Sint16)((v)*65535.0f - 32768.0f)
if (axis_state) {
uint32_t i;
uint32_t axis_count = reading->GetControllerAxisState(joystick->naxes, axis_state);
for (i = 0; i < axis_count; ++i) {
SDL_SendJoystickAxis(timestamp, joystick, (Uint8)i, CONVERT_AXIS(axis_state[i]));
}
SDL_stack_free(axis_state);
}
#undef CONVERT_AXIS
if (switch_state) {
uint32_t i;
uint32_t switch_count = reading->GetControllerSwitchState(joystick->nhats, switch_state);
for (i = 0; i < switch_count; ++i) {
Uint8 hat;
switch (switch_state[i]) {
case GameInputSwitchUp:
hat = SDL_HAT_UP;
break;
case GameInputSwitchUpRight:
hat = SDL_HAT_UP | SDL_HAT_RIGHT;
break;
case GameInputSwitchRight:
hat = SDL_HAT_RIGHT;
break;
case GameInputSwitchDownRight:
hat = SDL_HAT_DOWN | SDL_HAT_RIGHT;
break;
case GameInputSwitchDown:
hat = SDL_HAT_DOWN;
break;
case GameInputSwitchDownLeft:
hat = SDL_HAT_DOWN | SDL_HAT_LEFT;
break;
case GameInputSwitchLeft:
hat = SDL_HAT_LEFT;
break;
case GameInputSwitchUpLeft:
hat = SDL_HAT_UP | SDL_HAT_LEFT;
break;
case GameInputSwitchCenter:
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickHat(timestamp, joystick, (Uint8)i, hat);
}
SDL_stack_free(switch_state);
}
GAMEINPUT_ControllerUpdate(joystick, reading, timestamp);
}
#ifdef GAMEINPUT_SENSOR_SUPPORT
@@ -821,7 +975,7 @@ static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap
{
GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
if (!GAMEINPUT_InternalIsGamepad(elem->info)) {
if (!GAMEINPUT_InternalIsGamepad(elem->info) && elem->raw_type == SDL_GAMEINPUT_RAWTYPE_NONE) {
return false;
}

View File

@@ -53,6 +53,7 @@
#define USB_VENDOR_POWERA_ALT 0x20d6
#define USB_VENDOR_QANBA 0x2c22
#define USB_VENDOR_RAZER 0x1532
#define USB_VENDOR_RED_OCTANE 0x1430
#define USB_VENDOR_SAITEK 0x06a3
#define USB_VENDOR_SCEA 0x12ba
#define USB_VENDOR_SHANWAN 0x2563
@@ -102,6 +103,9 @@
#define USB_PRODUCT_LOGITECH_F310 0xc216
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
#define USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK 0x2218
#define USB_PRODUCT_MADCATZ_XB1_STRATOCASTER_GUITAR 0x4161
#define USB_PRODUCT_MADCATZ_XB1_DRUM_KIT 0x4262
#define USB_PRODUCT_MADCATZ_XB1_LEGACY_ADAPTER 0x4164
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRELESS 0x0d16
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18
@@ -127,6 +131,9 @@
#define USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V104 0x7214
#define USB_PRODUCT_PDP_ROCK_CANDY 0x0246
#define USB_PRODUCT_PDP_REALMZ_WIRELESS 0x018c
#define USB_PRODUCT_PDP_XB1_DRUM_KIT 0x0171
#define USB_PRODUCT_PDP_XB1_JAGUAR_GUITAR 0x0170
#define USB_PRODUCT_PDP_XB1_RIFFMASTER_GUITAR 0x0248
#define USB_PRODUCT_POWERA_MINI 0x541a
#define USB_PRODUCT_RAZER_ATROX 0x0a00
#define USB_PRODUCT_RAZER_KITSUNE 0x1012
@@ -146,6 +153,7 @@
#define USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_XBOX_WIRED 0x1010
#define USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_XBOX_WIRELESS 0x1011
#define USB_PRODUCT_RAZER_WOLVERINE_V3_PRO 0x0a3f
#define USB_PRODUCT_RED_OCTANE_XB1_GUITAR_HERO_LIVE_GUITAR 0x0170
#define USB_PRODUCT_SAITEK_CYBORG_V3 0xf622
#define USB_PRODUCT_SCEA_PS3_GH_GUITAR 0x0100
#define USB_PRODUCT_SCEA_PS3_GH_DRUMS 0x0120