Skip to content

Commit

Permalink
Merge pull request #71 from a1xd/fix-dev-id
Browse files Browse the repository at this point in the history
1.4.2
  • Loading branch information
a1xd authored Feb 3, 2021
2 parents e887f8d + f87856d commit 59e86a6
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 57 deletions.
2 changes: 1 addition & 1 deletion common/rawaccel-version.h
Original file line number Diff line number Diff line change
Expand Up @@ -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+"

Expand Down
2 changes: 1 addition & 1 deletion common/rawaccel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
78 changes: 46 additions & 32 deletions common/utility-rawinput.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#pragma comment(lib, "cfgmgr32.lib")

#include <iostream>
#include <string>
#include <system_error>
#include <vector>
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}

2 changes: 1 addition & 1 deletion doc/Guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion grapher/Models/Devices/DeviceIDItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void SetDeactivated()
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}";

Expand Down
22 changes: 2 additions & 20 deletions grapher/Models/Devices/DeviceIDManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,6 @@ public DeviceIDManager(ToolStripMenuItem deviceIDs)

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)
Expand All @@ -64,9 +46,9 @@ public void Update(string devID)

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);
Expand Down
1 change: 0 additions & 1 deletion grapher/grapher.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
48 changes: 48 additions & 0 deletions wrapper/wrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <algorithm>
#include <type_traits>
#include <msclr\marshal_cppstd.h>

Expand Down Expand Up @@ -276,6 +277,30 @@ public ref class SettingsErrors
}
};

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)
Expand All @@ -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
Expand Down

0 comments on commit 59e86a6

Please sign in to comment.