diff options
| author | a1xd <[email protected]> | 2021-01-30 01:23:34 -0500 |
|---|---|---|
| committer | a1xd <[email protected]> | 2021-01-30 01:23:34 -0500 |
| commit | f64c40346dab580220101b0aacb4a6ff5484d86a (patch) | |
| tree | e6103ccb3a0a4adde6cab99a6293a63dbc90738e | |
| parent | bump version (diff) | |
| download | rawaccel-f64c40346dab580220101b0aacb4a6ff5484d86a.tar.xz rawaccel-f64c40346dab580220101b0aacb4a6ff5484d86a.zip | |
fix device id not working with g305
this uses w32 apis for enumerating dev info instead of ManagementObjectSearcher, which upper-cases dev ids, differing from kernel/cfgmgr32
this also breaks showing dev name alongside id, as the name seems inaccessible from cfgmgr32 given an interface supplied by rawinput
not a big deal considering the names are too generic to be useful anyway
| -rw-r--r-- | common/utility-rawinput.hpp | 78 | ||||
| -rw-r--r-- | grapher/Models/Devices/DeviceIDItem.cs | 2 | ||||
| -rw-r--r-- | grapher/Models/Devices/DeviceIDManager.cs | 22 | ||||
| -rw-r--r-- | grapher/grapher.csproj | 1 | ||||
| -rw-r--r-- | wrapper/wrapper.cpp | 48 |
5 files changed, 97 insertions, 54 deletions
diff --git a/common/utility-rawinput.hpp b/common/utility-rawinput.hpp index 3c44068..c43084b 100644 --- a/common/utility-rawinput.hpp +++ b/common/utility-rawinput.hpp @@ -2,7 +2,6 @@ #pragma comment(lib, "cfgmgr32.lib") -#include <iostream> #include <string> #include <system_error> #include <vector> @@ -12,9 +11,40 @@ #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) { +std::wstring dev_prop_wstr_from_interface(const WCHAR* interface_name, const DEVPROPKEY* key) { + ULONG size = 0; + DEVPROPTYPE type; + CONFIGRET cm_res; + + cm_res = CM_Get_Device_Interface_PropertyW(interface_name, key, + &type, NULL, &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 prop((size + 1) / 2, L'\0'); + + cm_res = CM_Get_Device_Interface_PropertyW(interface_name, key, + &type, reinterpret_cast<PBYTE>(&prop[0]), &size, 0); + + if (cm_res != CR_SUCCESS) { + throw std::runtime_error("CM_Get_Device_Interface_PropertyW failed (" + + std::to_string(cm_res) + ')'); + } + + return prop; +} + +std::wstring dev_id_from_interface(const WCHAR* interface_name) { + auto id = dev_prop_wstr_from_interface(interface_name, &DEVPKEY_Device_InstanceId); + id.resize(id.find_last_of('\\')); + return id; +} + +template <typename Func> +void rawinput_foreach_with_interface(Func fn, DWORD input_type = RIM_TYPEMOUSE) { const UINT RI_ERROR = -1; UINT num_devs = 0; @@ -28,8 +58,6 @@ std::vector<HANDLE> rawinput_handles_from_dev_id(const std::wstring& dev_id, DWO 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; @@ -41,34 +69,20 @@ std::vector<HANDLE> rawinput_handles_from_dev_id(const std::wstring& dev_id, DWO 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) + ')'); - } + fn(dev, name); + } +} - // remove instance id - id.resize(id.find_last_of('\\')); +// 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& device_id, DWORD input_type = RIM_TYPEMOUSE) { + std::vector<HANDLE> handles; - if (id == dev_id) handles.push_back(dev.hDevice); - } + rawinput_foreach_with_interface([&](const auto& dev, const WCHAR* name) { + if (device_id == dev_id_from_interface(name)) { + handles.push_back(dev.hDevice); + } + }, input_type); return handles; } - diff --git a/grapher/Models/Devices/DeviceIDItem.cs b/grapher/Models/Devices/DeviceIDItem.cs index 63c2761..8f1587b 100644 --- a/grapher/Models/Devices/DeviceIDItem.cs +++ b/grapher/Models/Devices/DeviceIDItem.cs @@ -40,7 +40,7 @@ namespace grapher.Models.Devices DeviceIDMenuItem.Checked = false; } - private string MenuItemText() => string.IsNullOrEmpty(ID) ? $"{Name}" : $"{Name}: {ID}"; + private string MenuItemText() => string.IsNullOrEmpty(ID) ? $"{Name}" : ID.Replace("&", "&&"); private string DisconnectedText() => $"Disconnected: {ID}"; diff --git a/grapher/Models/Devices/DeviceIDManager.cs b/grapher/Models/Devices/DeviceIDManager.cs index c50cda8..8592763 100644 --- a/grapher/Models/Devices/DeviceIDManager.cs +++ b/grapher/Models/Devices/DeviceIDManager.cs @@ -25,24 +25,6 @@ namespace grapher.Models.Devices public Dictionary<string, DeviceIDItem> DeviceIDs { get; private set; } - public static IEnumerable<(string, string)> GetDeviceIDs(string PNPClass = "Mouse") - { - ManagementObjectSearcher searcher = new ManagementObjectSearcher(new SelectQuery("Win32_PnPEntity")); - - foreach (ManagementObject obj in searcher.Get()) - { - if (obj["PNPClass"] != null && obj["PNPClass"].ToString().Equals(PNPClass) && obj["DeviceID"] != null) - { - string name = obj["Name"].ToString(); - - string devInstanceID = obj["DeviceID"].ToString(); - string devID = devInstanceID.Remove(devInstanceID.LastIndexOf('\\')); - - yield return (name, devID); - } - } - } - public void SetActive(DeviceIDItem deviceIDItem) { if (SelectedDeviceID != null) @@ -64,9 +46,9 @@ namespace grapher.Models.Devices if (found) SetActive(anyDevice); - foreach (var device in GetDeviceIDs().Distinct()) + foreach (var (name, id) in RawInputInterop.GetDeviceIDs()) { - var deviceItem = new DeviceIDItem(device.Item1, device.Item2, this); + var deviceItem = new DeviceIDItem(name, id, this); if (!found && deviceItem.ID.Equals(devID)) { SetActive(deviceItem); diff --git a/grapher/grapher.csproj b/grapher/grapher.csproj index 8673325..1160ba8 100644 --- a/grapher/grapher.csproj +++ b/grapher/grapher.csproj @@ -59,7 +59,6 @@ </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> - <Reference Include="System.Management" /> <Reference Include="System.Windows.Forms.DataVisualization" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index f5672a1..71a8cf6 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -1,5 +1,6 @@ #pragma once +#include <algorithm> #include <type_traits> #include <msclr\marshal_cppstd.h> @@ -276,6 +277,30 @@ public: } }; +struct device_info { + std::wstring name; + std::wstring id; +}; + +std::vector<device_info> get_unique_device_info() { + std::vector<device_info> info; + + rawinput_foreach_with_interface([&](const auto& dev, const WCHAR* name) { + info.push_back({ + L"", // get_property_wstr(name, &DEVPKEY_Device_FriendlyName), /* doesn't work */ + dev_id_from_interface(name) + }); + }); + + std::sort(info.begin(), info.end(), + [](auto&& l, auto&& r) { return l.id < r.id; }); + auto last = std::unique(info.begin(), info.end(), + [](auto&& l, auto&& r) { return l.id == r.id; }); + info.erase(last, info.end()); + + return info; +} + public ref struct RawInputInterop { static void AddHandlesFromID(String^ deviceID, List<IntPtr>^ rawInputHandles) @@ -292,6 +317,29 @@ public ref struct RawInputInterop throw gcnew System::Exception(gcnew String(e.what())); } } + + static List<ValueTuple<String^, String^>>^ GetDeviceIDs() + { + try + { + auto managed = gcnew List<ValueTuple<String^, String^>>(); + + for (auto&& [name, id] : get_unique_device_info()) + { + managed->Add( + ValueTuple<String^, String^>( + msclr::interop::marshal_as<String^>(name), + msclr::interop::marshal_as<String^>(id))); + } + + return managed; + } + catch (const std::exception& e) + { + throw gcnew System::Exception(gcnew String(e.what())); + } + } + }; public ref struct DriverInterop |