diff options
| author | a1xd <[email protected]> | 2021-01-12 17:01:18 -0500 |
|---|---|---|
| committer | a1xd <[email protected]> | 2021-01-12 17:01:18 -0500 |
| commit | 0e60e22b73dd0693b349cbb63cf9a390c01fd5dd (patch) | |
| tree | 493bfaeb2b59b7db452c52e9ec9713e8b8296510 /common/utility-rawinput.hpp | |
| parent | Small behavior improvements (diff) | |
| download | rawaccel-0e60e22b73dd0693b349cbb63cf9a390c01fd5dd.tar.xz rawaccel-0e60e22b73dd0693b349cbb63cf9a390c01fd5dd.zip | |
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
Diffstat (limited to 'common/utility-rawinput.hpp')
| -rw-r--r-- | common/utility-rawinput.hpp | 74 |
1 files changed, 74 insertions, 0 deletions
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 <iostream> +#include <string> +#include <system_error> +#include <vector> + +#include <Windows.h> +#include <cfgmgr32.h> +#include <initguid.h> // needed for devpkey.h to parse properly +#include <devpkey.h> + +// returns device handles corresponding to a "device id" +// https://docs.microsoft.com/en-us/windows-hardware/drivers/install/device-ids +std::vector<HANDLE> 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<RAWINPUTDEVICELIST>(num_devs); + + if (GetRawInputDeviceList(&devs[0], &num_devs, sizeof(RAWINPUTDEVICELIST)) == RI_ERROR) { + throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceList failed"); + } + + std::vector<HANDLE> 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<size_t>(id_size) + 1) / 2, '\0'); + + cm_res = CM_Get_Device_Interface_PropertyW(name, &DEVPKEY_Device_InstanceId, + &type, reinterpret_cast<PBYTE>(&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; +} + |