# HG changeset patch # User Jimbly # Date 1459199875 25200 # Mon Mar 28 14:17:55 2016 -0700 # Node ID 7161a0cf5b92a5863bf0bcb8de8eb50d9c07b37c # Parent f0645cd8fd39df9a38841e702e3d4bb01083a191 Use HID Paths to re-identify joysticks when they are attached or removed. diff -r f0645cd8fd39 -r 7161a0cf5b92 src/joystick/SDL_gamecontroller.c --- a/src/joystick/SDL_gamecontroller.c Sun Mar 20 15:35:34 2016 -0300 +++ b/src/joystick/SDL_gamecontroller.c Mon Mar 28 14:17:55 2016 -0700 @@ -660,7 +660,7 @@ if (!mapping) { const char *name = SDL_JoystickNameForIndex(device_index); if (name) { - if (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box")) { + if (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box") || SDL_strstr(name, "XBOX")) { mapping = s_pXInputMapping; } } diff -r f0645cd8fd39 -r 7161a0cf5b92 src/joystick/windows/SDL_dinputjoystick.c --- a/src/joystick/windows/SDL_dinputjoystick.c Sun Mar 20 15:35:34 2016 -0300 +++ b/src/joystick/windows/SDL_dinputjoystick.c Mon Mar 28 14:17:55 2016 -0700 @@ -350,9 +350,46 @@ return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */ } + WCHAR hidPath[MAX_PATH]; + { + HRESULT result; + LPDIRECTINPUTDEVICE8 device; + LPDIRECTINPUTDEVICE8 InputDevice; + result = + IDirectInput8_CreateDevice(dinput, + &(pdidInstance->guidInstance), &device, NULL); + if (FAILED(result)) { + return DIENUM_CONTINUE; /* better luck next time? */ + } + + /* Now get the IDirectInputDevice8 interface, instead. */ + result = IDirectInputDevice8_QueryInterface(device, + &IID_IDirectInputDevice8, + (LPVOID *)&InputDevice); + /* We are done with this object. Use the stored one from now on. */ + IDirectInputDevice8_Release(device); + if (FAILED(result)) { + return DIENUM_CONTINUE; /* better luck next time? */ + } + DIPROPGUIDANDPATH dipdw2; + dipdw2.diph.dwSize = sizeof(dipdw2); + dipdw2.diph.dwHeaderSize = sizeof(dipdw2.diph); + dipdw2.diph.dwObj = 0; // device property + dipdw2.diph.dwHow = DIPH_DEVICE; + + result = IDirectInputDevice8_GetProperty(InputDevice, DIPROP_GUIDANDPATH, &dipdw2.diph); + IDirectInputDevice8_Release(InputDevice); + if (FAILED(result)) { + return DIENUM_CONTINUE; /* better luck next time? */ + } + + // Get device path, compare that instead of GUID, additionally update GUIDs of joysticks with matching paths, in case they're not open yet. + wcscpy_s(hidPath, SDL_arraysize(hidPath), dipdw2.wszPath); + } + pNewJoystick = *(JoyStick_DeviceData **)pContext; while (pNewJoystick) { - if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) { + if (0 == wcscmp(pNewJoystick->hidPath, hidPath)) { /* if we are replacing the front of the list then update it */ if (pNewJoystick == *(JoyStick_DeviceData **)pContext) { *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext; @@ -360,6 +397,9 @@ pPrevJoystick->pNext = pNewJoystick->pNext; } + // Update with new guid/etc, if it has changed + pNewJoystick->dxdevice = *pdidInstance; + pNewJoystick->pNext = SYS_Joystick; SYS_Joystick = pNewJoystick; @@ -376,6 +416,7 @@ } SDL_zerop(pNewJoystick); + wcscpy_s(pNewJoystick->hidPath, SDL_arraysize(pNewJoystick->hidPath), hidPath); pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName); if (!pNewJoystick->joystickname) { SDL_free(pNewJoystick); diff -r f0645cd8fd39 -r 7161a0cf5b92 src/joystick/windows/SDL_windowsjoystick_c.h --- a/src/joystick/windows/SDL_windowsjoystick_c.h Sun Mar 20 15:35:34 2016 -0300 +++ b/src/joystick/windows/SDL_windowsjoystick_c.h Mon Mar 28 14:17:55 2016 -0700 @@ -37,6 +37,7 @@ BYTE SubType; Uint8 XInputUserId; DIDEVICEINSTANCE dxdevice; + WCHAR hidPath[MAX_PATH]; struct JoyStick_DeviceData *pNext; } JoyStick_DeviceData;