summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerInterface
diff options
context:
space:
mode:
authorshuffle2 <godisgovernment@gmail.com>2014-09-02 23:21:47 -0700
committershuffle2 <godisgovernment@gmail.com>2014-09-02 23:21:47 -0700
commitde71db4864f39248ce491bc9a19644b521dcd065 (patch)
tree5a175b535caf4253f1a4008ca8ded48fd43e7d7e /Source/Core/InputCommon/ControllerInterface
parent532b7bb7da8dde441518a025965d4106f1f546c9 (diff)
parent3c0227445cb75f2798d8bcf1d284566c16f6f940 (diff)
Merge pull request #925 from shuffle2/xbcd-compat
Revert changes to how DInput filters out XInput devices.
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.cpp18
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.cpp123
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.h14
3 files changed, 143 insertions, 12 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.cpp b/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.cpp
index 7d1db57427..1ff48877db 100644
--- a/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.cpp
@@ -8,6 +8,7 @@
#include "InputCommon/ControllerInterface/DInput/DInput.h"
#include "InputCommon/ControllerInterface/DInput/DInputJoystick.h"
+#include "InputCommon/ControllerInterface/DInput/XInputFilter.h"
namespace ciface
{
@@ -16,29 +17,22 @@ namespace DInput
#define DATA_BUFFER_SIZE 32
-static const GUID s_known_xinput_guids[] = {
- // ValveStreamingGamepad
- { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } },
- // IID_X360WiredGamepad
- { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } },
- // IID_X360WirelessGamepad
- { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } },
-};
-
void InitJoystick(IDirectInput8* const idi8, std::vector<Core::Device*>& devices, HWND hwnd)
{
std::list<DIDEVICEINSTANCE> joysticks;
- idi8->EnumDevices( DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, (LPVOID)&joysticks, DIEDFL_ATTACHEDONLY );
+ idi8->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, (LPVOID)&joysticks, DIEDFL_ATTACHEDONLY);
// this is used to number the joysticks
// multiple joysticks with the same name shall get unique ids starting at 0
std::map< std::basic_string<TCHAR>, int> name_counts;
+ std::vector<DWORD> xinput_guids;
+ GetXInputGUIDS(&xinput_guids);
+
for (DIDEVICEINSTANCE& joystick : joysticks)
{
// skip XInput Devices
- if (std::find(std::begin(s_known_xinput_guids), std::end(s_known_xinput_guids),
- joystick.guidProduct) != std::end(s_known_xinput_guids))
+ if (std::find(xinput_guids.begin(), xinput_guids.end(), joystick.guidProduct.Data1) != xinput_guids.end())
{
continue;
}
diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.cpp b/Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.cpp
new file mode 100644
index 0000000000..a9a6c33918
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.cpp
@@ -0,0 +1,123 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+// This function is contained in a separate file because WbemIdl.h pulls in files which break on
+// /Zc:strictStrings, so this compilation unit is compiled without /Zc:strictStrings.
+
+#include <vector>
+#include <WbemIdl.h>
+#include <Windows.h>
+
+#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=nullptr; } }
+
+namespace ciface
+{
+namespace DInput
+{
+
+//-----------------------------------------------------------------------------
+// Modified some MSDN code to get all the XInput device GUID.Data1 values in a vector,
+// faster than checking all the devices for each DirectInput device, like MSDN says to do
+//-----------------------------------------------------------------------------
+void GetXInputGUIDS(std::vector<DWORD>* guids)
+{
+ IWbemLocator* pIWbemLocator = nullptr;
+ IEnumWbemClassObject* pEnumDevices = nullptr;
+ IWbemClassObject* pDevices[20] = {0};
+ IWbemServices* pIWbemServices = nullptr;
+ BSTR bstrNamespace = nullptr;
+ BSTR bstrDeviceID = nullptr;
+ BSTR bstrClassName = nullptr;
+ DWORD uReturned = 0;
+ VARIANT var;
+ HRESULT hr;
+
+ // CoInit if needed
+ hr = CoInitialize(nullptr);
+ bool bCleanupCOM = SUCCEEDED(hr);
+
+ // Create WMI
+ hr = CoCreateInstance(__uuidof(WbemLocator),
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IWbemLocator),
+ (LPVOID*) &pIWbemLocator);
+ if (FAILED(hr) || pIWbemLocator == nullptr)
+ goto LCleanup;
+
+ bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == nullptr) goto LCleanup;
+ bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == nullptr) goto LCleanup;
+ bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == nullptr) goto LCleanup;
+
+ // Connect to WMI
+ hr = pIWbemLocator->ConnectServer(bstrNamespace, nullptr, nullptr, 0L, 0L, nullptr, nullptr, &pIWbemServices);
+ if (FAILED(hr) || pIWbemServices == nullptr)
+ goto LCleanup;
+
+ // Switch security level to IMPERSONATE.
+ CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr,
+ RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);
+
+ hr = pIWbemServices->CreateInstanceEnum(bstrClassName, 0, nullptr, &pEnumDevices);
+ if (FAILED(hr) || pEnumDevices == nullptr)
+ goto LCleanup;
+
+ // Loop over all devices
+ while (true)
+ {
+ // Get 20 at a time
+ hr = pEnumDevices->Next(10000, 20, pDevices, &uReturned);
+ if (FAILED(hr) || uReturned == 0)
+ break;
+
+ for (UINT iDevice = 0; iDevice < uReturned; ++iDevice)
+ {
+ // For each device, get its device ID
+ hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, nullptr, nullptr);
+ if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != nullptr)
+ {
+ // 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);
+ guids->push_back(dwVidPid);
+ //bIsXinputDevice = true;
+ }
+ }
+ SAFE_RELEASE(pDevices[iDevice]);
+ }
+ }
+
+LCleanup:
+ if (bstrNamespace)
+ SysFreeString(bstrNamespace);
+ if (bstrDeviceID)
+ SysFreeString(bstrDeviceID);
+ if (bstrClassName)
+ SysFreeString(bstrClassName);
+ for (UINT iDevice = 0; iDevice < 20; iDevice++)
+ SAFE_RELEASE(pDevices[iDevice]);
+ SAFE_RELEASE(pEnumDevices);
+ SAFE_RELEASE(pIWbemLocator);
+ SAFE_RELEASE(pIWbemServices);
+
+ if (bCleanupCOM)
+ CoUninitialize();
+}
+
+}
+}
+
+#undef SAFE_RELEASE
diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.h b/Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.h
new file mode 100644
index 0000000000..1dcc1141bf
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/DInput/XInputFilter.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <vector>
+#include <Windows.h>
+
+namespace ciface
+{
+namespace DInput
+{
+
+void GetXInputGUIDS(std::vector<DWORD>* guids);
+
+}
+}