Try to use a Microsoft function to detect XInput devices when using
DirectInput - atm not working yet :(
This commit is contained in:
parent
22208365d2
commit
d3da93f368
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user