diff options
| -rw-r--r-- | common/rawaccel-version.h | 2 | ||||
| -rw-r--r-- | common/rawaccel.hpp | 2 | ||||
| -rw-r--r-- | common/utility-rawinput.hpp | 78 | ||||
| -rw-r--r-- | doc/Guide.md | 2 | ||||
| -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 |
8 files changed, 100 insertions, 57 deletions
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+" 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 { /// <summary> Struct to hold clamp (min and max) details for acceleration application </summary> struct accel_scale_clamp { double lo = 0; - double hi = 128; + double hi = 1e9; /// <summary> /// Clamps given input to min at lo, max at hi. 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/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  ### 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).  ### Natural & NaturalGain 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 |