mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Correctly implement exclusions of DInput devices that are also XInput
This commit is contained in:
1 parent
a58e24838b
commit
b2bd844a01
4 files changed
+100
-45
No files matched your search
+85
-37
@@ -24,6 +24,9 @@
|
||||
#include <XInput.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include <wbemidl.h>
|
||||
#include <comdef.h>
|
||||
#include <set>
|
||||
#include "Common/Input/InputState.h"
|
||||
#include "Common/Input/KeyCodes.h"
|
||||
#include "Common/StringUtils.h"
|
||||
@@ -32,10 +35,12 @@
|
||||
#include "Windows/DinputDevice.h"
|
||||
#pragma comment(lib,"dinput8.lib")
|
||||
|
||||
//initialize static members of DinputDevice
|
||||
// static members of DinputDevice
|
||||
unsigned int DinputDevice::pInstances = 0;
|
||||
Microsoft::WRL::ComPtr<IDirectInput8> DinputDevice::pDI;
|
||||
std::vector<DIDEVICEINSTANCE> DinputDevice::devices;
|
||||
std::set<u32> DinputDevice::ignoreDevices_;
|
||||
|
||||
bool DinputDevice::needsCheck_ = true;
|
||||
|
||||
// In order from 0. There can be 128, but most controllers do not have that many.
|
||||
@@ -64,23 +69,7 @@ static const InputKeyCode dinput_buttons[] = {
|
||||
#define JOY_POVBACKWARD_LEFT JOY_POVBACKWARD + DIFF
|
||||
#define JOY_POVLEFT_FORWARD JOY_POVLEFT + DIFF
|
||||
|
||||
struct XINPUT_DEVICE_NODE {
|
||||
DWORD dwVidPid;
|
||||
XINPUT_DEVICE_NODE* pNext;
|
||||
};
|
||||
XINPUT_DEVICE_NODE* g_pXInputDeviceList = NULL;
|
||||
|
||||
bool IsXInputDevice( const GUID* pGuidProductFromDirectInput ) {
|
||||
XINPUT_DEVICE_NODE* pNode = g_pXInputDeviceList;
|
||||
while( pNode )
|
||||
{
|
||||
if( pNode->dwVidPid == pGuidProductFromDirectInput->Data1 )
|
||||
return true;
|
||||
pNode = pNode->pNext;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static std::set<u32> DetectXInputVIDPIDs();
|
||||
|
||||
LPDIRECTINPUT8 DinputDevice::getPDI()
|
||||
{
|
||||
@@ -94,30 +83,28 @@ LPDIRECTINPUT8 DinputDevice::getPDI()
|
||||
return pDI.Get();
|
||||
}
|
||||
|
||||
BOOL CALLBACK DinputDevice::DevicesCallback(
|
||||
LPCDIDEVICEINSTANCE lpddi,
|
||||
LPVOID pvRef
|
||||
)
|
||||
{
|
||||
BOOL CALLBACK DinputDevice::DevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) {
|
||||
//check if a device with the same Instance guid is already saved
|
||||
auto res = std::find_if(devices.begin(), devices.end(),
|
||||
[lpddi](const DIDEVICEINSTANCE &to_consider){
|
||||
return lpddi->guidInstance == to_consider.guidInstance;
|
||||
});
|
||||
if (res == devices.end()) //not yet in the devices list
|
||||
{
|
||||
// Ignore if device supports XInput
|
||||
if (!IsXInputDevice(&lpddi->guidProduct)) {
|
||||
if (res == devices.end()) {
|
||||
// not yet in the devices list
|
||||
// Ignore if device supports XInput - we'll get the input through there instead.
|
||||
const u32 vidpid = lpddi->guidProduct.Data1;
|
||||
const bool isXinputDevice = ignoreDevices_.find(vidpid) != ignoreDevices_.end();
|
||||
if (!isXinputDevice) {
|
||||
devices.push_back(*lpddi);
|
||||
}
|
||||
}
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
void DinputDevice::getDevices(bool refresh)
|
||||
{
|
||||
if (refresh)
|
||||
{
|
||||
void DinputDevice::getDevices(bool refresh) {
|
||||
if (refresh) {
|
||||
// We don't want duplicate reporting from XInput devices through DInput.
|
||||
ignoreDevices_ = DetectXInputVIDPIDs();
|
||||
getPDI()->EnumDevices(DI8DEVCLASS_GAMECTRL, &DinputDevice::DevicesCallback, NULL, DIEDFL_ATTACHEDONLY);
|
||||
}
|
||||
}
|
||||
@@ -126,8 +113,6 @@ DinputDevice::DinputDevice(int devnum) {
|
||||
pInstances++;
|
||||
pDevNum = devnum;
|
||||
pJoystick = nullptr;
|
||||
memset(lastButtons_, 0, sizeof(lastButtons_));
|
||||
memset(lastPOV_, 0, sizeof(lastPOV_));
|
||||
last_lX_ = 0;
|
||||
last_lY_ = 0;
|
||||
last_lZ_ = 0;
|
||||
@@ -135,13 +120,11 @@ DinputDevice::DinputDevice(int devnum) {
|
||||
last_lRy_ = 0;
|
||||
last_lRz_ = 0;
|
||||
|
||||
if (getPDI() == NULL)
|
||||
{
|
||||
if (!getPDI()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (devnum >= MAX_NUM_PADS)
|
||||
{
|
||||
if (devnum >= MAX_NUM_PADS) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,3 +308,68 @@ size_t DinputDevice::getNumPads()
|
||||
needsCheck_ = false;
|
||||
return devices.size();
|
||||
}
|
||||
|
||||
static std::set<u32> DetectXInputVIDPIDs() {
|
||||
std::set<u32> xinputVidPids;
|
||||
|
||||
/*
|
||||
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
|
||||
return xinputVidPids;
|
||||
}
|
||||
*/
|
||||
|
||||
IWbemLocator* pIWbemLocator = nullptr;
|
||||
if (FAILED(CoCreateInstance(__uuidof(WbemLocator), nullptr, CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWbemLocator), (void**)&pIWbemLocator)))
|
||||
return xinputVidPids;
|
||||
|
||||
IWbemServices* pIWbemServices = nullptr;
|
||||
if (FAILED(pIWbemLocator->ConnectServer(_bstr_t(L"root\\cimv2"), nullptr, nullptr, nullptr, 0,
|
||||
nullptr, nullptr, &pIWbemServices))) {
|
||||
pIWbemLocator->Release();
|
||||
return xinputVidPids;
|
||||
}
|
||||
|
||||
CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr,
|
||||
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);
|
||||
|
||||
IEnumWbemClassObject* pEnumDevices = nullptr;
|
||||
if (FAILED(pIWbemServices->CreateInstanceEnum(_bstr_t(L"Win32_PNPEntity"), 0, nullptr, &pEnumDevices))) {
|
||||
pIWbemServices->Release();
|
||||
pIWbemLocator->Release();
|
||||
return xinputVidPids;
|
||||
}
|
||||
|
||||
IWbemClassObject* pDevices[20] = { 0 };
|
||||
ULONG uReturned = 0;
|
||||
|
||||
while (SUCCEEDED(pEnumDevices->Next(10000, 20, pDevices, &uReturned)) && uReturned > 0) {
|
||||
for (ULONG i = 0; i < uReturned; i++) {
|
||||
VARIANT var;
|
||||
if (SUCCEEDED(pDevices[i]->Get(L"DeviceID", 0, &var, nullptr, nullptr)))
|
||||
{
|
||||
if (wcsstr(var.bstrVal, L"IG_"))
|
||||
{
|
||||
DWORD vid = 0, pid = 0;
|
||||
const WCHAR *strVid = wcsstr(var.bstrVal, L"VID_");
|
||||
const WCHAR *strPid = wcsstr(var.bstrVal, L"PID_");
|
||||
|
||||
if (strVid) swscanf_s(strVid, L"VID_%4x", &vid);
|
||||
if (strPid) swscanf_s(strPid, L"PID_%4x", &pid);
|
||||
|
||||
const DWORD vidpid = MAKELONG(vid, pid);
|
||||
xinputVidPids.insert((u32)vidpid);
|
||||
}
|
||||
VariantClear(&var);
|
||||
}
|
||||
pDevices[i]->Release();
|
||||
}
|
||||
}
|
||||
|
||||
pEnumDevices->Release();
|
||||
pIWbemServices->Release();
|
||||
pIWbemLocator->Release();
|
||||
// CoUninitialize();
|
||||
|
||||
return xinputVidPids;
|
||||
}
|
||||
Reference in new issue
Block a user