From 52243c2ff49b13cb10ac9b35059a77c4b63398a8 Mon Sep 17 00:00:00 2001 From: Felipe Jorge Date: Tue, 15 Jul 2025 11:59:33 -0300 Subject: [PATCH] Win32: Update GUID for SDL newer format --- src/win32_init.c | 3 +++ src/win32_joystick.c | 29 +++++++++++++++++++++++++---- src/win32_platform.h | 16 ++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/win32_init.c b/src/win32_init.c index 6b6e9d08..3a2cc0b7 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -126,6 +126,9 @@ static GLFWbool loadLibraries(void) { _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities) _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetCapabilities"); + // 108 is the ordinal for _XInputGetCapabilitiesEx, which additionally returns VID/PID of the controller. + _glfw.win32.xinput.GetCapabilitiesEx = (PFN_XInputGetCapabilitiesEx) + _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, (LPCSTR)108); _glfw.win32.xinput.GetState = (PFN_XInputGetState) _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetState"); diff --git a/src/win32_joystick.c b/src/win32_joystick.c index 6703485e..9dd239a3 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -519,12 +519,33 @@ void _glfwDetectJoystickConnectionWin32(void) if (jid <= GLFW_JOYSTICK_LAST) continue; - if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS) + if (XInputGetCapabilities(index, XINPUT_FLAG_GAMEPAD, &xic) != ERROR_SUCCESS) continue; - // Generate a joystick GUID that matches the SDL 2.0.5+ one - sprintf(guid, "78696e707574%02x000000000000000000", - xic.SubType & 0xff); + GLFW_XINPUT_CAPABILITIES_EX xic_ex; + if (!XInputGetCapabilitiesEx || XInputGetCapabilitiesEx(1, index, 0, &xic_ex) != ERROR_SUCCESS) + { + // use a generic VID/PID representing an XInput controller + xic_ex.VendorId = USB_VENDOR_MICROSOFT; + xic_ex.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; + xic_ex.VersionNumber = 0; + } + else + { + // fixup for Wireless Xbox 360 Controller + if (xic_ex.ProductId == 0 && xic_ex.Capabilities.Flags & XINPUT_CAPS_WIRELESS) + { + xic_ex.VendorId = USB_VENDOR_MICROSOFT; + xic_ex.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; + } + } + + // Generate a joystick GUID that matches the SDL one + // SDL_xinputjoystick.c:207 + uint8_t* vid = (uint8_t*)&xic_ex.VendorId; + uint8_t* pid = (uint8_t*)&xic_ex.ProductId; + uint8_t* ver = (uint8_t*)&xic_ex.VersionNumber; + sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000", vid[0], vid[1], pid[0], pid[1], ver[0], ver[1]); js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1); if (!js) diff --git a/src/win32_platform.h b/src/win32_platform.h index 49cceba6..f45bcfea 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -216,11 +216,26 @@ typedef enum #define ERROR_INVALID_PROFILE_ARB 0x2096 #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +// this struct might not defined in XInput headers +typedef struct +{ + XINPUT_CAPABILITIES Capabilities; + WORD VendorId; + WORD ProductId; + WORD VersionNumber; + WORD unk1; + DWORD unk2; +} GLFW_XINPUT_CAPABILITIES_EX; + // xinput.dll function pointer typedefs typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*); +typedef DWORD (WINAPI * PFN_XInputGetCapabilitiesEx)(DWORD,DWORD,DWORD,GLFW_XINPUT_CAPABILITIES_EX*); typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); #define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities +#define XInputGetCapabilitiesEx _glfw.win32.xinput.GetCapabilitiesEx #define XInputGetState _glfw.win32.xinput.GetState +#define USB_VENDOR_MICROSOFT 0x045e +#define USB_PRODUCT_XBOX360_XUSB_CONTROLLER 0x02a1 // XUSB driver software PID // dinput8.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN); @@ -412,6 +427,7 @@ typedef struct _GLFWlibraryWin32 struct { HINSTANCE instance; PFN_XInputGetCapabilities GetCapabilities; + PFN_XInputGetCapabilitiesEx GetCapabilitiesEx; PFN_XInputGetState GetState; } xinput;