Try to use a Microsoft function to detect XInput devices when using

DirectInput - atm not working yet :(
This commit is contained in:
hiker 2017-08-03 09:24:50 +10:00
parent 22208365d2
commit d3da93f368

View File

@ -23,6 +23,9 @@
#ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include <wbemidl.h>
#include <oleauto.h>
#ifdef _MSC_VER
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
@ -123,12 +126,15 @@ struct SJoystickWin32Control
p->directInputAddJoystick(lpddi);
return DIENUM_CONTINUE;
}
bool IsXInputDevice(const GUID* pGuidProductFromDirectInput);
void directInputAddJoystick(LPCDIDEVICEINSTANCE lpddi)
{
//Get the GUID of the joystuck
const GUID guid = lpddi->guidInstance;
JoystickInfo activeJoystick;
activeJoystick.m_use_xinput = isXInputDevice(&guid);
activeJoystick.Index=ActiveJoysticks.size();
activeJoystick.guid=guid;
activeJoystick.Name=lpddi->tszProductName;
@ -193,6 +199,137 @@ struct SJoystickWin32Control
ActiveJoysticks.push_back(activeJoystick);
}
//-----------------------------------------------------------------------------
/** Taken from:
* https://msdn.microsoft.com/en-us/library/windows/desktop/dd940435(v=vs.85).aspx
*/
template <class T> void SAFE_RELEASE(T **ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}
/** Taken from:
* https://msdn.microsoft.com/en-us/library/windows/desktop/ee417014(v=vs.85).aspx
*/
//-----------------------------------------------------------------------------
// Enum each PNP device using WMI and check each device ID to see if it contains
// "IG_" (ex. "VID_045E&PID_028E&IG_00"). If it does, then it's an XInput device
// Unfortunately this information can not be found by just using DirectInput
//-----------------------------------------------------------------------------
bool isXInputDevice(const GUID* pGuidProductFromDirectInput)
{
IWbemLocator* pIWbemLocator = NULL;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemClassObject* pDevices[20] = { 0 };
IWbemServices* pIWbemServices = NULL;
BSTR bstrNamespace = NULL;
BSTR bstrDeviceID = NULL;
BSTR bstrClassName = NULL;
DWORD uReturned = 0;
bool bIsXinputDevice = false;
UINT iDevice = 0;
VARIANT var;
HRESULT hr;
// CoInit if needed
hr = CoInitialize(NULL);
bool bCleanupCOM = SUCCEEDED(hr);
// Create WMI
hr = CoCreateInstance(__uuidof(WbemLocator),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IWbemLocator),
(LPVOID*)&pIWbemLocator);
if (FAILED(hr) || pIWbemLocator == NULL)
goto LCleanup;
bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == NULL) goto LCleanup;
bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == NULL) goto LCleanup;
bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == NULL) goto LCleanup;
// Connect to WMI
hr = pIWbemLocator->ConnectServer(bstrNamespace, NULL, NULL, 0L,
0L, NULL, NULL, &pIWbemServices);
if (FAILED(hr) || pIWbemServices == NULL)
goto LCleanup;
// Switch security level to IMPERSONATE.
CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
hr = pIWbemServices->CreateInstanceEnum(bstrClassName, 0, NULL, &pEnumDevices);
if (FAILED(hr) || pEnumDevices == NULL)
goto LCleanup;
// Loop over all devices
for (;; )
{
// Get 20 at a time
hr = pEnumDevices->Next(10000, 20, pDevices, &uReturned);
if (FAILED(hr))
goto LCleanup;
if (uReturned == 0)
break;
for (iDevice = 0; iDevice<uReturned; iDevice++)
{
// For each device, get its device ID
hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL);
if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL)
{
// Check if the device ID contains "IG_". If it does, then it's an XInput device
// This information can not be found from DirectInput
if (wcsstr(var.bstrVal, L"IG_"))
{
// If it does, then get the VID/PID from var.bstrVal
DWORD dwPid = 0, dwVid = 0;
WCHAR* strVid = wcsstr(var.bstrVal, L"VID_");
if (strVid && swscanf(strVid, L"VID_%4X", &dwVid) != 1)
dwVid = 0;
WCHAR* strPid = wcsstr(var.bstrVal, L"PID_");
if (strPid && swscanf(strPid, L"PID_%4X", &dwPid) != 1)
dwPid = 0;
// Compare the VID/PID to the DInput device
DWORD dwVidPid = MAKELONG(dwVid, dwPid);
if (dwVidPid == pGuidProductFromDirectInput->Data1)
{
bIsXinputDevice = true;
goto LCleanup;
}
}
}
SAFE_RELEASE(&pDevices[iDevice]);
}
}
LCleanup:
if (bstrNamespace)
SysFreeString(bstrNamespace);
if (bstrDeviceID)
SysFreeString(bstrDeviceID);
if (bstrClassName)
SysFreeString(bstrClassName);
for (iDevice = 0; iDevice<20; iDevice++)
SAFE_RELEASE(&pDevices[iDevice]);
SAFE_RELEASE(&pEnumDevices);
SAFE_RELEASE(&pIWbemLocator);
SAFE_RELEASE(&pIWbemServices);
if (bCleanupCOM)
CoUninitialize();
return bIsXinputDevice;
}
// ------------------------------------------------------------------------
#endif
void pollJoysticks()