summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authora1xd <[email protected]>2021-04-01 01:51:31 -0400
committera1xd <[email protected]>2021-04-01 01:51:31 -0400
commit14bde56daf188bfc027dc8ead5b45ec0aa1109d6 (patch)
tree6c674efea62c4e945e4d8ed3e947189742486015
parentrefactor lut/motivity (diff)
downloadrawaccel-14bde56daf188bfc027dc8ead5b45ec0aa1109d6.tar.xz
rawaccel-14bde56daf188bfc027dc8ead5b45ec0aa1109d6.zip
update rest
grapher is still broken refactored io / error handling a bit
-rw-r--r--common/common.vcxitems1
-rw-r--r--common/rawaccel-error.hpp27
-rw-r--r--common/rawaccel-io-def.h4
-rw-r--r--common/rawaccel-io.hpp123
-rw-r--r--common/rawaccel-validate.hpp168
-rw-r--r--common/rawaccel-version.h30
-rw-r--r--common/utility.hpp4
-rw-r--r--converter/converter.cpp62
-rw-r--r--driver/driver.cpp2
-rw-r--r--driver/driver.h3
-rw-r--r--grapher/Properties/AssemblyInfo.cs4
-rw-r--r--wrapper/wrapper.cpp463
-rw-r--r--wrapper/wrapper.vcxproj2
-rw-r--r--wrapper/wrapper.vcxproj.filters6
-rw-r--r--wrapper/wrapper_io.cpp40
-rw-r--r--wrapper/wrapper_io.hpp25
-rw-r--r--writer/Program.cs38
-rw-r--r--writer/Properties/AssemblyInfo.cs4
18 files changed, 508 insertions, 498 deletions
diff --git a/common/common.vcxitems b/common/common.vcxitems
index 4cbe2b7..6d1b861 100644
--- a/common/common.vcxitems
+++ b/common/common.vcxitems
@@ -26,6 +26,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-io-def.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-io.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-base.hpp" />
+ <ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-validate.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-version.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)utility-install.hpp" />
diff --git a/common/rawaccel-error.hpp b/common/rawaccel-error.hpp
index cdbe1e5..a9cb7b8 100644
--- a/common/rawaccel-error.hpp
+++ b/common/rawaccel-error.hpp
@@ -1,11 +1,12 @@
#pragma once
-#include <stdexcept>
+#include <system_error>
+#include <string>
namespace rawaccel {
- class error : public std::runtime_error {
- using std::runtime_error::runtime_error;
+ class error : public std::runtime_error {
+ using std::runtime_error::runtime_error;
};
class io_error : public error {
@@ -14,7 +15,25 @@ namespace rawaccel {
class install_error : public io_error {
public:
- install_error() : io_error("Raw Accel driver is not installed, run installer.exe") {}
+ install_error() :
+ io_error("Raw Accel is not installed, run installer.exe") {}
+ };
+
+ class sys_error : public io_error {
+ public:
+ sys_error(const char* msg, DWORD code = GetLastError()) :
+ io_error(build_msg(code, msg)) {}
+
+ static std::string build_msg(DWORD code, const char* msg)
+ {
+ std::string ret =
+ std::system_error(code, std::system_category(), msg).what();
+ ret += " (";
+ ret += std::to_string(code);
+ ret += ")";
+ return ret;
+ }
+
};
}
diff --git a/common/rawaccel-io-def.h b/common/rawaccel-io-def.h
index e169390..399e0f2 100644
--- a/common/rawaccel-io-def.h
+++ b/common/rawaccel-io-def.h
@@ -1,9 +1,11 @@
#pragma once
+#define NOMINMAX
+
#ifdef _KERNEL_MODE
#include <ntddk.h>
#else
-#include <winioctl.h>
+#include <Windows.h>
#endif
#define RA_DEV_TYPE 0x8888u
diff --git a/common/rawaccel-io.hpp b/common/rawaccel-io.hpp
index da496fa..a80e254 100644
--- a/common/rawaccel-io.hpp
+++ b/common/rawaccel-io.hpp
@@ -1,67 +1,84 @@
#pragma once
#include "rawaccel-io-def.h"
-#include "rawaccel.hpp"
#include "rawaccel-version.h"
#include "rawaccel-error.hpp"
-
-#define NOMINMAX
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-#include <system_error>
+#include "rawaccel.hpp"
#pragma warning(push)
#pragma warning(disable:4245) // int -> DWORD conversion while passing CTL_CODE
namespace rawaccel {
- inline void io_control(DWORD code, void* in, DWORD in_size, void* out, DWORD out_size)
- {
- HANDLE ra_handle = INVALID_HANDLE_VALUE;
-
- ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0);
-
- if (ra_handle == INVALID_HANDLE_VALUE) {
- throw install_error();
- }
-
- DWORD dummy;
-
- BOOL success = DeviceIoControl(
- ra_handle,
- code,
- in,
- in_size,
- out,
- out_size,
- &dummy, // bytes returned
- NULL // overlapped structure
- );
-
- CloseHandle(ra_handle);
-
- if (!success) {
- throw std::system_error(GetLastError(), std::system_category(), "DeviceIoControl failed");
- }
- }
-
- inline void read(io_t& args)
- {
- io_control(RA_READ, NULL, 0, &args, sizeof(io_t));
- }
-
- inline void write(const io_t& args)
- {
- io_control(RA_WRITE, const_cast<io_t*>(&args), sizeof(io_t), NULL, 0);
- }
-
- inline version_t get_version()
- {
- version_t ver;
- io_control(RA_GET_VERSION, NULL, 0, &ver, sizeof(version_t));
- return ver;
- }
+ inline void io_control(DWORD code, void* in, DWORD in_size, void* out, DWORD out_size)
+ {
+ HANDLE ra_handle = INVALID_HANDLE_VALUE;
+
+ ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0);
+
+ if (ra_handle == INVALID_HANDLE_VALUE) {
+ throw install_error();
+ }
+
+ DWORD dummy;
+
+ BOOL success = DeviceIoControl(
+ ra_handle,
+ code,
+ in,
+ in_size,
+ out,
+ out_size,
+ &dummy, // bytes returned
+ NULL // overlapped structure
+ );
+
+ CloseHandle(ra_handle);
+
+ if (!success) {
+ throw sys_error("DeviceIoControl failed");
+ }
+ }
+
+ inline void read(io_t& args)
+ {
+ io_control(RA_READ, NULL, 0, &args, sizeof(io_t));
+ }
+
+ inline void write(const io_t& args)
+ {
+ io_control(RA_WRITE, const_cast<io_t*>(&args), sizeof(io_t), NULL, 0);
+ }
+
+ inline version_t get_version()
+ {
+ version_t v;
+
+ try {
+ io_control(RA_GET_VERSION, NULL, 0, &v, sizeof(version_t));
+ }
+ catch (const sys_error&) {
+ // assume request is not implemented (< 1.3)
+ v = { 0 };
+ }
+
+ return v;
+ }
+
+ inline version_t valid_version_or_throw()
+ {
+ auto v = get_version();
+
+ if (v < min_driver_version) {
+ throw error("reinstallation required");
+ }
+
+ if (version < v) {
+ throw error("newer driver is installed");
+ }
+
+ return v;
+ }
}
diff --git a/common/rawaccel-validate.hpp b/common/rawaccel-validate.hpp
new file mode 100644
index 0000000..b9ee2af
--- /dev/null
+++ b/common/rawaccel-validate.hpp
@@ -0,0 +1,168 @@
+#pragma once
+
+#include "rawaccel-base.hpp"
+#include "utility.hpp"
+
+namespace rawaccel {
+
+ struct valid_ret_t {
+ int count_x = 0;
+ int count_y = 0;
+ int count = 0;
+
+ explicit operator bool() const
+ {
+ return count == 0;
+ }
+ };
+
+ template <typename MsgHandler = noop>
+ valid_ret_t valid(const settings& args, MsgHandler fn = {})
+ {
+ valid_ret_t ret;
+
+ auto error = [&](auto msg) {
+ ++ret.count;
+ fn(msg);
+ };
+
+ auto check_accel = [&error](const accel_args& args) {
+ static_assert(LUT_CAPACITY == 1025, "update error msg");
+
+ const auto& lut_args = args.lut_args;
+
+ if (lut_args.partitions <= 0) {
+ error("lut partitions"" must be positive");
+ }
+
+ if (lut_args.mode == table_mode::linear) {
+ if (lut_args.start <= 0) {
+ error("start"" must be positive");
+ }
+
+ if (lut_args.stop <= lut_args.start) {
+ error("stop must be greater than start");
+ }
+
+ if (lut_args.num_elements < 2 ||
+ lut_args.num_elements > 1025) {
+ error("num must be between 2 and 1025");
+ }
+ }
+ else if (lut_args.mode == table_mode::binlog) {
+ int istart = static_cast<int>(lut_args.start);
+ int istop = static_cast<int>(lut_args.stop);
+
+ if (lut_args.start < -99) {
+ error("start is too small");
+ }
+ else if (lut_args.stop > 99) {
+ error("stop is too large");
+ }
+ else if (istart != lut_args.start || istop != lut_args.stop) {
+ error("start and stop must be integers");
+ }
+ else if (istop <= istart) {
+ error("stop must be greater than start");
+ }
+ else if (lut_args.num_elements <= 0) {
+ error("num"" must be positive");
+ }
+ else if (((lut_args.stop - lut_args.start) * lut_args.num_elements) >= 1025) {
+ error("binlog mode requires (num * (stop - start)) < 1025");
+ }
+ }
+
+ if (args.offset < 0) {
+ error("offset can not be negative");
+ }
+
+ if (args.cap <= 0) {
+ error("cap"" must be positive");
+ }
+
+ if (args.accel_motivity <= 0 ||
+ args.accel_natural <= 0 ||
+ args.accel_classic <= 0) {
+ error("acceleration"" must be positive");
+ }
+
+ if (args.motivity <= 1) {
+ error("motivity must be greater than 1");
+ }
+
+ if (args.power <= 1) {
+ error("power must be greater than 1");
+ }
+
+ if (args.scale <= 0) {
+ error("scale"" must be positive");
+ }
+
+ if (args.weight <= 0) {
+ error("weight"" must be positive");
+ }
+
+ if (args.exponent <= 0) {
+ error("exponent"" must be positive");
+ }
+
+ if (args.limit <= 0) {
+ error("limit"" must be positive");
+ }
+
+ if (args.midpoint <= 0) {
+ error("midpoint"" must be positive");
+ }
+
+ if (args.smooth < 0 || args.smooth > 1) {
+ error("smooth must be between 0 and 1");
+ }
+
+ };
+
+ check_accel(args.argsv.x);
+
+ if (!args.combine_mags) {
+ ret.count_x = ret.count;
+ check_accel(args.argsv.y);
+ ret.count_y = ret.count;
+ }
+
+ if (args.dpi <= 0) {
+ error("dpi"" must be positive");
+ }
+
+ if (args.speed_cap <= 0) {
+ error("speed cap"" must be positive");
+ }
+
+ if (args.sens.x == 0 || args.sens.y == 0) {
+ error("sens multiplier is 0");
+ }
+
+ if (args.dom_args.domain_weights.x <= 0 ||
+ args.dom_args.domain_weights.y <= 0) {
+ error("domain weights"" must be positive");
+ }
+
+ if (args.dom_args.lp_norm <= 0) {
+ error("Lp norm can not be negative");
+ }
+
+ if (args.dir_multipliers.x < 0 || args.dir_multipliers.y < 0) {
+ error("directional multipliers can not be negative");
+ }
+
+ if (args.range_weights.x <= 0 || args.range_weights.y <= 0) {
+ error("range weights"" must be positive");
+ }
+
+ if (args.time_min <= 0) {
+ error("minimum time"" must be positive");
+ }
+
+ return ret;
+ }
+
+}
diff --git a/common/rawaccel-version.h b/common/rawaccel-version.h
index 40ff2d2..de8644b 100644
--- a/common/rawaccel-version.h
+++ b/common/rawaccel-version.h
@@ -6,21 +6,31 @@
#define RA_OS "Win7+"
-#define M_STR_HELPER(x) #x
-#define M_STR(x) M_STR_HELPER(x)
+#define RA_M_STR_HELPER(x) #x
+#define RA_M_STR(x) RA_M_STR_HELPER(x)
-#define RA_VER_STRING M_STR(RA_VER_MAJOR) "." M_STR(RA_VER_MINOR) "." M_STR(RA_VER_PATCH)
+#define RA_VER_STRING RA_M_STR(RA_VER_MAJOR) "." RA_M_STR(RA_VER_MINOR) "." RA_M_STR(RA_VER_PATCH)
namespace rawaccel {
- struct version_t {
- int major;
- int minor;
- int patch;
- };
-
+ struct version_t {
+ int major;
+ int minor;
+ int patch;
+ };
+
+ constexpr bool operator<(const version_t& lhs, const version_t& rhs)
+ {
+ return (lhs.major != rhs.major) ?
+ (lhs.major < rhs.major) :
+ (lhs.minor != rhs.minor) ?
+ (lhs.minor < rhs.minor) :
+ (lhs.patch < rhs.patch) ;
+ }
+
+ inline constexpr version_t version = { RA_VER_MAJOR, RA_VER_MINOR, RA_VER_PATCH };
#ifndef _KERNEL_MODE
- inline constexpr version_t min_driver_version = { 1, 4, 0 };
+ inline constexpr version_t min_driver_version = { 1, 4, 0 };
#endif
}
diff --git a/common/utility.hpp b/common/utility.hpp
index de90d44..5f5c186 100644
--- a/common/utility.hpp
+++ b/common/utility.hpp
@@ -81,4 +81,8 @@ namespace rawaccel {
return ilogb(x) == 0x400;
}
+ struct noop {
+ template <typename... Ts>
+ constexpr void operator()(Ts&&...) const noexcept {}
+ };
}
diff --git a/converter/converter.cpp b/converter/converter.cpp
index 230e1be..7b71af3 100644
--- a/converter/converter.cpp
+++ b/converter/converter.cpp
@@ -1,3 +1,5 @@
+#include <rawaccel-base.hpp>
+
#include <array>
#include <charconv>
#include <filesystem>
@@ -7,8 +9,6 @@
#include <sstream>
#include <string>
-#include <rawaccel-settings.h>
-
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace Newtonsoft::Json;
@@ -108,7 +108,7 @@ auto make_extractor(const ia_settings_t& ia_settings) {
};
}
-ra::accel_args convert_natural(const ia_settings_t& ia_settings) {
+ra::accel_args convert_natural(const ia_settings_t& ia_settings, bool legacy) {
auto get = make_extractor(ia_settings);
double accel = get("Acceleration").value_or(0);
@@ -117,8 +117,13 @@ ra::accel_args convert_natural(const ia_settings_t& ia_settings) {
double prescale = get("Pre-ScaleX").value_or(1);
ra::accel_args args;
+
args.limit = 1 + std::abs(cap - sens) / sens;
- args.accel = accel * prescale / sens;
+ args.accel_natural = accel * prescale / sens;
+ args.offset = get("Offset").value_or(0);
+ args.mode = ra::accel_mode::natural;
+ args.legacy = legacy;
+
return args;
}
@@ -130,25 +135,16 @@ ra::accel_args convert_quake(const ia_settings_t& ia_settings, bool legacy) {
double cap = get("SensitivityCap").value_or(0);
double sens = get("Sensitivity").value_or(1);
double prescale = get("Pre-ScaleX").value_or(1);
- double offset = get("Offset").value_or(0);
-
- ra::accel_args args;
- double powm1 = power - 1;
- double rpowm1 = 1 / powm1;
- double accel_b = std::pow(accel * prescale, powm1) / sens;
- args.accel = std::pow(accel_b, rpowm1);
- args.exponent = power;
- args.legacy_offset = legacy;
- args.offset = offset;
- double cap_converted = cap / sens;
+ ra::accel_args args;
- if (legacy || cap_converted <= 1) {
- args.scale_cap = cap_converted;
- }
- else {
- args.gain_cap = offset + std::pow(cap_converted - 1, rpowm1) / args.accel;
- }
+ double accel_b = std::pow(accel * prescale, power - 1) / sens;
+ args.accel_classic = std::pow(accel_b, 1 / (power - 1));
+ args.cap = cap / sens;
+ args.power = power;
+ args.offset = get("Offset").value_or(0);
+ args.mode = ra::accel_mode::classic;
+ args.legacy = legacy;
return args;
}
@@ -168,17 +164,15 @@ bool try_convert(const ia_settings_t& ia_settings) {
switch (static_cast<IA_MODES_ENUM>(mode)) {
case IA_QL: {
- bool legacy = !ask("We recommend trying out our new cap and offset styles.\n"
- "Use new cap and offset?");
- ra_settings.modes.x = ra::accel_mode::classic;
+ bool legacy = !ask("We recommend trying out a new smooth cap style.\n"
+ "Use new cap style?");
ra_settings.argsv.x = convert_quake(ia_settings, legacy);
break;
}
case IA_NAT: {
- bool nat_gain = ask("Raw Accel offers a new mode that you might like more than Natural.\n"
+ bool legacy = !ask("Raw Accel offers a new mode that you might like more than Natural.\n"
"Wanna try it out now?");
- ra_settings.modes.x = nat_gain ? ra::accel_mode::naturalgain : ra::accel_mode::natural;
- ra_settings.argsv.x = convert_natural(ia_settings);
+ ra_settings.argsv.x = convert_natural(ia_settings, legacy);
break;
}
case IA_LOG: {
@@ -189,7 +183,7 @@ bool try_convert(const ia_settings_t& ia_settings) {
}
DriverSettings^ new_settings = Marshal::PtrToStructure<DriverSettings^>((IntPtr)&ra_settings);
- auto errors = DriverInterop::GetSettingsErrors(new_settings);
+ auto errors = gcnew SettingsErrors(new_settings);
if (!errors->Empty()) {
Console::WriteLine("Bad settings: {0}", errors);
@@ -197,7 +191,7 @@ bool try_convert(const ia_settings_t& ia_settings) {
}
Console::Write("Sending to driver... ");
- DriverInterop::Write(new_settings);
+ (gcnew ManagedAccel(new_settings))->Activate();
Console::WriteLine("done");
Console::Write("Generating settings.json... ");
@@ -208,10 +202,6 @@ bool try_convert(const ia_settings_t& ia_settings) {
return true;
}
-public ref struct ASSEMBLY {
- static initonly Version^ VERSION = ASSEMBLY::typeid->Assembly->GetName()->Version;
-};
-
int main()
{
auto close_prompt = [] {
@@ -221,9 +211,9 @@ int main()
};
try {
- VersionHelper::ValidateAndGetDriverVersion(ASSEMBLY::VERSION);
+ VersionHelper::ValidOrThrow();
}
- catch (VersionException^ ex) {
+ catch (InteropException^ ex) {
Console::WriteLine(ex->Message);
close_prompt();
}
@@ -239,7 +229,7 @@ int main()
entry.path().extension() == IA_PROFILE_EXT) {
opt_path = entry;
break;
- }
+ }
}
}
diff --git a/driver/driver.cpp b/driver/driver.cpp
index 89f09dc..fbc2d3d 100644
--- a/driver/driver.cpp
+++ b/driver/driver.cpp
@@ -210,7 +210,7 @@ Return Value:
DebugPrint(("RetrieveOutputBuffer failed: 0x%x\n", status));
}
else {
- *reinterpret_cast<ra::version_t*>(buffer) = { RA_VER_MAJOR, RA_VER_MINOR, RA_VER_PATCH };
+ *reinterpret_cast<ra::version_t*>(buffer) = ra::version;
bytes_out = sizeof(ra::version_t);
}
break;
diff --git a/driver/driver.h b/driver/driver.h
index 56742f6..6184a69 100644
--- a/driver/driver.h
+++ b/driver/driver.h
@@ -1,9 +1,8 @@
#pragma once
#include "rawaccel-base.hpp"
+#include "rawaccel-io-def.h"
-#define NOMINMAX
-#include <ntddk.h>
#include <kbdmou.h>
#include <wdf.h>
diff --git a/grapher/Properties/AssemblyInfo.cs b/grapher/Properties/AssemblyInfo.cs
index a46d6b3..d381102 100644
--- a/grapher/Properties/AssemblyInfo.cs
+++ b/grapher/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion(RawAccelVersion.value)]
-[assembly: AssemblyFileVersion(RawAccelVersion.value)]
+[assembly: AssemblyVersion(VersionHelper.VersionString)]
+[assembly: AssemblyFileVersion(VersionHelper.VersionString)]
diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp
index 71a8cf6..757972b 100644
--- a/wrapper/wrapper.cpp
+++ b/wrapper/wrapper.cpp
@@ -1,17 +1,16 @@
#pragma once
+#include <rawaccel-io.hpp>
+#include <rawaccel-validate.hpp>
+#include <utility-rawinput.hpp>
+
#include <algorithm>
#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::IO;
using namespace System::Runtime::InteropServices;
using namespace System::Reflection;
@@ -19,34 +18,39 @@ using namespace Windows::Forms;
using namespace Newtonsoft::Json;
+namespace ra = rawaccel;
+
+ra::settings default_settings;
+
[JsonConverter(Converters::StringEnumConverter::typeid)]
public enum class AccelMode
{
- linear, classic, natural, naturalgain, power, motivity, noaccel
+ classic, jump, natural, power, motivity, noaccel
+};
+
+public enum class TableMode
+{
+ off, binlog, linear
};
-[JsonObject(ItemRequired = Required::Always)]
[StructLayout(LayoutKind::Sequential)]
-public value struct AccelArgs
+public value struct TableArgs
{
- double offset;
+ [JsonIgnore]
+ TableMode mode;
+
[MarshalAs(UnmanagedType::U1)]
- bool legacyOffset;
- double acceleration;
- double scale;
- double limit;
- double exponent;
- double midpoint;
- double weight;
- [JsonProperty("legacyCap")]
- double scaleCap;
- double gainCap;
- [JsonProperty(Required = Required::Default)]
- double speedCap;
+ bool transfer;
+
+ [MarshalAs(UnmanagedType::U1)]
+ unsigned char partitions;
+
+ short num;
+ double start;
+ double stop;
};
generic <typename T>
-[JsonObject(ItemRequired = Required::Always)]
[StructLayout(LayoutKind::Sequential)]
public value struct Vec2
{
@@ -54,7 +58,32 @@ public value struct Vec2
T y;
};
-[JsonObject(ItemRequired = Required::Always)]
+[StructLayout(LayoutKind::Sequential)]
+public value struct AccelArgs
+{
+ AccelMode mode;
+
+ [MarshalAs(UnmanagedType::U1)]
+ bool legacy;
+
+ [JsonProperty(Required = Required::Default)]
+ TableArgs lutArgs;
+
+ double offset;
+ double cap;
+ double accelClassic;
+ double accelNatural;
+ double accelMotivity;
+ double motivity;
+ double power;
+ double scale;
+ double weight;
+ double exponent;
+ double limit;
+ double midpoint;
+ double smooth;
+};
+
[StructLayout(LayoutKind::Sequential)]
public value struct DomainArgs
{
@@ -66,20 +95,22 @@ public value struct DomainArgs
[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)]
public ref struct DriverSettings
{
+ literal double WriteDelayMs = ra::WRITE_DELAY;
literal String^ Key = "Driver settings";
[JsonProperty("Degrees of rotation")]
double rotation;
- [JsonProperty("Degrees of angle snapping", Required = Required::Default)]
+ [JsonProperty("Degrees of angle snapping")]
double snap;
[JsonProperty("Use x as whole/combined accel")]
[MarshalAs(UnmanagedType::U1)]
bool combineMagnitudes;
- [JsonProperty("Accel modes")]
- Vec2<AccelMode> modes;
+ double dpi;
+
+ double speedCap;
[JsonProperty("Accel parameters")]
Vec2<AccelArgs> args;
@@ -87,192 +118,125 @@ public ref struct DriverSettings
[JsonProperty("Sensitivity multipliers")]
Vec2<double> sensitivity;
- [JsonProperty("Negative directional multipliers", Required = Required::Default)]
+ [JsonProperty("Negative directional multipliers")]
Vec2<double> directionalMultipliers;
- [JsonProperty("Stretches domain for horizontal vs vertical inputs", Required = Required::Default)]
+ [JsonProperty("Stretches domain for horizontal vs vertical inputs")]
DomainArgs domainArgs;
- [JsonProperty("Stretches accel range for horizontal vs vertical inputs", Required = Required::Default)]
+ [JsonProperty("Stretches accel range for horizontal vs vertical inputs")]
Vec2<double> rangeXY;
[JsonProperty(Required = Required::Default)]
double minimumTime;
- [JsonProperty("Device ID", Required = Required::Default)]
- [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)]
+ [JsonProperty("Device ID")]
+ [MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_DEV_ID_LEN)]
String^ deviceID = "";
bool ShouldSerializeminimumTime()
{
- return minimumTime > 0 && minimumTime != DEFAULT_TIME_MIN;
+ return minimumTime != ra::DEFAULT_TIME_MIN;
}
DriverSettings()
{
- domainArgs = { { 1, 1 }, 2 };
- rangeXY = { 1, 1 };
+ Marshal::PtrToStructure(IntPtr(&default_settings), this);
}
-};
-
-
-template <typename NativeSettingsFunc>
-void as_native(DriverSettings^ managed_args, NativeSettingsFunc fn)
-{
-#ifndef NDEBUG
- if (Marshal::SizeOf(managed_args) != sizeof(settings))
- throw gcnew InvalidOperationException("setting sizes differ");
-#endif
- settings args;
- Marshal::StructureToPtr(managed_args, (IntPtr)&args, false);
- fn(args);
- if constexpr (!std::is_invocable_v<NativeSettingsFunc, const settings&>) {
- Marshal::PtrToStructure((IntPtr)&args, managed_args);
- }
-}
-
-DriverSettings^ get_default()
-{
- DriverSettings^ managed = gcnew DriverSettings();
- as_native(managed, [](settings& args) {
- args = {};
- });
- return managed;
-}
-
-void set_active(DriverSettings^ managed)
-{
- as_native(managed, [](const settings& args) {
- wrapper_io::writeToDriver(args);
- });
-}
-
-DriverSettings^ get_active()
-{
- DriverSettings^ managed = gcnew DriverSettings();
- as_native(managed, [](settings& args) {
- wrapper_io::readFromDriver(args);
- });
- return managed;
-}
-
-void update_modifier(mouse_modifier& mod, DriverSettings^ managed, vec2<si_pair*> luts = {})
-{
- as_native(managed, [&](const settings& args) {
- mod = { args, luts };
- });
-}
-
-using error_list_t = Collections::Generic::List<String^>;
-
-error_list_t^ get_accel_errors(AccelMode mode, AccelArgs^ args)
-{
- accel_mode mode_native = (accel_mode)mode;
-
- auto is_mode = [mode_native](auto... modes) {
- return ((mode_native == modes) || ...);
- };
- using am = accel_mode;
+ void ToFile(String^ path)
+ {
+ using namespace Newtonsoft::Json::Linq;
- auto error_list = gcnew error_list_t();
-
- if (args->acceleration > 10 && is_mode(am::natural, am::naturalgain))
- error_list->Add("acceleration can not be greater than 10");
- else if (args->acceleration == 0 && is_mode(am::naturalgain))
- error_list->Add("acceleration must be positive");
- else if (args->acceleration < 0) {
- bool additive = mode_native < am::power;
- if (additive) error_list->Add("acceleration can not be negative, use a negative weight to compensate");
- else error_list->Add("acceleration can not be negative");
+ JObject^ thisJO = JObject::FromObject(this);
+ String^ modes = String::Join(" | ", Enum::GetNames(AccelMode::typeid));
+ thisJO->AddFirst(gcnew JProperty("### Accel Modes ###", modes));
+ File::WriteAllText(path, thisJO->ToString(Formatting::Indented));
}
-
- if (args->scale <= 0)
- error_list->Add("scale must be positive");
- if (args->exponent <= 1 && is_mode(am::classic))
- error_list->Add("exponent must be greater than 1");
- else if (args->exponent <= 0)
- error_list->Add("exponent must be positive");
+ static DriverSettings^ FromFile(String^ path)
+ {
+ if (!File::Exists(path))
+ {
+ throw gcnew FileNotFoundException(
+ String::Format("Settings file not found at {0}", path));
+ }
- if (args->limit <= 1)
- error_list->Add("limit must be greater than 1");
+ auto settings = JsonConvert::DeserializeObject<DriverSettings^>(
+ File::ReadAllText(path));
- if (args->midpoint <= 0)
- error_list->Add("midpoint must be positive");
+ if (settings == nullptr) {
+ throw gcnew JsonException(String::Format("{0} contains invalid JSON", path));
+ }
- if (args->offset < 0)
- error_list->Add("offset can not be negative");
+ return settings;
+ }
+};
- return error_list;
-}
+public ref struct InteropException : public Exception {
+public:
+ InteropException(String^ what) :
+ Exception(what) {}
+ InteropException(const char* what) :
+ Exception(gcnew String(what)) {}
+ InteropException(const std::exception& e) :
+ InteropException(e.what()) {}
+};
-error_list_t^ get_other_errors(DriverSettings^ settings)
+public ref class SettingsErrors
{
- auto error_list = gcnew error_list_t();
+public:
+ List<String^>^ list;
+ int countX;
+ int countY;
- if (settings->rangeXY.x <= 0 || settings->rangeXY.y <= 0)
- {
- error_list->Add("range values must be positive");
- }
+ delegate void MsgHandler(const char*);
- if (settings->domainArgs.domainXY.x <= 0 || settings->domainArgs.domainXY.y <= 0)
+ void Add(const char* msg)
{
- error_list->Add("domain values must be positive");
+ list->Add(msclr::interop::marshal_as<String^>(msg));
}
- if (settings->domainArgs.lpNorm <= 0)
+ SettingsErrors(DriverSettings^ settings)
{
- error_list->Add("lp norm must be positive");
- }
-
- return error_list;
-}
+ MsgHandler^ del = gcnew MsgHandler(this, &SettingsErrors::Add);
+ GCHandle gch = GCHandle::Alloc(del);
+ auto fp = static_cast<void (*)(const char*)>(
+ Marshal::GetFunctionPointerForDelegate(del).ToPointer());
-public ref class SettingsErrors
-{
-public:
- error_list_t^ x;
- error_list_t^ y;
- error_list_t^ other;
+ ra::settings args;
+ Marshal::StructureToPtr(settings, (IntPtr)&args, false);
+
+ list = gcnew List<String^>();
+ auto [cx, cy, _] = ra::valid(args, fp);
+ countX = cx;
+ countY = cy;
+
+ gch.Free();
+ }
bool Empty()
{
- return (x == nullptr || x->Count == 0) &&
- (y == nullptr || y->Count == 0) &&
- (other == nullptr || other->Count == 0);
+ return list->Count == 0;
}
- virtual String^ ToString() override
+ virtual String^ ToString() override
{
- if (x == nullptr) throw;
-
Text::StringBuilder^ sb = gcnew Text::StringBuilder();
- if (y == nullptr) // assume combineMagnitudes
+ for each (auto s in list->GetRange(0, countX))
{
- for each (String^ str in x)
- {
- sb->AppendLine(str);
- }
+ sb->AppendFormat("x: {0}\n", s);
}
- else
+ for each (auto s in list->GetRange(countX, countY))
{
- for each (String^ str in x)
- {
- sb->AppendFormat("x: {0}\n", str);
- }
- for each (String^ str in y)
- {
- sb->AppendFormat("y: {0}\n", str);
- }
+ sb->AppendFormat("y: {0}\n", s);
}
-
- for each (String ^ str in other)
+ for each (auto s in list->GetRange(countY, list->Count))
{
- sb->AppendLine(str);
+ sb->AppendLine(s);
}
-
+
return sb->ToString();
}
};
@@ -314,7 +278,7 @@ public ref struct RawInputInterop
}
catch (const std::exception& e)
{
- throw gcnew System::Exception(gcnew String(e.what()));
+ throw gcnew InteropException(e);
}
}
@@ -336,80 +300,32 @@ public ref struct RawInputInterop
}
catch (const std::exception& e)
{
- throw gcnew System::Exception(gcnew String(e.what()));
+ throw gcnew InteropException(e);
}
}
};
-public ref struct DriverInterop
+public ref class ManagedAccel
{
- literal double WriteDelayMs = WRITE_DELAY;
- static initonly DriverSettings^ DefaultSettings = get_default();
-
- static DriverSettings^ GetActiveSettings()
- {
- return get_active();
- }
-
- static void Write(DriverSettings^ args)
- {
- set_active(args);
- }
+ ra::io_t* const instance = new ra::io_t();
- static DriverSettings^ GetDefaultSettings()
- {
- return get_default();
- }
+public:
+ ManagedAccel() {};
- static SettingsErrors^ GetSettingsErrors(DriverSettings^ args)
+ ManagedAccel(DriverSettings^ settings)
{
- auto errors = gcnew SettingsErrors();
-
- errors->x = get_accel_errors(args->modes.x, args->args.x);
-
- if (!args->combineMagnitudes) {
- errors->y = get_accel_errors(args->modes.y, args->args.y);
- }
-
- errors->other = get_other_errors(args);
-
- return errors;
+ Settings = settings;
}
-
-
- static error_list_t^ GetAccelErrors(AccelMode mode, AccelArgs^ args)
- {
- return get_accel_errors(mode, args);
- }
-};
-
-public ref class ManagedAccel
-{
- mouse_modifier* const modifier_instance = new mouse_modifier();
-#ifdef RA_LOOKUP
- si_pair* const lut_x = new si_pair[LUT_SIZE];
- si_pair* const lut_y = new si_pair[LUT_SIZE];
-#else
- si_pair* lut_x = nullptr;
- si_pair* lut_y = nullptr;
-#endif
-
-public:
-
virtual ~ManagedAccel()
{
- delete modifier_instance;
- delete[] lut_x;
- delete[] lut_y;
+ delete instance;
}
!ManagedAccel()
{
- delete modifier_instance;
- delete[] lut_x;
- delete[] lut_y;
+ delete instance;
}
Tuple<double, double>^ Accelerate(int x, int y, double time)
@@ -418,89 +334,64 @@ public:
(double)x,
(double)y
};
- modifier_instance->modify(in_out_vec, time);
+
+ instance->mod.modify(in_out_vec, time);
return gcnew Tuple<double, double>(in_out_vec.x, in_out_vec.y);
}
- void UpdateFromSettings(DriverSettings^ args)
+ void Activate()
{
- update_modifier(
- *modifier_instance,
- args,
- vec2<si_pair*>{ lut_x, lut_y }
- );
+ try {
+ ra::write(*instance);
+ }
+ catch (const ra::error& e) {
+ throw gcnew InteropException(e);
+ }
}
- static ManagedAccel^ GetActiveAccel()
+ property DriverSettings^ Settings
{
- settings args;
- wrapper_io::readFromDriver(args);
+ DriverSettings^ get()
+ {
+ DriverSettings^ settings = gcnew DriverSettings();
+ Marshal::PtrToStructure(IntPtr(&instance->args), settings);
+ return settings;
+ }
- auto active = gcnew ManagedAccel();
- *active->modifier_instance = {
- args
- , vec2<si_pair*> { active->lut_x, active->lut_y }
- };
- return active;
- }
-};
+ void set(DriverSettings^ val)
+ {
+ Marshal::StructureToPtr(val, IntPtr(&instance->args), false);
+ instance->mod = { instance->args };
+ }
-public ref struct RawAccelVersion
-{
- literal String^ value = RA_VER_STRING;
-};
+ }
-public ref struct VersionException : public Exception
-{
-public:
- VersionException() {}
- VersionException(String^ what) : Exception(what) {}
+ static ManagedAccel^ GetActive()
+ {
+ try {
+ auto active = gcnew ManagedAccel();
+ ra::read(*active->instance);
+ return active;
+ }
+ catch (const ra::error& e) {
+ throw gcnew InteropException(e);
+ }
+ }
};
-Version^ convert(rawaccel::version_t v)
-{
- return gcnew Version(v.major, v.minor, v.patch, 0);
-}
-
public ref struct VersionHelper
{
+ literal String^ VersionString = RA_VER_STRING;
- static Version^ ValidateAndGetDriverVersion(Version^ wrapperTarget)
+ static Version^ ValidOrThrow()
{
- Version^ wrapperActual = VersionHelper::typeid->Assembly->GetName()->Version;
-
- if (wrapperTarget != wrapperActual) {
- throw gcnew VersionException("version mismatch, expected wrapper.dll v" + wrapperActual);
- }
-
- version_t drv_ver;
-
try {
- wrapper_io::getDriverVersion(drv_ver);
- }
- catch (DriverNotInstalledException^ ex) {
- throw gcnew VersionException(ex->Message);
- }
- catch (DriverIOException^) {
- // Assume version ioctl is unimplemented (driver version < v1.3.0)
- throw gcnew VersionException("driver version is out of date\n\nrun installer.exe to reinstall");
- }
-
- Version^ drv_ver_managed = convert(drv_ver);
-
- if (drv_ver_managed < convert(min_driver_version)) {
- throw gcnew VersionException(
- String::Format("driver version is out of date (v{0})\n\nrun installer.exe to reinstall",
- drv_ver_managed));
- }
- else if (drv_ver_managed > wrapperActual) {
- throw gcnew VersionException(
- String::Format("newer driver version is installed (v{0})",
- drv_ver_managed));
+ ra::version_t v = ra::valid_version_or_throw();
+ return gcnew Version(v.major, v.minor, v.patch, 0);
}
- else {
- return drv_ver_managed;
+ catch (const ra::error& e) {
+ throw gcnew InteropException(e);
}
}
diff --git a/wrapper/wrapper.vcxproj b/wrapper/wrapper.vcxproj
index 721a981..fba03a7 100644
--- a/wrapper/wrapper.vcxproj
+++ b/wrapper/wrapper.vcxproj
@@ -84,12 +84,10 @@ copy /Y "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)signed\Newtonsoft.Json.
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
- <ClInclude Include="wrapper_io.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="wrapper.cpp" />
- <ClCompile Include="wrapper_io.cpp" />
</ItemGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json">
diff --git a/wrapper/wrapper.vcxproj.filters b/wrapper/wrapper.vcxproj.filters
index f265d72..96b8e1a 100644
--- a/wrapper/wrapper.vcxproj.filters
+++ b/wrapper/wrapper.vcxproj.filters
@@ -15,9 +15,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="wrapper_io.hpp">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -26,9 +23,6 @@
<ClCompile Include="wrapper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="wrapper_io.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/wrapper/wrapper_io.cpp b/wrapper/wrapper_io.cpp
deleted file mode 100644
index 4b77174..0000000
--- a/wrapper/wrapper_io.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-#include <rawaccel-io.hpp>
-#include "wrapper_io.hpp"
-
-auto with_managed_ex = [](auto fn) {
- try
- {
- fn();
- }
- catch (const install_error&)
- {
- throw gcnew DriverNotInstalledException();
- }
- catch (const std::system_error& e)
- {
- throw gcnew DriverIOException(gcnew String(e.what()));
- }
-};
-
-void wrapper_io::writeToDriver(const settings& args)
-{
- with_managed_ex([&] {
- write(args);
- });
-}
-
-void wrapper_io::readFromDriver(settings& args)
-{
- with_managed_ex([&] {
- args = read();
- });
-}
-
-void wrapper_io::getDriverVersion(version_t& ver)
-{
- with_managed_ex([&] {
- ver = get_version();
- });
-}
diff --git a/wrapper/wrapper_io.hpp b/wrapper/wrapper_io.hpp
deleted file mode 100644
index 6b94e46..0000000
--- a/wrapper/wrapper_io.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <rawaccel-error.hpp>
-#include <rawaccel-settings.h>
-#include <rawaccel-version.h>
-
-using namespace rawaccel;
-using namespace System;
-
-struct wrapper_io {
- static void writeToDriver(const settings&);
- static void readFromDriver(settings&);
- static void getDriverVersion(version_t&);
-};
-
-public ref struct DriverIOException : public IO::IOException {
-public:
- DriverIOException() {}
- DriverIOException(String^ what) : IO::IOException(what) {}
-};
-
-public ref struct DriverNotInstalledException : public DriverIOException {
- DriverNotInstalledException() :
- DriverIOException(gcnew String(install_error().what())) {}
-};
diff --git a/writer/Program.cs b/writer/Program.cs
index 37e384c..d381c16 100644
--- a/writer/Program.cs
+++ b/writer/Program.cs
@@ -16,27 +16,13 @@ namespace writer
MessageBox.Show(msg, "Raw Accel writer");
}
- static void Send(JToken settingsToken)
- {
- var settings = settingsToken.ToObject<DriverSettings>();
-
- var errors = DriverInterop.GetSettingsErrors(settings);
- if (errors.Empty())
- {
- DriverInterop.Write(settings);
- return;
- }
-
- Show($"Bad settings:\n\n{errors}");
- }
-
static void Main(string[] args)
{
try
{
- VersionHelper.ValidateAndGetDriverVersion(typeof(Program).Assembly.GetName().Version);
+ VersionHelper.ValidOrThrow();
}
- catch (VersionException e)
+ catch (InteropException e)
{
Show(e.Message);
return;
@@ -48,23 +34,19 @@ namespace writer
return;
}
- if (!File.Exists(args[0]))
- {
- Show($"Settings file not found at {args[0]}");
- return;
- }
-
try
{
- var JO = JObject.Parse(File.ReadAllText(args[0]));
+ var settings = DriverSettings.FromFile(args[0]);
+ var errors = new SettingsErrors(settings);
- if (JO.ContainsKey(DriverSettings.Key))
+ if (errors.Empty())
{
- Send(JO[DriverSettings.Key]);
- return;
+ new ManagedAccel(settings).Activate();
+ }
+ else
+ {
+ Show($"Bad settings:\n\n{errors}");
}
-
- Send(JO);
}
catch (JsonException e)
{
diff --git a/writer/Properties/AssemblyInfo.cs b/writer/Properties/AssemblyInfo.cs
index fc6a1ca..7f47c6d 100644
--- a/writer/Properties/AssemblyInfo.cs
+++ b/writer/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion(RawAccelVersion.value)]
-[assembly: AssemblyFileVersion(RawAccelVersion.value)]
+[assembly: AssemblyVersion(VersionHelper.VersionString)]
+[assembly: AssemblyFileVersion(VersionHelper.VersionString)] \ No newline at end of file