From 0e60e22b73dd0693b349cbb63cf9a390c01fd5dd Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 12 Jan 2021 17:01:18 -0500 Subject: filter raw input based on id use device id (from device instance) over first hardware id use buffered method for all ioctls update gui/DeviceIDManager to match driver behavior respond to device change events desync MouseData and PointData accessors --- common/common.vcxitems | 1 + common/rawaccel-io-def.h | 4 +-- common/rawaccel-settings.h | 4 +-- common/utility-rawinput.hpp | 74 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 common/utility-rawinput.hpp (limited to 'common') diff --git a/common/common.vcxitems b/common/common.vcxitems index 2b03405..ba9bd98 100644 --- a/common/common.vcxitems +++ b/common/common.vcxitems @@ -29,6 +29,7 @@ + diff --git a/common/rawaccel-io-def.h b/common/rawaccel-io-def.h index d8d4088..e169390 100644 --- a/common/rawaccel-io-def.h +++ b/common/rawaccel-io-def.h @@ -8,6 +8,6 @@ #define RA_DEV_TYPE 0x8888u -#define RA_READ CTL_CODE(RA_DEV_TYPE, 0x888, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define RA_READ CTL_CODE(RA_DEV_TYPE, 0x888, METHOD_BUFFERED, FILE_ANY_ACCESS) #define RA_WRITE CTL_CODE(RA_DEV_TYPE, 0x889, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define RA_GET_VERSION CTL_CODE(RA_DEV_TYPE, 0x88a, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define RA_GET_VERSION CTL_CODE(RA_DEV_TYPE, 0x88a, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/common/rawaccel-settings.h b/common/rawaccel-settings.h index f94e960..eb7c49a 100644 --- a/common/rawaccel-settings.h +++ b/common/rawaccel-settings.h @@ -3,7 +3,7 @@ #include "vec2.h" #include "accel-base.hpp" -#define MAX_HWID_LEN 200 +#define MAX_DEV_ID_LEN 200 namespace rawaccel { @@ -25,7 +25,7 @@ namespace rawaccel { vec2d sens = { 1, 1 }; vec2d dir_multipliers = {}; milliseconds time_min = DEFAULT_TIME_MIN; - wchar_t device_hw_id[MAX_HWID_LEN] = {0}; + wchar_t device_id[MAX_DEV_ID_LEN] = {0}; }; } diff --git a/common/utility-rawinput.hpp b/common/utility-rawinput.hpp new file mode 100644 index 0000000..3c44068 --- /dev/null +++ b/common/utility-rawinput.hpp @@ -0,0 +1,74 @@ +#pragma once + +#pragma comment(lib, "cfgmgr32.lib") + +#include +#include +#include +#include + +#include +#include +#include // needed for devpkey.h to parse properly +#include + +// returns device handles corresponding to a "device id" +// https://docs.microsoft.com/en-us/windows-hardware/drivers/install/device-ids +std::vector rawinput_handles_from_dev_id(const std::wstring& dev_id, DWORD input_type = RIM_TYPEMOUSE) { + const UINT RI_ERROR = -1; + + UINT num_devs = 0; + + if (GetRawInputDeviceList(NULL, &num_devs, sizeof(RAWINPUTDEVICELIST)) == RI_ERROR) { + throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceList failed"); + } + + auto devs = std::vector(num_devs); + + if (GetRawInputDeviceList(&devs[0], &num_devs, sizeof(RAWINPUTDEVICELIST)) == RI_ERROR) { + throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceList failed"); + } + + std::vector handles; + + for (auto&& dev : devs) { + if (dev.dwType != input_type) continue; + + WCHAR name[256] = {}; + UINT name_size = sizeof(name); + + if (GetRawInputDeviceInfoW(dev.hDevice, RIDI_DEVICENAME, name, &name_size) == RI_ERROR) { + throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceInfoW failed"); + } + + ULONG id_size = 0; + DEVPROPTYPE type; + CONFIGRET cm_res; + + cm_res = CM_Get_Device_Interface_PropertyW(name, &DEVPKEY_Device_InstanceId, + &type, NULL, &id_size, 0); + + if (cm_res != CR_BUFFER_SMALL && cm_res != CR_SUCCESS) { + throw std::runtime_error("CM_Get_Device_Interface_PropertyW failed (" + + std::to_string(cm_res) + ')'); + } + + std::wstring id((static_cast(id_size) + 1) / 2, '\0'); + + cm_res = CM_Get_Device_Interface_PropertyW(name, &DEVPKEY_Device_InstanceId, + &type, reinterpret_cast(&id[0]), &id_size, 0); + + if (cm_res != CR_SUCCESS) { + throw std::runtime_error("CM_Get_Device_Interface_PropertyW failed (" + + std::to_string(cm_res) + ')'); + } + + // remove instance id + id.resize(id.find_last_of('\\')); + + if (id == dev_id) handles.push_back(dev.hDevice); + } + + return handles; +} + -- cgit v1.2.3