diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 3b72fd3601328..4fe0b6a2591f4 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2843,6 +2843,15 @@ SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product return vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; } +SDL_bool SDL_IsJoystickSteamVirtualGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version) +{ +#ifdef __MACOSX__ + return (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0); +#else + return (vendor_id == USB_VENDOR_VALVE && product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD); +#endif +} + SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 44d8e8cc91121..35c255f49eaf7 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -123,6 +123,9 @@ extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id); extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id); +/* Function to return whether a joystick is a Steam Virtual Gamepad */ +extern SDL_bool SDL_IsJoystickSteamVirtualGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version); + /* Function to return whether a joystick is a Steam Controller */ extern SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index 628346f3cd6f4..5a23ed18d154a 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -85,10 +85,15 @@ static SDL_bool HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device return SDL_FALSE; } #if defined(__MACOSX__) && defined(SDL_JOYSTICK_MFI) - /* On macOS you can't write output reports to wired XBox controllers, - so we'll just use the GCController support instead. - */ - return SDL_FALSE; + if (SDL_IsJoystickSteamVirtualGamepad(vendor_id, product_id, version)) { + /* GCController support doesn't work with the Steam Virtual Gamepad */ + return SDL_TRUE; + } else { + /* On macOS you can't write output reports to wired XBox controllers, + so we'll just use the GCController support instead. + */ + return SDL_FALSE; + } #else return (type == SDL_CONTROLLER_TYPE_XBOX360) ? SDL_TRUE : SDL_FALSE; #endif @@ -143,6 +148,13 @@ static SDL_bool HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device) device->type = SDL_CONTROLLER_TYPE_XBOX360; + if (SDL_IsJoystickSteamVirtualGamepad(device->vendor_id, device->product_id, device->version) && + device->product_string && SDL_strncmp(device->product_string, "GamePad-", 8) == 0) { + int slot = 0; + SDL_sscanf(device->product_string, "GamePad-%d", &slot); + device->steam_virtual_gamepad_slot = (slot - 1); + } + return HIDAPI_JoystickConnected(device, NULL); } @@ -231,7 +243,11 @@ static int HIDAPI_DriverXbox360_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *dev static void HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXbox360_Context *ctx, Uint8 *data, int size) { Sint16 axis; +#ifdef __MACOSX__ + const SDL_bool invert_y_axes = SDL_FALSE; +#else const SDL_bool invert_y_axes = SDL_TRUE; +#endif if (ctx->last_state[2] != data[2]) { SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 863785eec0bb2..28209fa5ed07b 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -929,6 +929,7 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0); device->joystick_type = SDL_JOYSTICK_TYPE_GAMECONTROLLER; device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol); + device->steam_virtual_gamepad_slot = -1; if (num_children > 0) { int i; @@ -1380,6 +1381,12 @@ static const char *HIDAPI_JoystickGetDevicePath(int device_index) static int HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) { + SDL_HIDAPI_Device *device; + + device = HIDAPI_GetDeviceByIndex(device_index, NULL); + if (device) { + return device->steam_virtual_gamepad_slot; + } return -1; } diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index 738c43abebe46..8a315da37ba35 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -83,6 +83,7 @@ typedef struct _SDL_HIDAPI_Device SDL_bool is_bluetooth; SDL_JoystickType joystick_type; SDL_GameControllerType type; + int steam_virtual_gamepad_slot; struct _SDL_HIDAPI_DeviceDriver *driver; void *context; diff --git a/src/joystick/iphoneos/SDL_mfijoystick.m b/src/joystick/iphoneos/SDL_mfijoystick.m index 2dedc9710d192..3b09127e20e38 100644 --- a/src/joystick/iphoneos/SDL_mfijoystick.m +++ b/src/joystick/iphoneos/SDL_mfijoystick.m @@ -419,6 +419,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle return FALSE; } #endif + if (device->is_xbox && SDL_strncmp(name, "GamePad-", 8) == 0) { + /* This is a Steam Virtual Gamepad, which isn't supported by GCController */ + return FALSE; + } CheckControllerSiriRemote(controller, &device->is_siri_remote); if (device->is_siri_remote && !SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { @@ -438,7 +442,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->has_xbox_share_button = TRUE; } } -#endif // ENABLE_PHYSICAL_INPUT_PROFILE +#endif /* ENABLE_PHYSICAL_INPUT_PROFILE */ if (device->is_backbone_one) { vendor = USB_VENDOR_BACKBONE;