From f64c40346dab580220101b0aacb4a6ff5484d86a Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Sat, 30 Jan 2021 01:23:34 -0500 Subject: 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 --- common/utility-rawinput.hpp | 78 ++++++++++++++++++------------- grapher/Models/Devices/DeviceIDItem.cs | 2 +- grapher/Models/Devices/DeviceIDManager.cs | 22 +-------- grapher/grapher.csproj | 1 - 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 #include #include #include @@ -12,9 +11,40 @@ #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) { +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(&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 +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 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 handles; for (auto&& dev : devs) { if (dev.dwType != input_type) continue; @@ -41,34 +69,20 @@ std::vector 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(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) + ')'); - } + 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 rawinput_handles_from_dev_id(const std::wstring& device_id, DWORD input_type = RIM_TYPEMOUSE) { + std::vector 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 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 @@ - 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 #include #include @@ -276,6 +277,30 @@ public: } }; +struct device_info { + std::wstring name; + std::wstring id; +}; + +std::vector get_unique_device_info() { + std::vector 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^ rawInputHandles) @@ -292,6 +317,29 @@ public ref struct RawInputInterop throw gcnew System::Exception(gcnew String(e.what())); } } + + static List>^ GetDeviceIDs() + { + try + { + auto managed = gcnew List>(); + + for (auto&& [name, id] : get_unique_device_info()) + { + managed->Add( + ValueTuple( + msclr::interop::marshal_as(name), + msclr::interop::marshal_as(id))); + } + + return managed; + } + catch (const std::exception& e) + { + throw gcnew System::Exception(gcnew String(e.what())); + } + } + }; public ref struct DriverInterop -- cgit v1.2.3 From 48463581ecec7667f4e52fd6c1c1180dafbafd1c Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 2 Feb 2021 22:39:19 -0500 Subject: increase default sens cap --- common/rawaccel.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/rawaccel.hpp b/common/rawaccel.hpp index 4c1e597..e28cd92 100644 --- a/common/rawaccel.hpp +++ b/common/rawaccel.hpp @@ -65,7 +65,7 @@ namespace rawaccel { /// Struct to hold clamp (min and max) details for acceleration application struct accel_scale_clamp { double lo = 0; - double hi = 128; + double hi = 1e9; /// /// Clamps given input to min at lo, max at hi. -- cgit v1.2.3 From 20df03273fdc17df059930c2ee4771abfc430bd7 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 2 Feb 2021 22:39:57 -0500 Subject: bump version --- common/rawaccel-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/rawaccel-version.h b/common/rawaccel-version.h index aef506d..7002919 100644 --- a/common/rawaccel-version.h +++ b/common/rawaccel-version.h @@ -2,7 +2,7 @@ #define RA_VER_MAJOR 1 #define RA_VER_MINOR 4 -#define RA_VER_PATCH 1 +#define RA_VER_PATCH 2 #define RA_OS "Win7+" -- cgit v1.2.3 From f87856d4045c8b8683aa4c44a0b23fe2eb42f0f0 Mon Sep 17 00:00:00 2001 From: a1xd <68629610+a1xd@users.noreply.github.com> Date: Tue, 2 Feb 2021 22:43:44 -0500 Subject: fix typos in guide --- doc/Guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Guide.md b/doc/Guide.md index df43e94..23b4be1 100644 --- a/doc/Guide.md +++ b/doc/Guide.md @@ -114,7 +114,7 @@ This is the style found in Quake 3, Quake Live, and countless inspired followers ![ClassicExample](images/classic_example.png) ### Power -This is the style found in CS:GO and Source Engine games (m_customaccel 3). The user can set a rate by which the speed is multplied, and then an exponent to which the product is raised, which is then the final multiplier (no adding to 1.). In the aforementioned games the default m_customaccel_exponent value of 1.05 would be a value of 0.05 in Raw Accel, leading to a concave slowly rising curve. CS:GO and Source Engine games apply acceleration in an fps-dependent manner, so Raw Accel can only simulate acceleration from these games at a given fps. To do so, set scale to 1000/(in-game fps). +This is the style found in CS:GO and Source Engine games (m_customaccel 3). The user can set a rate by which the speed is multiplied, and then an exponent to which the product is raised, which is then the final multiplier (no adding to 1). In the aforementioned games the default m_customaccel_exponent value of 1.05 would be a value of 0.05 in Raw Accel, leading to a concave slowly rising curve. CS:GO and Source Engine games apply acceleration in an fps-dependent manner, so Raw Accel can only simulate acceleration from these games at a given fps. To do so, set scale to 1000/(in-game fps). ![PowerExample](images/power_example.png) ### Natural & NaturalGain -- cgit v1.2.3