Added Steam Input API support for game controllers

Added support for getting the real controller info, as well as the function SDL_GetGamepadSteamHandle() to get the Steam Input API handle, from the virtual gamepads provided by Steam.

Also added an event SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED which is triggered when a controller's API handle changes, e.g. the controllers were reassigned slots in the Steam UI.
This commit is contained in:
Sam Lantinga 2023-12-09 23:05:34 -08:00
parent a8f4f40d08
commit c981a597dc
42 changed files with 779 additions and 40 deletions

View file

@ -114,6 +114,7 @@ typedef struct SDL_RAWINPUT_Device
SDL_JoystickGUID guid;
SDL_bool is_xinput;
SDL_bool is_xboxone;
int steam_virtual_gamepad_slot;
PHIDP_PREPARSED_DATA preparsed_data;
HANDLE hDevice;
@ -841,6 +842,19 @@ static SDL_RAWINPUT_Device *RAWINPUT_DeviceFromHandle(HANDLE hDevice)
return NULL;
}
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path)
{
int slot = -1;
// The format for the raw input device path is documented here:
// https://partner.steamgames.com/doc/features/steam_controller/steam_input_gamepad_emulation_bestpractices
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
(void)SDL_sscanf(device_path, "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%*X&%*X&%*X#%d#%*u", &slot);
}
return slot;
}
static void RAWINPUT_AddDevice(HANDLE hDevice)
{
#define CHECK(expression) \
@ -883,6 +897,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
device->version = (Uint16)rdi.hid.dwVersionNumber;
device->is_xinput = SDL_TRUE;
device->is_xboxone = SDL_IsJoystickXboxOne(device->vendor_id, device->product_id);
device->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(device->vendor_id, device->product_id, dev_name);
/* Get HID Top-Level Collection Preparsed Data */
size = 0;
@ -1189,6 +1204,11 @@ static const char *RAWINPUT_JoystickGetDevicePath(int device_index)
return RAWINPUT_GetDeviceByIndex(device_index)->path;
}
static int RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return RAWINPUT_GetDeviceByIndex(device_index)->steam_virtual_gamepad_slot;
}
static int RAWINPUT_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
@ -2198,6 +2218,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = {
RAWINPUT_JoystickDetect,
RAWINPUT_JoystickGetDeviceName,
RAWINPUT_JoystickGetDevicePath,
RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,
RAWINPUT_JoystickGetDevicePlayerIndex,
RAWINPUT_JoystickSetDevicePlayerIndex,
RAWINPUT_JoystickGetDeviceGUID,