mirror of
https://github.com/RawAccelOfficial/rawaccel.git
synced 2025-05-11 10:26:58 +02:00
update rest
grapher is still broken refactored io / error handling a bit
This commit is contained in:
parent
fa3ebfb1eb
commit
14bde56daf
18 changed files with 513 additions and 503 deletions
|
@ -26,6 +26,7 @@
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-io-def.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-io-def.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-io.hpp" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-io.hpp" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-base.hpp" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-base.hpp" />
|
||||||
|
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-validate.hpp" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-version.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-version.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)utility-install.hpp" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)utility-install.hpp" />
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <system_error>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace rawaccel {
|
namespace rawaccel {
|
||||||
|
|
||||||
class error : public std::runtime_error {
|
class error : public std::runtime_error {
|
||||||
using std::runtime_error::runtime_error;
|
using std::runtime_error::runtime_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
class io_error : public error {
|
class io_error : public error {
|
||||||
|
@ -14,7 +15,25 @@ namespace rawaccel {
|
||||||
|
|
||||||
class install_error : public io_error {
|
class install_error : public io_error {
|
||||||
public:
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
|
||||||
#ifdef _KERNEL_MODE
|
#ifdef _KERNEL_MODE
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#else
|
#else
|
||||||
#include <winioctl.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RA_DEV_TYPE 0x8888u
|
#define RA_DEV_TYPE 0x8888u
|
||||||
|
|
|
@ -1,67 +1,84 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "rawaccel-io-def.h"
|
#include "rawaccel-io-def.h"
|
||||||
#include "rawaccel.hpp"
|
|
||||||
#include "rawaccel-version.h"
|
#include "rawaccel-version.h"
|
||||||
#include "rawaccel-error.hpp"
|
#include "rawaccel-error.hpp"
|
||||||
|
#include "rawaccel.hpp"
|
||||||
#define NOMINMAX
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#include <system_error>
|
|
||||||
|
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4245) // int -> DWORD conversion while passing CTL_CODE
|
#pragma warning(disable:4245) // int -> DWORD conversion while passing CTL_CODE
|
||||||
|
|
||||||
namespace rawaccel {
|
namespace rawaccel {
|
||||||
|
|
||||||
inline void io_control(DWORD code, void* in, DWORD in_size, void* out, DWORD out_size)
|
inline void io_control(DWORD code, void* in, DWORD in_size, void* out, DWORD out_size)
|
||||||
{
|
{
|
||||||
HANDLE ra_handle = INVALID_HANDLE_VALUE;
|
HANDLE ra_handle = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0);
|
ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0);
|
||||||
|
|
||||||
if (ra_handle == INVALID_HANDLE_VALUE) {
|
if (ra_handle == INVALID_HANDLE_VALUE) {
|
||||||
throw install_error();
|
throw install_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD dummy;
|
DWORD dummy;
|
||||||
|
|
||||||
BOOL success = DeviceIoControl(
|
BOOL success = DeviceIoControl(
|
||||||
ra_handle,
|
ra_handle,
|
||||||
code,
|
code,
|
||||||
in,
|
in,
|
||||||
in_size,
|
in_size,
|
||||||
out,
|
out,
|
||||||
out_size,
|
out_size,
|
||||||
&dummy, // bytes returned
|
&dummy, // bytes returned
|
||||||
NULL // overlapped structure
|
NULL // overlapped structure
|
||||||
);
|
);
|
||||||
|
|
||||||
CloseHandle(ra_handle);
|
CloseHandle(ra_handle);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw std::system_error(GetLastError(), std::system_category(), "DeviceIoControl failed");
|
throw sys_error("DeviceIoControl failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void read(io_t& args)
|
inline void read(io_t& args)
|
||||||
{
|
{
|
||||||
io_control(RA_READ, NULL, 0, &args, sizeof(io_t));
|
io_control(RA_READ, NULL, 0, &args, sizeof(io_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void write(const io_t& args)
|
inline void write(const io_t& args)
|
||||||
{
|
{
|
||||||
io_control(RA_WRITE, const_cast<io_t*>(&args), sizeof(io_t), NULL, 0);
|
io_control(RA_WRITE, const_cast<io_t*>(&args), sizeof(io_t), NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline version_t get_version()
|
inline version_t get_version()
|
||||||
{
|
{
|
||||||
version_t ver;
|
version_t v;
|
||||||
io_control(RA_GET_VERSION, NULL, 0, &ver, sizeof(version_t));
|
|
||||||
return ver;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
168
common/rawaccel-validate.hpp
Normal file
168
common/rawaccel-validate.hpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,21 +6,31 @@
|
||||||
|
|
||||||
#define RA_OS "Win7+"
|
#define RA_OS "Win7+"
|
||||||
|
|
||||||
#define M_STR_HELPER(x) #x
|
#define RA_M_STR_HELPER(x) #x
|
||||||
#define M_STR(x) M_STR_HELPER(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 {
|
namespace rawaccel {
|
||||||
|
|
||||||
struct version_t {
|
struct version_t {
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
int patch;
|
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
|
#ifndef _KERNEL_MODE
|
||||||
inline constexpr version_t min_driver_version = { 1, 4, 0 };
|
inline constexpr version_t min_driver_version = { 1, 4, 0 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,4 +81,8 @@ namespace rawaccel {
|
||||||
return ilogb(x) == 0x400;
|
return ilogb(x) == 0x400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct noop {
|
||||||
|
template <typename... Ts>
|
||||||
|
constexpr void operator()(Ts&&...) const noexcept {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <rawaccel-base.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
@ -7,8 +9,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <rawaccel-settings.h>
|
|
||||||
|
|
||||||
using namespace System;
|
using namespace System;
|
||||||
using namespace System::Runtime::InteropServices;
|
using namespace System::Runtime::InteropServices;
|
||||||
using namespace Newtonsoft::Json;
|
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);
|
auto get = make_extractor(ia_settings);
|
||||||
|
|
||||||
double accel = get("Acceleration").value_or(0);
|
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);
|
double prescale = get("Pre-ScaleX").value_or(1);
|
||||||
|
|
||||||
ra::accel_args args;
|
ra::accel_args args;
|
||||||
|
|
||||||
args.limit = 1 + std::abs(cap - sens) / sens;
|
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;
|
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 cap = get("SensitivityCap").value_or(0);
|
||||||
double sens = get("Sensitivity").value_or(1);
|
double sens = get("Sensitivity").value_or(1);
|
||||||
double prescale = get("Pre-ScaleX").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) {
|
double accel_b = std::pow(accel * prescale, power - 1) / sens;
|
||||||
args.scale_cap = cap_converted;
|
args.accel_classic = std::pow(accel_b, 1 / (power - 1));
|
||||||
}
|
args.cap = cap / sens;
|
||||||
else {
|
args.power = power;
|
||||||
args.gain_cap = offset + std::pow(cap_converted - 1, rpowm1) / args.accel;
|
args.offset = get("Offset").value_or(0);
|
||||||
}
|
args.mode = ra::accel_mode::classic;
|
||||||
|
args.legacy = legacy;
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
@ -168,17 +164,15 @@ bool try_convert(const ia_settings_t& ia_settings) {
|
||||||
|
|
||||||
switch (static_cast<IA_MODES_ENUM>(mode)) {
|
switch (static_cast<IA_MODES_ENUM>(mode)) {
|
||||||
case IA_QL: {
|
case IA_QL: {
|
||||||
bool legacy = !ask("We recommend trying out our new cap and offset styles.\n"
|
bool legacy = !ask("We recommend trying out a new smooth cap style.\n"
|
||||||
"Use new cap and offset?");
|
"Use new cap style?");
|
||||||
ra_settings.modes.x = ra::accel_mode::classic;
|
|
||||||
ra_settings.argsv.x = convert_quake(ia_settings, legacy);
|
ra_settings.argsv.x = convert_quake(ia_settings, legacy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IA_NAT: {
|
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?");
|
"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, legacy);
|
||||||
ra_settings.argsv.x = convert_natural(ia_settings);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IA_LOG: {
|
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);
|
DriverSettings^ new_settings = Marshal::PtrToStructure<DriverSettings^>((IntPtr)&ra_settings);
|
||||||
auto errors = DriverInterop::GetSettingsErrors(new_settings);
|
auto errors = gcnew SettingsErrors(new_settings);
|
||||||
|
|
||||||
if (!errors->Empty()) {
|
if (!errors->Empty()) {
|
||||||
Console::WriteLine("Bad settings: {0}", errors);
|
Console::WriteLine("Bad settings: {0}", errors);
|
||||||
|
@ -197,7 +191,7 @@ bool try_convert(const ia_settings_t& ia_settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::Write("Sending to driver... ");
|
Console::Write("Sending to driver... ");
|
||||||
DriverInterop::Write(new_settings);
|
(gcnew ManagedAccel(new_settings))->Activate();
|
||||||
Console::WriteLine("done");
|
Console::WriteLine("done");
|
||||||
|
|
||||||
Console::Write("Generating settings.json... ");
|
Console::Write("Generating settings.json... ");
|
||||||
|
@ -208,10 +202,6 @@ bool try_convert(const ia_settings_t& ia_settings) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref struct ASSEMBLY {
|
|
||||||
static initonly Version^ VERSION = ASSEMBLY::typeid->Assembly->GetName()->Version;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
auto close_prompt = [] {
|
auto close_prompt = [] {
|
||||||
|
@ -221,9 +211,9 @@ int main()
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
VersionHelper::ValidateAndGetDriverVersion(ASSEMBLY::VERSION);
|
VersionHelper::ValidOrThrow();
|
||||||
}
|
}
|
||||||
catch (VersionException^ ex) {
|
catch (InteropException^ ex) {
|
||||||
Console::WriteLine(ex->Message);
|
Console::WriteLine(ex->Message);
|
||||||
close_prompt();
|
close_prompt();
|
||||||
}
|
}
|
||||||
|
@ -239,7 +229,7 @@ int main()
|
||||||
entry.path().extension() == IA_PROFILE_EXT) {
|
entry.path().extension() == IA_PROFILE_EXT) {
|
||||||
opt_path = entry;
|
opt_path = entry;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,7 +210,7 @@ Return Value:
|
||||||
DebugPrint(("RetrieveOutputBuffer failed: 0x%x\n", status));
|
DebugPrint(("RetrieveOutputBuffer failed: 0x%x\n", status));
|
||||||
}
|
}
|
||||||
else {
|
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);
|
bytes_out = sizeof(ra::version_t);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "rawaccel-base.hpp"
|
#include "rawaccel-base.hpp"
|
||||||
|
#include "rawaccel-io-def.h"
|
||||||
|
|
||||||
#define NOMINMAX
|
|
||||||
#include <ntddk.h>
|
|
||||||
#include <kbdmou.h>
|
#include <kbdmou.h>
|
||||||
#include <wdf.h>
|
#include <wdf.h>
|
||||||
|
|
||||||
|
|
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion(RawAccelVersion.value)]
|
[assembly: AssemblyVersion(VersionHelper.VersionString)]
|
||||||
[assembly: AssemblyFileVersion(RawAccelVersion.value)]
|
[assembly: AssemblyFileVersion(VersionHelper.VersionString)]
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <rawaccel-io.hpp>
|
||||||
|
#include <rawaccel-validate.hpp>
|
||||||
|
#include <utility-rawinput.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <msclr\marshal_cppstd.h>
|
#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;
|
||||||
using namespace System::Collections::Generic;
|
using namespace System::Collections::Generic;
|
||||||
|
using namespace System::IO;
|
||||||
using namespace System::Runtime::InteropServices;
|
using namespace System::Runtime::InteropServices;
|
||||||
using namespace System::Reflection;
|
using namespace System::Reflection;
|
||||||
|
|
||||||
|
@ -19,34 +18,39 @@ using namespace Windows::Forms;
|
||||||
|
|
||||||
using namespace Newtonsoft::Json;
|
using namespace Newtonsoft::Json;
|
||||||
|
|
||||||
|
namespace ra = rawaccel;
|
||||||
|
|
||||||
|
ra::settings default_settings;
|
||||||
|
|
||||||
[JsonConverter(Converters::StringEnumConverter::typeid)]
|
[JsonConverter(Converters::StringEnumConverter::typeid)]
|
||||||
public enum class AccelMode
|
public enum class AccelMode
|
||||||
{
|
{
|
||||||
linear, classic, natural, naturalgain, power, motivity, noaccel
|
classic, jump, natural, power, motivity, noaccel
|
||||||
};
|
};
|
||||||
|
|
||||||
[JsonObject(ItemRequired = Required::Always)]
|
public enum class TableMode
|
||||||
[StructLayout(LayoutKind::Sequential)]
|
|
||||||
public value struct AccelArgs
|
|
||||||
{
|
{
|
||||||
double offset;
|
off, binlog, linear
|
||||||
|
};
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind::Sequential)]
|
||||||
|
public value struct TableArgs
|
||||||
|
{
|
||||||
|
[JsonIgnore]
|
||||||
|
TableMode mode;
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType::U1)]
|
[MarshalAs(UnmanagedType::U1)]
|
||||||
bool legacyOffset;
|
bool transfer;
|
||||||
double acceleration;
|
|
||||||
double scale;
|
[MarshalAs(UnmanagedType::U1)]
|
||||||
double limit;
|
unsigned char partitions;
|
||||||
double exponent;
|
|
||||||
double midpoint;
|
short num;
|
||||||
double weight;
|
double start;
|
||||||
[JsonProperty("legacyCap")]
|
double stop;
|
||||||
double scaleCap;
|
|
||||||
double gainCap;
|
|
||||||
[JsonProperty(Required = Required::Default)]
|
|
||||||
double speedCap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
generic <typename T>
|
generic <typename T>
|
||||||
[JsonObject(ItemRequired = Required::Always)]
|
|
||||||
[StructLayout(LayoutKind::Sequential)]
|
[StructLayout(LayoutKind::Sequential)]
|
||||||
public value struct Vec2
|
public value struct Vec2
|
||||||
{
|
{
|
||||||
|
@ -54,7 +58,32 @@ public value struct Vec2
|
||||||
T y;
|
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)]
|
[StructLayout(LayoutKind::Sequential)]
|
||||||
public value struct DomainArgs
|
public value struct DomainArgs
|
||||||
{
|
{
|
||||||
|
@ -66,20 +95,22 @@ public value struct DomainArgs
|
||||||
[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)]
|
[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)]
|
||||||
public ref struct DriverSettings
|
public ref struct DriverSettings
|
||||||
{
|
{
|
||||||
|
literal double WriteDelayMs = ra::WRITE_DELAY;
|
||||||
literal String^ Key = "Driver settings";
|
literal String^ Key = "Driver settings";
|
||||||
|
|
||||||
[JsonProperty("Degrees of rotation")]
|
[JsonProperty("Degrees of rotation")]
|
||||||
double rotation;
|
double rotation;
|
||||||
|
|
||||||
[JsonProperty("Degrees of angle snapping", Required = Required::Default)]
|
[JsonProperty("Degrees of angle snapping")]
|
||||||
double snap;
|
double snap;
|
||||||
|
|
||||||
[JsonProperty("Use x as whole/combined accel")]
|
[JsonProperty("Use x as whole/combined accel")]
|
||||||
[MarshalAs(UnmanagedType::U1)]
|
[MarshalAs(UnmanagedType::U1)]
|
||||||
bool combineMagnitudes;
|
bool combineMagnitudes;
|
||||||
|
|
||||||
[JsonProperty("Accel modes")]
|
double dpi;
|
||||||
Vec2<AccelMode> modes;
|
|
||||||
|
double speedCap;
|
||||||
|
|
||||||
[JsonProperty("Accel parameters")]
|
[JsonProperty("Accel parameters")]
|
||||||
Vec2<AccelArgs> args;
|
Vec2<AccelArgs> args;
|
||||||
|
@ -87,192 +118,125 @@ public ref struct DriverSettings
|
||||||
[JsonProperty("Sensitivity multipliers")]
|
[JsonProperty("Sensitivity multipliers")]
|
||||||
Vec2<double> sensitivity;
|
Vec2<double> sensitivity;
|
||||||
|
|
||||||
[JsonProperty("Negative directional multipliers", Required = Required::Default)]
|
[JsonProperty("Negative directional multipliers")]
|
||||||
Vec2<double> directionalMultipliers;
|
Vec2<double> directionalMultipliers;
|
||||||
|
|
||||||
[JsonProperty("Stretches domain for horizontal vs vertical inputs", Required = Required::Default)]
|
[JsonProperty("Stretches domain for horizontal vs vertical inputs")]
|
||||||
DomainArgs domainArgs;
|
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;
|
Vec2<double> rangeXY;
|
||||||
|
|
||||||
[JsonProperty(Required = Required::Default)]
|
[JsonProperty(Required = Required::Default)]
|
||||||
double minimumTime;
|
double minimumTime;
|
||||||
|
|
||||||
[JsonProperty("Device ID", Required = Required::Default)]
|
[JsonProperty("Device ID")]
|
||||||
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)]
|
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = ra::MAX_DEV_ID_LEN)]
|
||||||
String^ deviceID = "";
|
String^ deviceID = "";
|
||||||
|
|
||||||
bool ShouldSerializeminimumTime()
|
bool ShouldSerializeminimumTime()
|
||||||
{
|
{
|
||||||
return minimumTime > 0 && minimumTime != DEFAULT_TIME_MIN;
|
return minimumTime != ra::DEFAULT_TIME_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverSettings()
|
DriverSettings()
|
||||||
{
|
{
|
||||||
domainArgs = { { 1, 1 }, 2 };
|
Marshal::PtrToStructure(IntPtr(&default_settings), this);
|
||||||
rangeXY = { 1, 1 };
|
}
|
||||||
|
|
||||||
|
void ToFile(String^ path)
|
||||||
|
{
|
||||||
|
using namespace Newtonsoft::Json::Linq;
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
static DriverSettings^ FromFile(String^ path)
|
||||||
|
{
|
||||||
|
if (!File::Exists(path))
|
||||||
|
{
|
||||||
|
throw gcnew FileNotFoundException(
|
||||||
|
String::Format("Settings file not found at {0}", path));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto settings = JsonConvert::DeserializeObject<DriverSettings^>(
|
||||||
|
File::ReadAllText(path));
|
||||||
|
|
||||||
|
if (settings == nullptr) {
|
||||||
|
throw gcnew JsonException(String::Format("{0} contains invalid JSON", path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public ref struct InteropException : public Exception {
|
||||||
template <typename NativeSettingsFunc>
|
public:
|
||||||
void as_native(DriverSettings^ managed_args, NativeSettingsFunc fn)
|
InteropException(String^ what) :
|
||||||
{
|
Exception(what) {}
|
||||||
#ifndef NDEBUG
|
InteropException(const char* what) :
|
||||||
if (Marshal::SizeOf(managed_args) != sizeof(settings))
|
Exception(gcnew String(what)) {}
|
||||||
throw gcnew InvalidOperationException("setting sizes differ");
|
InteropException(const std::exception& e) :
|
||||||
#endif
|
InteropException(e.what()) {}
|
||||||
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;
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
if (args->limit <= 1)
|
|
||||||
error_list->Add("limit must be greater than 1");
|
|
||||||
|
|
||||||
if (args->midpoint <= 0)
|
|
||||||
error_list->Add("midpoint must be positive");
|
|
||||||
|
|
||||||
if (args->offset < 0)
|
|
||||||
error_list->Add("offset can not be negative");
|
|
||||||
|
|
||||||
return error_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_list_t^ get_other_errors(DriverSettings^ settings)
|
|
||||||
{
|
|
||||||
auto error_list = gcnew error_list_t();
|
|
||||||
|
|
||||||
if (settings->rangeXY.x <= 0 || settings->rangeXY.y <= 0)
|
|
||||||
{
|
|
||||||
error_list->Add("range values must be positive");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings->domainArgs.domainXY.x <= 0 || settings->domainArgs.domainXY.y <= 0)
|
|
||||||
{
|
|
||||||
error_list->Add("domain values must be positive");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings->domainArgs.lpNorm <= 0)
|
|
||||||
{
|
|
||||||
error_list->Add("lp norm must be positive");
|
|
||||||
}
|
|
||||||
|
|
||||||
return error_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ref class SettingsErrors
|
public ref class SettingsErrors
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
error_list_t^ x;
|
List<String^>^ list;
|
||||||
error_list_t^ y;
|
int countX;
|
||||||
error_list_t^ other;
|
int countY;
|
||||||
|
|
||||||
|
delegate void MsgHandler(const char*);
|
||||||
|
|
||||||
|
void Add(const char* msg)
|
||||||
|
{
|
||||||
|
list->Add(msclr::interop::marshal_as<String^>(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsErrors(DriverSettings^ settings)
|
||||||
|
{
|
||||||
|
MsgHandler^ del = gcnew MsgHandler(this, &SettingsErrors::Add);
|
||||||
|
GCHandle gch = GCHandle::Alloc(del);
|
||||||
|
auto fp = static_cast<void (*)(const char*)>(
|
||||||
|
Marshal::GetFunctionPointerForDelegate(del).ToPointer());
|
||||||
|
|
||||||
|
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()
|
bool Empty()
|
||||||
{
|
{
|
||||||
return (x == nullptr || x->Count == 0) &&
|
return list->Count == 0;
|
||||||
(y == nullptr || y->Count == 0) &&
|
|
||||||
(other == nullptr || other->Count == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual String^ ToString() override
|
virtual String^ ToString() override
|
||||||
{
|
{
|
||||||
if (x == nullptr) throw;
|
|
||||||
|
|
||||||
Text::StringBuilder^ sb = gcnew Text::StringBuilder();
|
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->AppendFormat("x: {0}\n", s);
|
||||||
{
|
|
||||||
sb->AppendLine(str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
for each (auto s in list->GetRange(countX, countY))
|
||||||
{
|
{
|
||||||
for each (String^ str in x)
|
sb->AppendFormat("y: {0}\n", s);
|
||||||
{
|
}
|
||||||
sb->AppendFormat("x: {0}\n", str);
|
for each (auto s in list->GetRange(countY, list->Count))
|
||||||
}
|
{
|
||||||
for each (String^ str in y)
|
sb->AppendLine(s);
|
||||||
{
|
|
||||||
sb->AppendFormat("y: {0}\n", str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for each (String ^ str in other)
|
|
||||||
{
|
|
||||||
sb->AppendLine(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb->ToString();
|
return sb->ToString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -314,7 +278,7 @@ public ref struct RawInputInterop
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
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)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
throw gcnew System::Exception(gcnew String(e.what()));
|
throw gcnew InteropException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public ref struct DriverInterop
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DriverSettings^ GetDefaultSettings()
|
|
||||||
{
|
|
||||||
return get_default();
|
|
||||||
}
|
|
||||||
|
|
||||||
static SettingsErrors^ GetSettingsErrors(DriverSettings^ args)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static error_list_t^ GetAccelErrors(AccelMode mode, AccelArgs^ args)
|
|
||||||
{
|
|
||||||
return get_accel_errors(mode, args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public ref class ManagedAccel
|
public ref class ManagedAccel
|
||||||
{
|
{
|
||||||
mouse_modifier* const modifier_instance = new mouse_modifier();
|
ra::io_t* const instance = new ra::io_t();
|
||||||
#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:
|
public:
|
||||||
|
ManagedAccel() {};
|
||||||
|
|
||||||
|
ManagedAccel(DriverSettings^ settings)
|
||||||
|
{
|
||||||
|
Settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~ManagedAccel()
|
virtual ~ManagedAccel()
|
||||||
{
|
{
|
||||||
delete modifier_instance;
|
delete instance;
|
||||||
delete[] lut_x;
|
|
||||||
delete[] lut_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
!ManagedAccel()
|
!ManagedAccel()
|
||||||
{
|
{
|
||||||
delete modifier_instance;
|
delete instance;
|
||||||
delete[] lut_x;
|
|
||||||
delete[] lut_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple<double, double>^ Accelerate(int x, int y, double time)
|
Tuple<double, double>^ Accelerate(int x, int y, double time)
|
||||||
|
@ -418,89 +334,64 @@ public:
|
||||||
(double)x,
|
(double)x,
|
||||||
(double)y
|
(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);
|
return gcnew Tuple<double, double>(in_out_vec.x, in_out_vec.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateFromSettings(DriverSettings^ args)
|
void Activate()
|
||||||
{
|
{
|
||||||
update_modifier(
|
try {
|
||||||
*modifier_instance,
|
ra::write(*instance);
|
||||||
args,
|
}
|
||||||
vec2<si_pair*>{ lut_x, lut_y }
|
catch (const ra::error& e) {
|
||||||
);
|
throw gcnew InteropException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ManagedAccel^ GetActiveAccel()
|
property DriverSettings^ Settings
|
||||||
{
|
{
|
||||||
settings args;
|
DriverSettings^ get()
|
||||||
wrapper_io::readFromDriver(args);
|
{
|
||||||
|
DriverSettings^ settings = gcnew DriverSettings();
|
||||||
|
Marshal::PtrToStructure(IntPtr(&instance->args), settings);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
auto active = gcnew ManagedAccel();
|
void set(DriverSettings^ val)
|
||||||
*active->modifier_instance = {
|
{
|
||||||
args
|
Marshal::StructureToPtr(val, IntPtr(&instance->args), false);
|
||||||
, vec2<si_pair*> { active->lut_x, active->lut_y }
|
instance->mod = { instance->args };
|
||||||
};
|
}
|
||||||
return active;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static ManagedAccel^ GetActive()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
auto active = gcnew ManagedAccel();
|
||||||
|
ra::read(*active->instance);
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
catch (const ra::error& e) {
|
||||||
|
throw gcnew InteropException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public ref struct RawAccelVersion
|
|
||||||
{
|
|
||||||
literal String^ value = RA_VER_STRING;
|
|
||||||
};
|
|
||||||
|
|
||||||
public ref struct VersionException : public Exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VersionException() {}
|
|
||||||
VersionException(String^ what) : Exception(what) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
Version^ convert(rawaccel::version_t v)
|
|
||||||
{
|
|
||||||
return gcnew Version(v.major, v.minor, v.patch, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ref struct VersionHelper
|
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 {
|
try {
|
||||||
wrapper_io::getDriverVersion(drv_ver);
|
ra::version_t v = ra::valid_version_or_throw();
|
||||||
|
return gcnew Version(v.major, v.minor, v.patch, 0);
|
||||||
}
|
}
|
||||||
catch (DriverNotInstalledException^ ex) {
|
catch (const ra::error& e) {
|
||||||
throw gcnew VersionException(ex->Message);
|
throw gcnew InteropException(e);
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return drv_ver_managed;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,12 +84,10 @@ copy /Y "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)signed\Newtonsoft.Json.
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
<ClInclude Include="wrapper_io.hpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AssemblyInfo.cpp" />
|
<ClCompile Include="AssemblyInfo.cpp" />
|
||||||
<ClCompile Include="wrapper.cpp" />
|
<ClCompile Include="wrapper.cpp" />
|
||||||
<ClCompile Include="wrapper_io.cpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json">
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="wrapper_io.hpp">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="resource.h">
|
<ClInclude Include="resource.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -26,9 +23,6 @@
|
||||||
<ClCompile Include="wrapper.cpp">
|
<ClCompile Include="wrapper.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="wrapper_io.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="AssemblyInfo.cpp">
|
<ClCompile Include="AssemblyInfo.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -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())) {}
|
|
||||||
};
|
|
|
@ -16,27 +16,13 @@ namespace writer
|
||||||
MessageBox.Show(msg, "Raw Accel 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)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
VersionHelper.ValidateAndGetDriverVersion(typeof(Program).Assembly.GetName().Version);
|
VersionHelper.ValidOrThrow();
|
||||||
}
|
}
|
||||||
catch (VersionException e)
|
catch (InteropException e)
|
||||||
{
|
{
|
||||||
Show(e.Message);
|
Show(e.Message);
|
||||||
return;
|
return;
|
||||||
|
@ -48,23 +34,19 @@ namespace writer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!File.Exists(args[0]))
|
|
||||||
{
|
|
||||||
Show($"Settings file not found at {args[0]}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
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]);
|
new ManagedAccel(settings).Activate();
|
||||||
return;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Show($"Bad settings:\n\n{errors}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Send(JO);
|
|
||||||
}
|
}
|
||||||
catch (JsonException e)
|
catch (JsonException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion(RawAccelVersion.value)]
|
[assembly: AssemblyVersion(VersionHelper.VersionString)]
|
||||||
[assembly: AssemblyFileVersion(RawAccelVersion.value)]
|
[assembly: AssemblyFileVersion(VersionHelper.VersionString)]
|
Loading…
Add table
Add a link
Reference in a new issue