summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authora1xd <[email protected]>2021-01-14 12:27:42 -0500
committerGitHub <[email protected]>2021-01-14 12:27:42 -0500
commit9ea8b4b94bba795eb5060b376baa8e5169e80272 (patch)
tree493bfaeb2b59b7db452c52e9ec9713e8b8296510
parentMerge pull request #53 from termhn/patch-1 (diff)
parentfilter raw input based on id (diff)
downloadrawaccel-9ea8b4b94bba795eb5060b376baa8e5169e80272.tar.xz
rawaccel-9ea8b4b94bba795eb5060b376baa8e5169e80272.zip
Merge pull request #59 from aroidzap/apply-for-specific-device-gui
(GUI) Apply RawAccel only for specific device
-rw-r--r--common/common.vcxitems1
-rw-r--r--common/rawaccel-io-def.h4
-rw-r--r--common/rawaccel-settings.h3
-rw-r--r--common/utility-rawinput.hpp74
-rw-r--r--driver/driver.cpp75
-rw-r--r--driver/driver.h3
-rw-r--r--driver/driver.rc2
-rw-r--r--grapher/Form1.Designer.cs34
-rw-r--r--grapher/Form1.cs22
-rw-r--r--grapher/Models/AccelGUI.cs20
-rw-r--r--grapher/Models/AccelGUIFactory.cs11
-rw-r--r--grapher/Models/Devices/DeviceIDItem.cs73
-rw-r--r--grapher/Models/Devices/DeviceIDManager.cs86
-rw-r--r--grapher/Models/Mouse/MouseData.cs17
-rw-r--r--grapher/Models/Mouse/MouseWatcher.cs33
-rw-r--r--grapher/Models/Mouse/PointData.cs13
-rw-r--r--grapher/Models/Serialized/RawAccelSettings.cs3
-rw-r--r--grapher/Models/Serialized/SettingsManager.cs8
-rw-r--r--grapher/grapher.csproj3
-rw-r--r--signed/driver/rawaccel.sysbin61096 -> 61640 bytes
-rw-r--r--uninstaller/uninstaller.rc2
-rw-r--r--wrapper/wrapper.cpp27
-rw-r--r--wrapper/wrapper.vcxproj4
23 files changed, 422 insertions, 96 deletions
diff --git a/common/common.vcxitems b/common/common.vcxitems
index 2b03405..ba9bd98 100644
--- a/common/common.vcxitems
+++ b/common/common.vcxitems
@@ -29,6 +29,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-version.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)utility-install.hpp" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)utility-rawinput.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)x64-util.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)vec2.h" />
</ItemGroup>
diff --git a/common/rawaccel-io-def.h b/common/rawaccel-io-def.h
index d8d4088..e169390 100644
--- a/common/rawaccel-io-def.h
+++ b/common/rawaccel-io-def.h
@@ -8,6 +8,6 @@
#define RA_DEV_TYPE 0x8888u
-#define RA_READ CTL_CODE(RA_DEV_TYPE, 0x888, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+#define RA_READ CTL_CODE(RA_DEV_TYPE, 0x888, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define RA_WRITE CTL_CODE(RA_DEV_TYPE, 0x889, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define RA_GET_VERSION CTL_CODE(RA_DEV_TYPE, 0x88a, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+#define RA_GET_VERSION CTL_CODE(RA_DEV_TYPE, 0x88a, METHOD_BUFFERED, FILE_ANY_ACCESS)
diff --git a/common/rawaccel-settings.h b/common/rawaccel-settings.h
index 649c936..eb7c49a 100644
--- a/common/rawaccel-settings.h
+++ b/common/rawaccel-settings.h
@@ -3,6 +3,8 @@
#include "vec2.h"
#include "accel-base.hpp"
+#define MAX_DEV_ID_LEN 200
+
namespace rawaccel {
using milliseconds = double;
@@ -23,6 +25,7 @@ namespace rawaccel {
vec2d sens = { 1, 1 };
vec2d dir_multipliers = {};
milliseconds time_min = DEFAULT_TIME_MIN;
+ wchar_t device_id[MAX_DEV_ID_LEN] = {0};
};
}
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;
+}
+
diff --git a/driver/driver.cpp b/driver/driver.cpp
index a99a70b..a92f773 100644
--- a/driver/driver.cpp
+++ b/driver/driver.cpp
@@ -54,15 +54,18 @@ Arguments:
WDFDEVICE hDevice = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject);
PDEVICE_EXTENSION devExt = FilterGetData(hDevice);
- if (!(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE)) {
- auto num_packets = InputDataEnd - InputDataStart;
-
+ auto num_packets = InputDataEnd - InputDataStart;
+
+ bool any = num_packets > 0;
+ bool rel_move = !(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE);
+ bool dev_match = global.args.device_id[0] == 0 ||
+ wcsncmp(devExt->dev_id, global.args.device_id, MAX_DEV_ID_LEN) == 0;
+
+ if (any && rel_move && dev_match) {
// if IO is backed up to the point where we get more than 1 packet here
// then applying accel is pointless as we can't get an accurate timing
bool enable_accel = num_packets == 1;
- vec2d carry = devExt->carry;
-
auto it = InputDataStart;
do {
vec2d input = {
@@ -86,21 +89,20 @@ Arguments:
global.modifier.apply_sensitivity(input);
- double carried_result_x = input.x + carry.x;
- double carried_result_y = input.y + carry.y;
+ double carried_result_x = input.x + devExt->carry.x;
+ double carried_result_y = input.y + devExt->carry.y;
LONG out_x = static_cast<LONG>(carried_result_x);
LONG out_y = static_cast<LONG>(carried_result_y);
- carry.x = carried_result_x - out_x;
- carry.y = carried_result_y - out_y;
+ devExt->carry.x = carried_result_x - out_x;
+ devExt->carry.y = carried_result_y - out_y;
it->LastX = out_x;
it->LastY = out_y;
} while (++it != InputDataEnd);
- devExt->carry = carry;
}
(*(PSERVICE_CALLBACK_ROUTINE)devExt->UpperConnectData.ClassService)(
@@ -144,6 +146,8 @@ Return Value:
NTSTATUS status;
void* buffer;
+ size_t bytes_out = 0;
+
UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(OutputBufferLength);
UNREFERENCED_PARAMETER(InputBufferLength);
@@ -164,6 +168,7 @@ Return Value:
}
else {
*reinterpret_cast<ra::settings*>(buffer) = global.args;
+ bytes_out = sizeof(ra::settings);
}
break;
case RA_WRITE:
@@ -203,6 +208,7 @@ Return Value:
}
else {
*reinterpret_cast<ra::version_t*>(buffer) = { RA_VER_MAJOR, RA_VER_MINOR, RA_VER_PATCH };
+ bytes_out = sizeof(ra::version_t);
}
break;
default:
@@ -210,7 +216,7 @@ Return Value:
break;
}
- WdfRequestComplete(Request, status);
+ WdfRequestCompleteWithInformation(Request, status, bytes_out);
}
#pragma warning(pop) // enable 28118 again
@@ -465,7 +471,7 @@ Return Value:
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes,
DEVICE_EXTENSION);
-
+
//
// Create a framework device object. This call will in turn create
// a WDM deviceobject, attach to the lower stack and set the
@@ -477,6 +483,33 @@ Return Value:
return status;
}
+ //
+ // get device id from bus driver
+ //
+ DEVICE_OBJECT* pdo = WdfDeviceWdmGetPhysicalDevice(hDevice);
+
+ KEVENT ke;
+ KeInitializeEvent(&ke, NotificationEvent, FALSE);
+ IO_STATUS_BLOCK iosb = {};
+ PIRP Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+ pdo, NULL, 0, NULL, &ke, &iosb);
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+ PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
+ stack->MinorFunction = IRP_MN_QUERY_ID;
+ stack->Parameters.QueryId.IdType = BusQueryDeviceID;
+
+ NTSTATUS nts = IoCallDriver(pdo, Irp);
+
+ if (nts == STATUS_PENDING) {
+ KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
+ }
+
+ if (NT_SUCCESS(nts)) {
+ auto* id_ptr = reinterpret_cast<WCHAR*>(iosb.Information);
+ wcsncpy(FilterGetData(hDevice)->dev_id, id_ptr, MAX_DEV_ID_LEN);
+ DebugPrint(("Device ID = %ws\n", id_ptr));
+ ExFreePool(id_ptr);
+ }
//
// Configure the default queue to be Parallel. Do not use sequential queue
@@ -561,7 +594,7 @@ Routine Description:
//
// Connect a mouse class device driver to the port driver.
//
- case IOCTL_INTERNAL_MOUSE_CONNECT:
+ case IOCTL_INTERNAL_MOUSE_CONNECT: {
//
// Only allow one connection.
//
@@ -569,19 +602,19 @@ Routine Description:
status = STATUS_SHARING_VIOLATION;
break;
}
-
+
//
// Copy the connection parameters to the device extension.
//
- status = WdfRequestRetrieveInputBuffer(Request,
- sizeof(CONNECT_DATA),
- reinterpret_cast<PVOID*>(&connectData),
- &length);
- if(!NT_SUCCESS(status)){
+ status = WdfRequestRetrieveInputBuffer(Request,
+ sizeof(CONNECT_DATA),
+ reinterpret_cast<PVOID*>(&connectData),
+ &length);
+ if (!NT_SUCCESS(status)) {
DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status));
break;
}
-
+
devExt->counter = 0;
devExt->carry = {};
devExt->UpperConnectData = *connectData;
@@ -595,7 +628,7 @@ Routine Description:
connectData->ClassService = RawaccelCallback;
break;
-
+ }
//
// Disconnect a mouse class device driver from the port driver.
//
diff --git a/driver/driver.h b/driver/driver.h
index 8554f8c..a0381fb 100644
--- a/driver/driver.h
+++ b/driver/driver.h
@@ -4,7 +4,7 @@
#include <kbdmou.h>
#include <wdf.h>
-#include "vec2.h"
+#include "rawaccel-settings.h"
#if DBG
#define DebugPrint(_x_) DbgPrint _x_
@@ -21,6 +21,7 @@ typedef struct _DEVICE_EXTENSION {
counter_t counter;
vec2d carry;
CONNECT_DATA UpperConnectData;
+ WCHAR dev_id[MAX_DEV_ID_LEN];
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, FilterGetData)
diff --git a/driver/driver.rc b/driver/driver.rc
index e351ac3..53cad53 100644
--- a/driver/driver.rc
+++ b/driver/driver.rc
@@ -1,4 +1,4 @@
-//
+//
// Include the necessary resources
//
#include <winver.h>
diff --git a/grapher/Form1.Designer.cs b/grapher/Form1.Designer.cs
index 6fd9478..b375de1 100644
--- a/grapher/Form1.Designer.cs
+++ b/grapher/Form1.Designer.cs
@@ -161,6 +161,8 @@ namespace grapher
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.wholeVectorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.byVectorComponentToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.AutoWriteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.UseSpecificDeviceMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.chartsPanel = new System.Windows.Forms.Panel();
this.GainChartY = new System.Windows.Forms.DataVisualization.Charting.Chart();
this.VelocityChartY = new System.Windows.Forms.DataVisualization.Charting.Chart();
@@ -168,7 +170,6 @@ namespace grapher
this.GainChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
this.VelocityChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
this.AccelerationChart = new System.Windows.Forms.DataVisualization.Charting.Chart();
- this.AutoWriteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.optionsPanel.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.chartsPanel.SuspendLayout();
@@ -260,7 +261,6 @@ namespace grapher
this.optionsPanel.Name = "optionsPanel";
this.optionsPanel.Size = new System.Drawing.Size(483, 956);
this.optionsPanel.TabIndex = 34;
- this.optionsPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.optionsPanel_Paint);
//
// toggleButton
//
@@ -956,7 +956,8 @@ namespace grapher
this.capStyleToolStripMenuItem,
this.offsetStyleToolStripMenuItem,
this.toolStripMenuItem1,
- this.AutoWriteMenuItem});
+ this.AutoWriteMenuItem,
+ this.UseSpecificDeviceMenuItem});
this.advancedToolStripMenuItem.Name = "advancedToolStripMenuItem";
this.advancedToolStripMenuItem.Size = new System.Drawing.Size(72, 20);
this.advancedToolStripMenuItem.Text = "Advanced";
@@ -1029,6 +1030,21 @@ namespace grapher
this.byVectorComponentToolStripMenuItem.Size = new System.Drawing.Size(154, 22);
this.byVectorComponentToolStripMenuItem.Text = "By Component";
//
+ // AutoWriteMenuItem
+ //
+ this.AutoWriteMenuItem.Checked = true;
+ this.AutoWriteMenuItem.CheckOnClick = true;
+ this.AutoWriteMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.AutoWriteMenuItem.Name = "AutoWriteMenuItem";
+ this.AutoWriteMenuItem.Size = new System.Drawing.Size(210, 22);
+ this.AutoWriteMenuItem.Text = "Apply Settings On Startup";
+ //
+ // UseSpecificDeviceMenuItem
+ //
+ this.UseSpecificDeviceMenuItem.Name = "UseSpecificDeviceMenuItem";
+ this.UseSpecificDeviceMenuItem.Size = new System.Drawing.Size(210, 22);
+ this.UseSpecificDeviceMenuItem.Text = "Use Specific Device";
+ //
// chartsPanel
//
this.chartsPanel.AutoScroll = true;
@@ -1281,15 +1297,6 @@ namespace grapher
title6.Text = "Sensitivity";
this.AccelerationChart.Titles.Add(title6);
//
- // AutoWriteMenuItem
- //
- this.AutoWriteMenuItem.Checked = true;
- this.AutoWriteMenuItem.CheckOnClick = true;
- this.AutoWriteMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
- this.AutoWriteMenuItem.Name = "AutoWriteMenuItem";
- this.AutoWriteMenuItem.Size = new System.Drawing.Size(210, 22);
- this.AutoWriteMenuItem.Text = "Apply Settings On Startup";
- //
// RawAcceleration
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -1300,8 +1307,6 @@ namespace grapher
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "RawAcceleration";
this.Text = "Raw Accel";
- this.Load += new System.EventHandler(this.Form1_Load);
- this.Paint += new System.Windows.Forms.PaintEventHandler(this.RawAcceleration_Paint);
this.optionsPanel.ResumeLayout(false);
this.optionsPanel.PerformLayout();
this.menuStrip1.ResumeLayout(false);
@@ -1418,6 +1423,7 @@ namespace grapher
private System.Windows.Forms.DataVisualization.Charting.Chart VelocityChart;
private System.Windows.Forms.DataVisualization.Charting.Chart AccelerationChart;
private System.Windows.Forms.ToolStripMenuItem AutoWriteMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem UseSpecificDeviceMenuItem;
}
}
diff --git a/grapher/Form1.cs b/grapher/Form1.cs
index 0c12b86..afa7a50 100644
--- a/grapher/Form1.cs
+++ b/grapher/Form1.cs
@@ -71,6 +71,7 @@ namespace grapher
gainOffsetToolStripMenuItem,
legacyOffsetToolStripMenuItem,
AutoWriteMenuItem,
+ UseSpecificDeviceMenuItem,
ScaleMenuItem,
DPITextBox,
PollRateTextBox,
@@ -154,19 +155,18 @@ namespace grapher
protected override void WndProc(ref Message m)
{
- if (m.Msg == 0x00ff)
+ if (m.Msg == 0x00ff) // WM_INPUT
{
AccelGUI.MouseWatcher.ReadMouseMove(m);
}
+ else if (m.Msg == 0x00fe) // WM_INPUT_DEVICE_CHANGE
+ {
+ AccelGUI.UpdateInputManagers();
+ }
base.WndProc(ref m);
}
- private void Form1_Load(object sender, EventArgs e)
- {
-
- }
-
public void ResetAutoScroll()
{
chartsPanel.AutoScrollPosition = Constants.Origin;
@@ -186,16 +186,6 @@ namespace grapher
};
}
- private void RawAcceleration_Paint(object sender, PaintEventArgs e)
- {
- //AccelGUI.AccelCharts.DrawLastMovement();
- }
-
#endregion Method
-
- private void optionsPanel_Paint(object sender, PaintEventArgs e)
- {
-
- }
}
}
diff --git a/grapher/Models/AccelGUI.cs b/grapher/Models/AccelGUI.cs
index c6a2dcc..81b3e13 100644
--- a/grapher/Models/AccelGUI.cs
+++ b/grapher/Models/AccelGUI.cs
@@ -1,4 +1,5 @@
using grapher.Models.Calculations;
+using grapher.Models.Devices;
using grapher.Models.Mouse;
using grapher.Models.Options;
using grapher.Models.Serialized;
@@ -23,7 +24,8 @@ namespace grapher
Button writeButton,
ButtonBase toggleButton,
MouseWatcher mouseWatcher,
- ToolStripMenuItem scaleMenuItem)
+ ToolStripMenuItem scaleMenuItem,
+ DeviceIDManager deviceIDManager)
{
AccelForm = accelForm;
AccelCalculator = accelCalculator;
@@ -36,6 +38,7 @@ namespace grapher
DefaultButtonFont = WriteButton.Font;
SmallButtonFont = new Font(WriteButton.Font.Name, WriteButton.Font.Size * Constants.SmallButtonSizeFactor);
MouseWatcher = mouseWatcher;
+ DeviceIDManager = deviceIDManager;
ScaleMenuItem.Click += new System.EventHandler(OnScaleMenuItemClick);
WriteButton.Click += new System.EventHandler(OnWriteButtonClick);
@@ -95,6 +98,10 @@ namespace grapher
public ToolStripMenuItem ScaleMenuItem { get; }
+ public DeviceIDManager DeviceIDManager { get; }
+
+ public Action UpdateInputManagers { get; private set; }
+
private Timer ChartRefresh { get; }
private Font SmallButtonFont { get; }
@@ -141,7 +148,8 @@ namespace grapher
modes = ApplyOptions.GetModes(),
args = newArgs,
minimumTime = driverSettings.minimumTime,
- directionalMultipliers = driverSettings.directionalMultipliers
+ directionalMultipliers = driverSettings.directionalMultipliers,
+ deviceID = DeviceIDManager.ID,
};
ButtonDelay(WriteButton);
@@ -162,6 +170,14 @@ namespace grapher
{
UpdateShownActiveValues(args);
UpdateGraph(args);
+
+ UpdateInputManagers = () =>
+ {
+ MouseWatcher.UpdateHandles(args.deviceID);
+ DeviceIDManager.Update(args.deviceID);
+ };
+
+ UpdateInputManagers();
}
public void UpdateGraph(DriverSettings args)
diff --git a/grapher/Models/AccelGUIFactory.cs b/grapher/Models/AccelGUIFactory.cs
index 901a1b5..0669bf5 100644
--- a/grapher/Models/AccelGUIFactory.cs
+++ b/grapher/Models/AccelGUIFactory.cs
@@ -1,4 +1,5 @@
using grapher.Models.Calculations;
+using grapher.Models.Devices;
using grapher.Models.Mouse;
using grapher.Models.Options;
using grapher.Models.Serialized;
@@ -34,6 +35,7 @@ namespace grapher.Models
ToolStripMenuItem gainOffsetToolStripMenuItem,
ToolStripMenuItem legacyOffsetToolStripMenuItem,
ToolStripMenuItem autoWriteMenuItem,
+ ToolStripMenuItem useSpecificDeviceMenuItem,
ToolStripMenuItem scaleMenuItem,
ToolStripTextBox dpiTextBox,
ToolStripTextBox pollRateTextBox,
@@ -324,16 +326,20 @@ namespace grapher.Models
lockXYLabel,
accelCharts);
+ var deviceIdManager = new DeviceIDManager(useSpecificDeviceMenuItem);
+
var settings = new SettingsManager(
activeAccel,
accelCalculator.DPI,
accelCalculator.PollRate,
autoWriteMenuItem,
showLastMouseMoveMenuItem,
- showVelocityGainToolStripMenuItem);
+ showVelocityGainToolStripMenuItem,
+ deviceIdManager);
var mouseWatcher = new MouseWatcher(form, mouseLabel, accelCharts, settings);
+
return new AccelGUI(
form,
accelCalculator,
@@ -343,7 +349,8 @@ namespace grapher.Models
writeButton,
toggleButton,
mouseWatcher,
- scaleMenuItem);
+ scaleMenuItem,
+ deviceIdManager);
}
#endregion Methods
diff --git a/grapher/Models/Devices/DeviceIDItem.cs b/grapher/Models/Devices/DeviceIDItem.cs
new file mode 100644
index 0000000..63c2761
--- /dev/null
+++ b/grapher/Models/Devices/DeviceIDItem.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace grapher.Models.Devices
+{
+ public class DeviceIDItem
+ {
+ public DeviceIDItem(string name, string id, DeviceIDManager manager)
+ {
+ Name = name;
+ ID = id;
+ Manager = manager;
+ DeviceIDMenuItem = new ToolStripMenuItem();
+ DeviceIDMenuItem.Checked = false;
+ DeviceIDMenuItem.Text = MenuItemText();
+ DeviceIDMenuItem.Click += OnClicked;
+ manager.DeviceIDsMenuItem.DropDownItems.Add(DeviceIDMenuItem);
+ }
+
+ private ToolStripMenuItem DeviceIDMenuItem { get; }
+
+ public string Name { get; }
+
+ public string ID { get; }
+
+ private DeviceIDManager Manager { get; }
+
+ public void SetActivated()
+ {
+ DeviceIDMenuItem.Checked = true;
+ }
+
+ public void SetDeactivated()
+ {
+ DeviceIDMenuItem.Checked = false;
+ }
+
+ private string MenuItemText() => string.IsNullOrEmpty(ID) ? $"{Name}" : $"{Name}: {ID}";
+
+ private string DisconnectedText() => $"Disconnected: {ID}";
+
+ public void SetDisconnected()
+ {
+ DeviceIDMenuItem.ForeColor = Color.DarkGray;
+ DeviceIDMenuItem.Text = DisconnectedText();
+ }
+
+ public void OnClicked(object sender, EventArgs e)
+ {
+ Manager.SetActive(this);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is DeviceIDItem item &&
+ Name == item.Name &&
+ ID == item.ID;
+ }
+
+ public override int GetHashCode()
+ {
+ int hashCode = -1692744877;
+ hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
+ hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(ID);
+ return hashCode;
+ }
+ }
+}
diff --git a/grapher/Models/Devices/DeviceIDManager.cs b/grapher/Models/Devices/DeviceIDManager.cs
new file mode 100644
index 0000000..c50cda8
--- /dev/null
+++ b/grapher/Models/Devices/DeviceIDManager.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Management;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace grapher.Models.Devices
+{
+ public class DeviceIDManager
+ {
+ public DeviceIDManager(ToolStripMenuItem deviceIDs)
+ {
+ DeviceIDsMenuItem = deviceIDs;
+ DeviceIDsMenuItem.Checked = false;
+ }
+
+ public ToolStripMenuItem DeviceIDsMenuItem { get; }
+
+ public string ID { get => SelectedDeviceID.ID; }
+
+ public DeviceIDItem SelectedDeviceID { get; private set; }
+
+ 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)
+ {
+ SelectedDeviceID.SetDeactivated();
+ }
+
+ SelectedDeviceID = deviceIDItem;
+ SelectedDeviceID.SetActivated();
+ }
+
+ public void Update(string devID)
+ {
+ DeviceIDsMenuItem.DropDownItems.Clear();
+
+ bool found = string.IsNullOrEmpty(devID);
+
+ var anyDevice = new DeviceIDItem("Any", string.Empty, this);
+
+ if (found) SetActive(anyDevice);
+
+ foreach (var device in GetDeviceIDs().Distinct())
+ {
+ var deviceItem = new DeviceIDItem(device.Item1, device.Item2, this);
+ if (!found && deviceItem.ID.Equals(devID))
+ {
+ SetActive(deviceItem);
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ var deviceItem = new DeviceIDItem(string.Empty, devID, this);
+ deviceItem.SetDisconnected();
+ SetActive(deviceItem);
+ }
+ }
+
+ }
+}
diff --git a/grapher/Models/Mouse/MouseData.cs b/grapher/Models/Mouse/MouseData.cs
index e59a969..5944fe4 100644
--- a/grapher/Models/Mouse/MouseData.cs
+++ b/grapher/Models/Mouse/MouseData.cs
@@ -8,7 +8,6 @@ namespace grapher.Models.Mouse
public MouseData()
{
- Lock = new Object();
X = 0;
Y = 0;
}
@@ -17,18 +16,13 @@ namespace grapher.Models.Mouse
#region Properties
- public Object Lock { get; }
-
private int X { get; set; }
private int Y { get; set; }
public void Set(int x, int y)
{
- lock (Lock)
- {
- X = x;
- Y = y;
- }
+ X = x;
+ Y = y;
}
#endregion Properties
@@ -37,11 +31,8 @@ namespace grapher.Models.Mouse
public void Get(out int x, out int y)
{
- lock (Lock)
- {
- x = X;
- y = Y;
- }
+ x = X;
+ y = Y;
}
#endregion Methods
diff --git a/grapher/Models/Mouse/MouseWatcher.cs b/grapher/Models/Mouse/MouseWatcher.cs
index cbfc119..151a2a2 100644
--- a/grapher/Models/Mouse/MouseWatcher.cs
+++ b/grapher/Models/Mouse/MouseWatcher.cs
@@ -1,5 +1,6 @@
using grapher.Models.Serialized;
using System;
+using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
@@ -397,7 +398,11 @@ namespace grapher.Models.Mouse
/// <summary>If set, the application-defined keyboard device hotkeys are not handled. However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled. By default, all keyboard hotkeys are handled. NoHotKeys can be specified even if NoLegacy is not specified and WindowHandle is NULL.</summary>
NoHotKeys = 0x00000200,
/// <summary>If set, application keys are handled. NoLegacy must be specified. Keyboard only.</summary>
- AppKeys = 0x00000400
+ AppKeys = 0x00000400,
+ /// <summary>If set, this enables the caller to receive input in the background only if the foreground application does not process it. In other words, if the foreground application is not registered for raw input, then the background application that is registered will receive the input.</summary>
+ ExInputSink = 0x00001000,
+ /// <summary>If set, this enables the caller to receive WM_INPUT_DEVICE_CHANGE notifications for device arrival and device removal.</summary>
+ DevNotify = 0x00002000
}
/// <summary>Value type for raw input devices.</summary>
@@ -685,12 +690,13 @@ namespace grapher.Models.Mouse
AccelCharts = accelCharts;
SettingsManager = setMngr;
MouseData = new MouseData();
+ DeviceHandles = new List<IntPtr>();
RAWINPUTDEVICE device = new RAWINPUTDEVICE();
device.WindowHandle = ContainingForm.Handle;
device.UsagePage = HIDUsagePage.Generic;
device.Usage = HIDUsage.Mouse;
- device.Flags = RawInputDeviceFlags.InputSink;
+ device.Flags = RawInputDeviceFlags.InputSink | RawInputDeviceFlags.DevNotify;
RAWINPUTDEVICE[] devices = new RAWINPUTDEVICE[1];
devices[0] = device;
@@ -711,6 +717,10 @@ namespace grapher.Models.Mouse
private MouseData MouseData { get; }
+ private List<IntPtr> DeviceHandles { get; }
+
+ private bool AnyDevice { get; set; }
+
private double PollTime
{
get => 1000 / SettingsManager.PollRateField.Data;
@@ -720,6 +730,16 @@ namespace grapher.Models.Mouse
#region Methods
+ public void UpdateHandles(string devID)
+ {
+ DeviceHandles.Clear();
+ AnyDevice = string.IsNullOrEmpty(devID);
+ if (!AnyDevice)
+ {
+ RawInputInterop.AddHandlesFromID(devID, DeviceHandles);
+ }
+ }
+
public void UpdateLastMove()
{
MouseData.Get(out var x, out var y);
@@ -728,15 +748,14 @@ namespace grapher.Models.Mouse
public void ReadMouseMove(Message message)
{
- RawInput rawInput = new RawInput();
- int outSize = 0;
+ RawInput rawInput;
int size = Marshal.SizeOf(typeof(RawInput));
-
- outSize = GetRawInputData((IntPtr)message.LParam, RawInputCommand.Input, out rawInput, ref size, Marshal.SizeOf(typeof(RAWINPUTHEADER)));
+ _ = GetRawInputData(message.LParam, RawInputCommand.Input, out rawInput, ref size, Marshal.SizeOf(typeof(RAWINPUTHEADER)));
bool relative = !rawInput.Data.Mouse.Flags.HasFlag(RawMouseFlags.MoveAbsolute);
+ bool deviceMatch = AnyDevice || DeviceHandles.Contains(rawInput.Header.Device);
- if (relative && (rawInput.Data.Mouse.LastX != 0 || rawInput.Data.Mouse.LastY != 0))
+ if (relative && deviceMatch && (rawInput.Data.Mouse.LastX != 0 || rawInput.Data.Mouse.LastY != 0))
{
double x = rawInput.Data.Mouse.LastX;
double y = rawInput.Data.Mouse.LastY;
diff --git a/grapher/Models/Mouse/PointData.cs b/grapher/Models/Mouse/PointData.cs
index e3f44ea..87bfc62 100644
--- a/grapher/Models/Mouse/PointData.cs
+++ b/grapher/Models/Mouse/PointData.cs
@@ -8,7 +8,6 @@ namespace grapher.Models.Mouse
public PointData()
{
- Lock = new Object();
X = new double[] { 0.01 };
Y = new double[] { 0.01 };
}
@@ -17,18 +16,13 @@ namespace grapher.Models.Mouse
#region Properties
- public Object Lock { get; }
-
private double[] X { get; set; }
private double[] Y { get; set; }
public void Set(double x, double y)
{
- lock(Lock)
- {
- X[0] = x;
- Y[0] = y;
- }
+ X[0] = x;
+ Y[0] = y;
}
#endregion Properties
@@ -37,11 +31,8 @@ namespace grapher.Models.Mouse
public void Get(out double[] x, out double[] y)
{
- lock(Lock)
- {
x = X;
y = Y;
- }
}
#endregion Methods
diff --git a/grapher/Models/Serialized/RawAccelSettings.cs b/grapher/Models/Serialized/RawAccelSettings.cs
index dcaf864..f4fb1e2 100644
--- a/grapher/Models/Serialized/RawAccelSettings.cs
+++ b/grapher/Models/Serialized/RawAccelSettings.cs
@@ -125,7 +125,8 @@ namespace grapher.Models.Serialized
bool wholeOrNoY = accelSettings.combineMagnitudes ||
accelSettings.modes.y == AccelMode.noaccel;
- return accelSettings.sensitivity.x == 1 &&
+ return string.IsNullOrEmpty(accelSettings.deviceID) &&
+ accelSettings.sensitivity.x == 1 &&
accelSettings.sensitivity.y == 1 &&
accelSettings.directionalMultipliers.x <= 0 &&
accelSettings.directionalMultipliers.y <= 0 &&
diff --git a/grapher/Models/Serialized/SettingsManager.cs b/grapher/Models/Serialized/SettingsManager.cs
index 41ebcb5..40652dd 100644
--- a/grapher/Models/Serialized/SettingsManager.cs
+++ b/grapher/Models/Serialized/SettingsManager.cs
@@ -3,6 +3,8 @@ using System;
using System.Windows.Forms;
using System.Threading;
using System.Text;
+using System.Drawing;
+using grapher.Models.Devices;
namespace grapher.Models.Serialized
{
@@ -16,7 +18,8 @@ namespace grapher.Models.Serialized
Field pollRateField,
ToolStripMenuItem autoWrite,
ToolStripMenuItem showLastMouseMove,
- ToolStripMenuItem showVelocityAndGain)
+ ToolStripMenuItem showVelocityAndGain,
+ DeviceIDManager deviceIDManager)
{
ActiveAccel = activeAccel;
DpiField = dpiField;
@@ -24,6 +27,7 @@ namespace grapher.Models.Serialized
AutoWriteMenuItem = autoWrite;
ShowLastMouseMoveMenuItem = showLastMouseMove;
ShowVelocityAndGainMoveMenuItem = showVelocityAndGain;
+ DeviceIDManager = deviceIDManager;
}
#endregion Constructors
@@ -38,6 +42,8 @@ namespace grapher.Models.Serialized
public Field PollRateField { get; private set; }
+ public DeviceIDManager DeviceIDManager { get; }
+
private ToolStripMenuItem AutoWriteMenuItem { get; set; }
private ToolStripMenuItem ShowLastMouseMoveMenuItem { get; set; }
diff --git a/grapher/grapher.csproj b/grapher/grapher.csproj
index f6bdcb9..2788cca 100644
--- a/grapher/grapher.csproj
+++ b/grapher/grapher.csproj
@@ -59,6 +59,7 @@
</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" />
@@ -92,6 +93,8 @@
<Compile Include="Models\Charts\EstimatedPoints.cs" />
<Compile Include="Models\Charts\ChartState\XYOneGraphState.cs" />
<Compile Include="Models\Charts\ChartState\XYTwoGraphState.cs" />
+ <Compile Include="Models\Devices\DeviceIDItem.cs" />
+ <Compile Include="Models\Devices\DeviceIDManager.cs" />
<Compile Include="Models\Mouse\MouseData.cs" />
<Compile Include="Models\Mouse\MouseWatcher.cs" />
<Compile Include="Models\Mouse\PointData.cs" />
diff --git a/signed/driver/rawaccel.sys b/signed/driver/rawaccel.sys
index 3762899..0fef07f 100644
--- a/signed/driver/rawaccel.sys
+++ b/signed/driver/rawaccel.sys
Binary files differ
diff --git a/uninstaller/uninstaller.rc b/uninstaller/uninstaller.rc
index a9e8304..23b773d 100644
--- a/uninstaller/uninstaller.rc
+++ b/uninstaller/uninstaller.rc
@@ -1,4 +1,4 @@
-// Microsoft Visual C++ generated resource script.
+// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp
index fcbf2e8..2c0d5e3 100644
--- a/wrapper/wrapper.cpp
+++ b/wrapper/wrapper.cpp
@@ -1,13 +1,16 @@
#pragma once
#include <type_traits>
+#include <msclr\marshal_cppstd.h>
#include <rawaccel.hpp>
#include <rawaccel-version.h>
+#include <utility-rawinput.hpp>
#include "wrapper_io.hpp"
using namespace System;
+using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Reflection;
@@ -51,7 +54,7 @@ public value struct Vec2
};
[JsonObject(ItemRequired = Required::Always)]
-[StructLayout(LayoutKind::Sequential)]
+[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)]
public ref struct DriverSettings
{
literal String^ Key = "Driver settings";
@@ -78,6 +81,10 @@ public ref struct DriverSettings
[JsonProperty(Required = Required::Default)]
double minimumTime;
+ [JsonProperty("Device ID", Required = Required::Default)]
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)]
+ String^ deviceID = "";
+
bool ShouldSerializeminimumTime()
{
return minimumTime > 0 && minimumTime != DEFAULT_TIME_MIN;
@@ -217,6 +224,24 @@ public:
}
};
+public ref struct RawInputInterop
+{
+ static void AddHandlesFromID(String^ deviceID, List<IntPtr>^ rawInputHandles)
+ {
+ try
+ {
+ std::vector<HANDLE> nativeHandles = rawinput_handles_from_dev_id(
+ msclr::interop::marshal_as<std::wstring>(deviceID));
+
+ for (auto nh : nativeHandles) rawInputHandles->Add(IntPtr(nh));
+ }
+ catch (const std::exception& e)
+ {
+ throw gcnew System::Exception(gcnew String(e.what()));
+ }
+ }
+};
+
public ref struct DriverInterop
{
literal double WriteDelayMs = WRITE_DELAY;
diff --git a/wrapper/wrapper.vcxproj b/wrapper/wrapper.vcxproj
index 4f8ed1c..721a981 100644
--- a/wrapper/wrapper.vcxproj
+++ b/wrapper/wrapper.vcxproj
@@ -59,7 +59,7 @@
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
- <AdditionalDependencies />
+ <AdditionalDependencies>User32.lib;</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(SolutionDir)/common;</AdditionalIncludeDirectories>
@@ -72,7 +72,7 @@
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
- <AdditionalDependencies />
+ <AdditionalDependencies>User32.lib;</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)signed\$(TargetFileName)" &amp;