mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
misc: various performance clean up (#844)
## Link to GitHub Issue or related Pull Request, if one exists n/a ## Description of change - Replace unnecessary precision timers with standard sleeps to reduce wakeups and background CPU usage. - Reuse buffers in raw input, touchscreen, and HID output paths to eliminate steady-state allocations. - Pre-index HID button groups and correctly process batched HID reports. No functional changes. ## Testing
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
#include "keypads.h"
|
#include "keypads.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "avs/game.h"
|
#include "avs/game.h"
|
||||||
#include "external/rapidjson/document.h"
|
#include "external/rapidjson/document.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
@@ -59,7 +60,6 @@ namespace api::modules {
|
|||||||
// get params
|
// get params
|
||||||
auto keypad = req.params[0].GetUint();
|
auto keypad = req.params[0].GetUint();
|
||||||
auto input = std::string(req.params[1].GetString());
|
auto input = std::string(req.params[1].GetString());
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
// process all chars
|
// process all chars
|
||||||
for (auto c : input) {
|
for (auto c : input) {
|
||||||
@@ -93,11 +93,11 @@ namespace api::modules {
|
|||||||
|
|
||||||
// set
|
// set
|
||||||
eamuse_set_keypad_overrides(keypad, state);
|
eamuse_set_keypad_overrides(keypad, state);
|
||||||
timer.sleep(sleep_time);
|
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
|
||||||
|
|
||||||
// unset
|
// unset
|
||||||
eamuse_set_keypad_overrides(keypad, 0);
|
eamuse_set_keypad_overrides(keypad, 0);
|
||||||
timer.sleep(sleep_time);
|
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -17,7 +18,6 @@ namespace api {
|
|||||||
controller->init_state(this->state);
|
controller->init_state(this->state);
|
||||||
this->thread = new std::thread([this] () {
|
this->thread = new std::thread([this] () {
|
||||||
log_warning("api::serial", "listening on {} (baud: {})", this->port, this->baud);
|
log_warning("api::serial", "listening on {} (baud: {})", this->port, this->baud);
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
// read buffer
|
// read buffer
|
||||||
uint8_t read_buffer[16*1024];
|
uint8_t read_buffer[16*1024];
|
||||||
@@ -162,7 +162,7 @@ namespace api {
|
|||||||
|
|
||||||
// slow down on reconnect
|
// slow down on reconnect
|
||||||
if (this->running) {
|
if (this->running) {
|
||||||
timer.sleep(retry_time);
|
std::this_thread::sleep_for(std::chrono::milliseconds(retry_time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "poke.h"
|
#include "poke.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
@@ -11,7 +12,6 @@
|
|||||||
#include "touch/native/inject.h"
|
#include "touch/native/inject.h"
|
||||||
#include "touch/touch.h"
|
#include "touch/touch.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
|
|
||||||
namespace games::iidx::poke {
|
namespace games::iidx::poke {
|
||||||
|
|
||||||
@@ -125,8 +125,6 @@ namespace games::iidx::poke {
|
|||||||
// create new thread
|
// create new thread
|
||||||
THREAD_RUNNING = true;
|
THREAD_RUNNING = true;
|
||||||
THREAD = new std::thread([] {
|
THREAD = new std::thread([] {
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
// log
|
// log
|
||||||
log_info("poke", "enabled");
|
log_info("poke", "enabled");
|
||||||
|
|
||||||
@@ -198,7 +196,7 @@ namespace games::iidx::poke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// slow down
|
// slow down
|
||||||
timer.sleep(50);
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!touch_points.empty()) {
|
if (!touch_points.empty()) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "poke.h"
|
#include "poke.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@@ -11,7 +12,6 @@
|
|||||||
#include "touch/native/inject.h"
|
#include "touch/native/inject.h"
|
||||||
#include "touch/native/nativetouchhook.h"
|
#include "touch/native/nativetouchhook.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
|
|
||||||
namespace games::nost::poke {
|
namespace games::nost::poke {
|
||||||
|
|
||||||
@@ -68,8 +68,6 @@ namespace games::nost::poke {
|
|||||||
// create new thread
|
// create new thread
|
||||||
THREAD_RUNNING = true;
|
THREAD_RUNNING = true;
|
||||||
THREAD = new std::thread([] {
|
THREAD = new std::thread([] {
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
const int swipe_anim_total_frames = 6;
|
const int swipe_anim_total_frames = 6;
|
||||||
const int swipe_anim_y = 300;
|
const int swipe_anim_y = 300;
|
||||||
|
|
||||||
@@ -194,7 +192,7 @@ namespace games::nost::poke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// slow down
|
// slow down
|
||||||
timer.sleep(30);
|
std::this_thread::sleep_for(std::chrono::milliseconds(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contact_active) {
|
if (contact_active) {
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "hooks/audio/util.h"
|
#include "hooks/audio/util.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
|
|
||||||
NullDiscardBackend::~NullDiscardBackend() {
|
NullDiscardBackend::~NullDiscardBackend() {
|
||||||
this->running = false;
|
this->running = false;
|
||||||
@@ -125,8 +125,6 @@ HRESULT NullDiscardBackend::on_release_buffer(uint32_t, DWORD) {
|
|||||||
void NullDiscardBackend::pace_loop() {
|
void NullDiscardBackend::pace_loop() {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
// audio is discarded, so timing precision and drift do not matter; just wake the
|
// audio is discarded, so timing precision and drift do not matter; just wake the
|
||||||
// game once per buffer period to keep its render thread from blocking on the event.
|
// game once per buffer period to keep its render thread from blocking on the event.
|
||||||
const auto period = duration_cast<steady_clock::duration>(
|
const auto period = duration_cast<steady_clock::duration>(
|
||||||
@@ -136,6 +134,6 @@ void NullDiscardBackend::pace_loop() {
|
|||||||
if (this->relay_handle) {
|
if (this->relay_handle) {
|
||||||
SetEvent(this->relay_handle);
|
SetEvent(this->relay_handle);
|
||||||
}
|
}
|
||||||
timer.sleep(period);
|
std::this_thread::sleep_for(period);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "eamuse.h"
|
#include "eamuse.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@@ -10,7 +11,6 @@
|
|||||||
#include "rawinput/rawinput.h"
|
#include "rawinput/rawinput.h"
|
||||||
#include "games/sdvx/sdvx.h"
|
#include "games/sdvx/sdvx.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
#include "overlay/overlay.h"
|
#include "overlay/overlay.h"
|
||||||
@@ -335,7 +335,6 @@ void eamuse_coin_start_thread() {
|
|||||||
COIN_INPUT_THREAD = new std::thread([]() {
|
COIN_INPUT_THREAD = new std::thread([]() {
|
||||||
auto overlay_buttons = games::get_buttons_overlay(eamuse_get_game());
|
auto overlay_buttons = games::get_buttons_overlay(eamuse_get_game());
|
||||||
static bool COIN_INPUT_KEY_STATE = false;
|
static bool COIN_INPUT_KEY_STATE = false;
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
while (COIN_INPUT_THREAD_ACTIVE) {
|
while (COIN_INPUT_THREAD_ACTIVE) {
|
||||||
|
|
||||||
// check input key
|
// check input key
|
||||||
@@ -355,7 +354,7 @@ void eamuse_coin_start_thread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// once every two frames
|
// once every two frames
|
||||||
timer.sleep(1000 / 30);
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 30));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -409,7 +408,6 @@ void eamuse_pin_macro_start_thread() {
|
|||||||
size_t pin_index[2] = {PIN_MACRO_VALUES[0].length(), PIN_MACRO_VALUES[1].length()};
|
size_t pin_index[2] = {PIN_MACRO_VALUES[0].length(), PIN_MACRO_VALUES[1].length()};
|
||||||
|
|
||||||
std::optional<uint8_t> active_unit = std::nullopt;
|
std::optional<uint8_t> active_unit = std::nullopt;
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
while (PIN_MACRO_THREAD_ACTIVE) {
|
while (PIN_MACRO_THREAD_ACTIVE) {
|
||||||
// wait for key press or auto-trigger
|
// wait for key press or auto-trigger
|
||||||
@@ -438,7 +436,7 @@ void eamuse_pin_macro_start_thread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!active_unit.has_value()) {
|
if (!active_unit.has_value()) {
|
||||||
timer.sleep(20);
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,22 +452,22 @@ void eamuse_pin_macro_start_thread() {
|
|||||||
eamuse_set_keypad_overrides(unit, keypad_overrides[char_index]);
|
eamuse_set_keypad_overrides(unit, keypad_overrides[char_index]);
|
||||||
}
|
}
|
||||||
pin_index[unit]++;
|
pin_index[unit]++;
|
||||||
timer.sleep(100);
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
|
||||||
// clear
|
// clear
|
||||||
eamuse_set_keypad_overrides(unit, 0);
|
eamuse_set_keypad_overrides(unit, 0);
|
||||||
timer.sleep(50);
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
|
||||||
// end of PIN
|
// end of PIN
|
||||||
if (pin_index[unit] == PIN_MACRO_VALUES[unit].length()) {
|
if (pin_index[unit] == PIN_MACRO_VALUES[unit].length()) {
|
||||||
active_unit = std::nullopt;
|
active_unit = std::nullopt;
|
||||||
timer.sleep(120);
|
std::this_thread::sleep_for(std::chrono::milliseconds(120));
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.sleep(200);
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
@@ -103,6 +102,13 @@ namespace rawinput {
|
|||||||
std::vector<HIDTouchPoint> touch_points;
|
std::vector<HIDTouchPoint> touch_points;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HIDButtonInputGroup {
|
||||||
|
USAGE usage_page;
|
||||||
|
USHORT link_collection;
|
||||||
|
std::vector<size_t> cap_indices;
|
||||||
|
std::vector<USAGE> usages;
|
||||||
|
};
|
||||||
|
|
||||||
struct DeviceHIDInfo {
|
struct DeviceHIDInfo {
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
_HIDP_CAPS caps;
|
_HIDP_CAPS caps;
|
||||||
@@ -125,11 +131,12 @@ namespace rawinput {
|
|||||||
|
|
||||||
std::vector<std::vector<bool>> button_states;
|
std::vector<std::vector<bool>> button_states;
|
||||||
std::vector<std::vector<double>> button_up, button_down;
|
std::vector<std::vector<double>> button_up, button_down;
|
||||||
|
std::vector<std::vector<uint8_t>> button_report_states;
|
||||||
std::vector<std::vector<bool>> button_output_states;
|
std::vector<std::vector<bool>> button_output_states;
|
||||||
|
std::vector<HIDButtonInputGroup> button_input_groups;
|
||||||
// key: usage page, link collection
|
std::vector<CHAR> output_report;
|
||||||
// value: number of buttons for that key (combine ranges and nonranges)
|
std::vector<USAGE> button_output_usages;
|
||||||
std::map<std::pair<USAGE, ULONG>, ULONG> button_usage_pages;
|
std::vector<USAGE> button_output_usages_off;
|
||||||
|
|
||||||
std::vector<float> value_states;
|
std::vector<float> value_states;
|
||||||
std::vector<LONG> value_states_raw;
|
std::vector<LONG> value_states_raw;
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#include "rawinput.h"
|
#include "rawinput.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <map>
|
||||||
|
#include <thread>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -9,7 +13,6 @@
|
|||||||
|
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "external/robin_hood.h"
|
#include "external/robin_hood.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
|
|
||||||
@@ -169,9 +172,8 @@ void rawinput::RawInputManager::input_hwnd_create() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// wait for window creation being done
|
// wait for window creation being done
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
while (!this->input_hwnd) {
|
while (!this->input_hwnd) {
|
||||||
timer.sleep(1);
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +441,9 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
|||||||
std::vector<std::string> button_caps_names;
|
std::vector<std::string> button_caps_names;
|
||||||
std::vector<std::vector<bool>> button_states;
|
std::vector<std::vector<bool>> button_states;
|
||||||
std::vector<std::vector<double>> button_up, button_down;
|
std::vector<std::vector<double>> button_up, button_down;
|
||||||
std::map<std::pair<USAGE, ULONG>, ULONG> button_usage_pages;
|
std::vector<std::vector<uint8_t>> button_report_states;
|
||||||
|
std::vector<HIDButtonInputGroup> button_input_groups;
|
||||||
|
std::map<std::pair<USAGE, ULONG>, size_t> button_input_group_indices;
|
||||||
for (int button_cap_num = 0; button_cap_num < button_cap_length; button_cap_num++) {
|
for (int button_cap_num = 0; button_cap_num < button_cap_length; button_cap_num++) {
|
||||||
auto &button_caps = button_cap_data[button_cap_num];
|
auto &button_caps = button_cap_data[button_cap_num];
|
||||||
|
|
||||||
@@ -458,7 +462,7 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
|||||||
int button_count = button_caps.Range.UsageMax - button_caps.Range.UsageMin + 1;
|
int button_count = button_caps.Range.UsageMax - button_caps.Range.UsageMin + 1;
|
||||||
|
|
||||||
// ignore bad ranges reported by bad devices
|
// ignore bad ranges reported by bad devices
|
||||||
if (button_count >= 0xffff) {
|
if (button_count <= 0 || button_count >= 0xffff) {
|
||||||
log_warning("rawinput", "skipping bad button cap range for device {}, range [{}, {}]",
|
log_warning("rawinput", "skipping bad button cap range for device {}, range [{}, {}]",
|
||||||
device_name,
|
device_name,
|
||||||
button_caps.Range.UsageMin,
|
button_caps.Range.UsageMin,
|
||||||
@@ -467,11 +471,30 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fill vectors
|
// fill vectors
|
||||||
|
const size_t cap_index = button_caps_list.size();
|
||||||
button_caps_list.emplace_back(button_caps);
|
button_caps_list.emplace_back(button_caps);
|
||||||
button_states.emplace_back(std::vector<bool>(static_cast<unsigned int>(button_count), false));
|
button_states.emplace_back(std::vector<bool>(static_cast<unsigned int>(button_count), false));
|
||||||
button_up.emplace_back(std::vector<double>(static_cast<unsigned int>(button_count), 0.0));
|
button_up.emplace_back(std::vector<double>(static_cast<unsigned int>(button_count), 0.0));
|
||||||
button_down.emplace_back(std::vector<double>(static_cast<unsigned int>(button_count), 0.0));
|
button_down.emplace_back(std::vector<double>(static_cast<unsigned int>(button_count), 0.0));
|
||||||
button_usage_pages[std::make_pair(button_caps.UsagePage, button_caps.LinkCollection)] += button_count;
|
button_report_states.emplace_back(static_cast<size_t>(button_count), 0);
|
||||||
|
|
||||||
|
const auto group_key = std::make_pair(
|
||||||
|
button_caps.UsagePage,
|
||||||
|
static_cast<ULONG>(button_caps.LinkCollection));
|
||||||
|
auto [group_it, inserted] = button_input_group_indices.try_emplace(
|
||||||
|
group_key,
|
||||||
|
button_input_groups.size());
|
||||||
|
if (inserted) {
|
||||||
|
button_input_groups.emplace_back(HIDButtonInputGroup {
|
||||||
|
.usage_page = button_caps.UsagePage,
|
||||||
|
.link_collection = button_caps.LinkCollection,
|
||||||
|
.cap_indices = {},
|
||||||
|
.usages = {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
auto &input_group = button_input_groups[group_it->second];
|
||||||
|
input_group.cap_indices.push_back(cap_index);
|
||||||
|
input_group.usages.resize(input_group.usages.size() + button_count);
|
||||||
|
|
||||||
// names
|
// names
|
||||||
for (USAGE usg = button_caps.Range.UsageMin; usg <= button_caps.Range.UsageMax; usg++) {
|
for (USAGE usg = button_caps.Range.UsageMin; usg <= button_caps.Range.UsageMax; usg++) {
|
||||||
@@ -512,7 +535,7 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
|||||||
int button_count = button_caps.Range.UsageMax - button_caps.Range.UsageMin + 1;
|
int button_count = button_caps.Range.UsageMax - button_caps.Range.UsageMin + 1;
|
||||||
|
|
||||||
// ignore bad ranges reported by bad devices
|
// ignore bad ranges reported by bad devices
|
||||||
if (button_count >= 0xffff) {
|
if (button_count <= 0 || button_count >= 0xffff) {
|
||||||
log_warning("rawinput", "skipping bad button output cap range for device {}, range [{}, {}]",
|
log_warning("rawinput", "skipping bad button output cap range for device {}, range [{}, {}]",
|
||||||
device_name,
|
device_name,
|
||||||
button_caps.Range.UsageMin,
|
button_caps.Range.UsageMin,
|
||||||
@@ -800,8 +823,18 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
|
|||||||
new_device.hidInfo->button_states = std::move(button_states);
|
new_device.hidInfo->button_states = std::move(button_states);
|
||||||
new_device.hidInfo->button_up = std::move(button_up);
|
new_device.hidInfo->button_up = std::move(button_up);
|
||||||
new_device.hidInfo->button_down = std::move(button_down);
|
new_device.hidInfo->button_down = std::move(button_down);
|
||||||
|
new_device.hidInfo->button_report_states = std::move(button_report_states);
|
||||||
new_device.hidInfo->button_output_states = std::move(button_output_states);
|
new_device.hidInfo->button_output_states = std::move(button_output_states);
|
||||||
new_device.hidInfo->button_usage_pages = std::move(button_usage_pages);
|
new_device.hidInfo->button_input_groups = std::move(button_input_groups);
|
||||||
|
new_device.hidInfo->output_report.resize(caps.OutputReportByteLength);
|
||||||
|
size_t max_button_output_count = 0;
|
||||||
|
for (const auto &button_output_state : new_device.hidInfo->button_output_states) {
|
||||||
|
if (button_output_state.size() > max_button_output_count) {
|
||||||
|
max_button_output_count = button_output_state.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_device.hidInfo->button_output_usages.reserve(max_button_output_count);
|
||||||
|
new_device.hidInfo->button_output_usages_off.reserve(max_button_output_count);
|
||||||
new_device.hidInfo->value_states = std::move(value_states);
|
new_device.hidInfo->value_states = std::move(value_states);
|
||||||
new_device.hidInfo->value_states_raw = std::move(value_states_raw);
|
new_device.hidInfo->value_states_raw = std::move(value_states_raw);
|
||||||
new_device.hidInfo->value_output_states = std::move(value_output_states);
|
new_device.hidInfo->value_output_states = std::move(value_output_states);
|
||||||
@@ -1573,11 +1606,17 @@ LRESULT CALLBACK rawinput::RawInputManager::input_wnd_proc(
|
|||||||
if (!data_size) {
|
if (!data_size) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::shared_ptr<RAWINPUT> data((RAWINPUT *) new char[data_size]{});
|
thread_local std::vector<RAWINPUT> data_buffer;
|
||||||
|
const size_t data_count =
|
||||||
|
(data_size + sizeof(RAWINPUT) - 1) / sizeof(RAWINPUT);
|
||||||
|
if (data_buffer.size() < data_count) {
|
||||||
|
data_buffer.resize(data_count);
|
||||||
|
}
|
||||||
|
auto data = data_buffer.data();
|
||||||
if (GetRawInputData(
|
if (GetRawInputData(
|
||||||
(HRAWINPUT) lParam,
|
(HRAWINPUT) lParam,
|
||||||
RID_INPUT,
|
RID_INPUT,
|
||||||
data.get(),
|
data,
|
||||||
&data_size,
|
&data_size,
|
||||||
sizeof(RAWINPUTHEADER)) != data_size) {
|
sizeof(RAWINPUTHEADER)) != data_size) {
|
||||||
break;
|
break;
|
||||||
@@ -1791,17 +1830,13 @@ LRESULT CALLBACK rawinput::RawInputManager::input_wnd_proc(
|
|||||||
+ (size_t) hid_report_index * data_hid.dwSizeHid;
|
+ (size_t) hid_report_index * data_hid.dwSizeHid;
|
||||||
|
|
||||||
// parse reports
|
// parse reports
|
||||||
for (const auto &pair : device.hidInfo->button_usage_pages) {
|
for (auto &input_group : device.hidInfo->button_input_groups) {
|
||||||
const auto usage_page = pair.first.first;
|
auto &usages = input_group.usages;
|
||||||
const auto link_collection = pair.first.second;
|
ULONG usages_length = static_cast<ULONG>(usages.size());
|
||||||
const auto button_count = pair.second;
|
|
||||||
|
|
||||||
ULONG usages_length = button_count;
|
|
||||||
std::vector<USAGE> usages(static_cast<size_t>(usages_length));
|
|
||||||
if (HidP_GetUsages(
|
if (HidP_GetUsages(
|
||||||
HidP_Input,
|
HidP_Input,
|
||||||
usage_page,
|
input_group.usage_page,
|
||||||
link_collection,
|
input_group.link_collection,
|
||||||
usages.data(),
|
usages.data(),
|
||||||
&usages_length,
|
&usages_length,
|
||||||
reinterpret_cast<PHIDP_PREPARSED_DATA>(device.hidInfo->preparsed_data.get()),
|
reinterpret_cast<PHIDP_PREPARSED_DATA>(device.hidInfo->preparsed_data.get()),
|
||||||
@@ -1819,29 +1854,22 @@ LRESULT CALLBACK rawinput::RawInputManager::input_wnd_proc(
|
|||||||
// log_info(
|
// log_info(
|
||||||
// "rawinput",
|
// "rawinput",
|
||||||
// "processing HID input for device {}, usage page {:x} and link collection {:x} with {} buttons, got {} reports",
|
// "processing HID input for device {}, usage page {:x} and link collection {:x} with {} buttons, got {} reports",
|
||||||
// device.desc,
|
// device.desc, input_group.usage_page,
|
||||||
// usage_page, link_collection, button_count, usages_length);
|
// input_group.link_collection, usages.size(), usages_length);
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
for (size_t cap_num = 0; cap_num < device.hidInfo->button_caps_list.size(); cap_num++) {
|
for (const size_t cap_num : input_group.cap_indices) {
|
||||||
auto &button_caps = device.hidInfo->button_caps_list[cap_num];
|
auto &button_caps = device.hidInfo->button_caps_list[cap_num];
|
||||||
auto &button_states = device.hidInfo->button_states[cap_num];
|
auto &button_states = device.hidInfo->button_states[cap_num];
|
||||||
auto &button_down = device.hidInfo->button_down[cap_num];
|
auto &button_down = device.hidInfo->button_down[cap_num];
|
||||||
auto &button_up = device.hidInfo->button_up[cap_num];
|
auto &button_up = device.hidInfo->button_up[cap_num];
|
||||||
|
auto &new_states = device.hidInfo->button_report_states[cap_num];
|
||||||
// is this the right usage page and link collection?
|
|
||||||
if (button_caps.UsagePage != usage_page || button_caps.LinkCollection != link_collection) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get button count
|
// get button count
|
||||||
int button_count = button_caps.Range.UsageMax - button_caps.Range.UsageMin + 1;
|
int button_count = button_caps.Range.UsageMax - button_caps.Range.UsageMin + 1;
|
||||||
if (button_count <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update buttons
|
// update buttons
|
||||||
std::vector<bool> new_states(button_count);
|
std::fill(new_states.begin(), new_states.end(), 0);
|
||||||
for (ULONG usage_num = 0; usage_num < usages_length; usage_num++) {
|
for (ULONG usage_num = 0; usage_num < usages_length; usage_num++) {
|
||||||
if (usages[usage_num] < button_caps.Range.UsageMin ||
|
if (usages[usage_num] < button_caps.Range.UsageMin ||
|
||||||
usages[usage_num] > button_caps.Range.UsageMax) {
|
usages[usage_num] > button_caps.Range.UsageMax) {
|
||||||
@@ -1852,17 +1880,18 @@ LRESULT CALLBACK rawinput::RawInputManager::input_wnd_proc(
|
|||||||
|
|
||||||
// guard against some buggy device sending an event for a usage below UsageMin
|
// guard against some buggy device sending an event for a usage below UsageMin
|
||||||
if (usage < button_count) {
|
if (usage < button_count) {
|
||||||
new_states[usage] = true;
|
new_states[usage] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int button_num = 0; button_num < button_count; button_num++) {
|
for (int button_num = 0; button_num < button_count; button_num++) {
|
||||||
if (!new_states[button_num] && button_states[button_num]) {
|
const bool new_state = new_states[button_num] != 0;
|
||||||
|
if (!new_state && button_states[button_num]) {
|
||||||
device.updated = true;
|
device.updated = true;
|
||||||
button_states[button_num] = new_states[button_num];
|
button_states[button_num] = new_state;
|
||||||
button_down[button_num] = input_time;
|
button_down[button_num] = input_time;
|
||||||
} else if (new_states[button_num] && !button_states[button_num]) {
|
} else if (new_state && !button_states[button_num]) {
|
||||||
device.updated = true;
|
device.updated = true;
|
||||||
button_states[button_num] = new_states[button_num];
|
button_states[button_num] = new_state;
|
||||||
button_up[button_num] = input_time;
|
button_up[button_num] = input_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2017,8 +2046,10 @@ void rawinput::RawInputManager::device_write_output(Device *device, bool only_up
|
|||||||
switch (hid->driver) {
|
switch (hid->driver) {
|
||||||
case HIDDriver::Default: {
|
case HIDDriver::Default: {
|
||||||
|
|
||||||
// allocate report
|
auto &report_data = hid->output_report;
|
||||||
CHAR *report_data = new CHAR[hid->caps.OutputReportByteLength] {};
|
auto &usage_list = hid->button_output_usages;
|
||||||
|
auto &usage_off_list = hid->button_output_usages_off;
|
||||||
|
std::fill(report_data.begin(), report_data.end(), 0);
|
||||||
|
|
||||||
// set buttons
|
// set buttons
|
||||||
for (size_t cap_no = 0; cap_no < hid->button_output_caps_list.size(); cap_no++) {
|
for (size_t cap_no = 0; cap_no < hid->button_output_caps_list.size(); cap_no++) {
|
||||||
@@ -2026,10 +2057,8 @@ void rawinput::RawInputManager::device_write_output(Device *device, bool only_up
|
|||||||
auto &button_state_list = hid->button_output_states[cap_no];
|
auto &button_state_list = hid->button_output_states[cap_no];
|
||||||
|
|
||||||
// determine which buttons to turn on
|
// determine which buttons to turn on
|
||||||
std::vector<USAGE> usage_list;
|
usage_list.clear();
|
||||||
std::vector<USAGE> usage_off_list;
|
usage_off_list.clear();
|
||||||
usage_list.reserve(button_state_list.size());
|
|
||||||
usage_off_list.reserve(button_state_list.size());
|
|
||||||
for (size_t state_no = 0; state_no < button_state_list.size(); state_no++) {
|
for (size_t state_no = 0; state_no < button_state_list.size(); state_no++) {
|
||||||
if (button_state_list[state_no]) {
|
if (button_state_list[state_no]) {
|
||||||
usage_list.push_back(button_cap.Range.UsageMin + (USAGE) state_no);
|
usage_list.push_back(button_cap.Range.UsageMin + (USAGE) state_no);
|
||||||
@@ -2044,15 +2073,18 @@ void rawinput::RawInputManager::device_write_output(Device *device, bool only_up
|
|||||||
HidP_Output,
|
HidP_Output,
|
||||||
button_cap.UsagePage,
|
button_cap.UsagePage,
|
||||||
button_cap.LinkCollection,
|
button_cap.LinkCollection,
|
||||||
&usage_list[0],
|
usage_list.data(),
|
||||||
&usage_list_length,
|
&usage_list_length,
|
||||||
reinterpret_cast<PHIDP_PREPARSED_DATA>(hid->preparsed_data.get()),
|
reinterpret_cast<PHIDP_PREPARSED_DATA>(hid->preparsed_data.get()),
|
||||||
report_data,
|
report_data.data(),
|
||||||
hid->caps.OutputReportByteLength) == HIDP_STATUS_INCOMPATIBLE_REPORT_ID) {
|
hid->caps.OutputReportByteLength) == HIDP_STATUS_INCOMPATIBLE_REPORT_ID) {
|
||||||
|
|
||||||
// flush report
|
// flush report
|
||||||
HidD_SetOutputReport(hid->handle, report_data, hid->caps.OutputReportByteLength);
|
HidD_SetOutputReport(
|
||||||
memset(report_data, 0, hid->caps.OutputReportByteLength);
|
hid->handle,
|
||||||
|
report_data.data(),
|
||||||
|
hid->caps.OutputReportByteLength);
|
||||||
|
std::fill(report_data.begin(), report_data.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the buttons
|
// clear the buttons
|
||||||
@@ -2061,22 +2093,22 @@ void rawinput::RawInputManager::device_write_output(Device *device, bool only_up
|
|||||||
HidP_Output,
|
HidP_Output,
|
||||||
button_cap.UsagePage,
|
button_cap.UsagePage,
|
||||||
button_cap.LinkCollection,
|
button_cap.LinkCollection,
|
||||||
&usage_off_list[0],
|
usage_off_list.data(),
|
||||||
&usage_off_list_length,
|
&usage_off_list_length,
|
||||||
reinterpret_cast<PHIDP_PREPARSED_DATA>(hid->preparsed_data.get()),
|
reinterpret_cast<PHIDP_PREPARSED_DATA>(hid->preparsed_data.get()),
|
||||||
report_data,
|
report_data.data(),
|
||||||
hid->caps.OutputReportByteLength) == HIDP_STATUS_INCOMPATIBLE_REPORT_ID) {
|
hid->caps.OutputReportByteLength) == HIDP_STATUS_INCOMPATIBLE_REPORT_ID) {
|
||||||
|
|
||||||
// flush report
|
// flush report
|
||||||
DWORD written_bytes = 0;
|
DWORD written_bytes = 0;
|
||||||
WriteFile(
|
WriteFile(
|
||||||
hid->handle,
|
hid->handle,
|
||||||
reinterpret_cast<void *>(report_data),
|
report_data.data(),
|
||||||
hid->caps.OutputReportByteLength,
|
hid->caps.OutputReportByteLength,
|
||||||
&written_bytes,
|
&written_bytes,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
memset(report_data, 0, hid->caps.OutputReportByteLength);
|
std::fill(report_data.begin(), report_data.end(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2105,19 +2137,19 @@ void rawinput::RawInputManager::device_write_output(Device *device, bool only_up
|
|||||||
value_cap.NotRange.Usage,
|
value_cap.NotRange.Usage,
|
||||||
static_cast<ULONG>(usage_value),
|
static_cast<ULONG>(usage_value),
|
||||||
reinterpret_cast<PHIDP_PREPARSED_DATA>(hid->preparsed_data.get()),
|
reinterpret_cast<PHIDP_PREPARSED_DATA>(hid->preparsed_data.get()),
|
||||||
report_data,
|
report_data.data(),
|
||||||
hid->caps.OutputReportByteLength) == HIDP_STATUS_INCOMPATIBLE_REPORT_ID) {
|
hid->caps.OutputReportByteLength) == HIDP_STATUS_INCOMPATIBLE_REPORT_ID) {
|
||||||
|
|
||||||
// flush report
|
// flush report
|
||||||
DWORD written_bytes = 0;
|
DWORD written_bytes = 0;
|
||||||
WriteFile(
|
WriteFile(
|
||||||
hid->handle,
|
hid->handle,
|
||||||
reinterpret_cast<void *>(report_data),
|
report_data.data(),
|
||||||
hid->caps.OutputReportByteLength,
|
hid->caps.OutputReportByteLength,
|
||||||
&written_bytes,
|
&written_bytes,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
memset(report_data, 0, hid->caps.OutputReportByteLength);
|
std::fill(report_data.begin(), report_data.end(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2151,15 +2183,12 @@ void rawinput::RawInputManager::device_write_output(Device *device, bool only_up
|
|||||||
DWORD written_bytes = 0;
|
DWORD written_bytes = 0;
|
||||||
WriteFile(
|
WriteFile(
|
||||||
hid->handle,
|
hid->handle,
|
||||||
reinterpret_cast<void *>(report_data),
|
report_data.data(),
|
||||||
hid->caps.OutputReportByteLength,
|
hid->caps.OutputReportByteLength,
|
||||||
&written_bytes,
|
&written_bytes,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
// delete report
|
|
||||||
delete[] report_data;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIDDriver::PacDrive: {
|
case HIDDriver::PacDrive: {
|
||||||
|
|||||||
@@ -319,7 +319,8 @@ namespace rawinput::touch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// iterate all input data and get touch points
|
// iterate all input data and get touch points
|
||||||
std::vector<HIDTouchPoint> touch_points;
|
thread_local std::vector<HIDTouchPoint> touch_points;
|
||||||
|
touch_points.clear();
|
||||||
touch_points.reserve(touch.elements_x.size());
|
touch_points.reserve(touch.elements_x.size());
|
||||||
for (size_t i = 0; i < touch.elements_x.size(); i++) {
|
for (size_t i = 0; i < touch.elements_x.size(); i++) {
|
||||||
|
|
||||||
@@ -424,9 +425,15 @@ namespace rawinput::touch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// process touch points
|
// process touch points
|
||||||
std::vector<DWORD> touch_removes;
|
thread_local std::vector<DWORD> touch_removes;
|
||||||
std::vector<TouchPoint> touch_writes;
|
thread_local std::vector<TouchPoint> touch_writes;
|
||||||
std::vector<DWORD> touch_modifications;
|
thread_local std::vector<DWORD> touch_modifications;
|
||||||
|
touch_removes.clear();
|
||||||
|
touch_writes.clear();
|
||||||
|
touch_modifications.clear();
|
||||||
|
touch_removes.reserve(touch.touch_points.size() + touch_points.size());
|
||||||
|
touch_writes.reserve(touch_points.size());
|
||||||
|
touch_modifications.reserve(touch_points.size());
|
||||||
|
|
||||||
// drop every touch point with the given id (marking it as released)
|
// drop every touch point with the given id (marking it as released)
|
||||||
auto remove_touch_point = [&] (DWORD id) {
|
auto remove_touch_point = [&] (DWORD id) {
|
||||||
@@ -581,7 +588,9 @@ namespace rawinput::touch {
|
|||||||
auto deadline = get_system_milliseconds() - 50;
|
auto deadline = get_system_milliseconds() - 50;
|
||||||
|
|
||||||
// check touch points
|
// check touch points
|
||||||
std::vector<DWORD> touch_removes;
|
thread_local std::vector<DWORD> touch_removes;
|
||||||
|
touch_removes.clear();
|
||||||
|
touch_removes.reserve(touch.touch_points.size());
|
||||||
auto touch_it = touch.touch_points.begin();
|
auto touch_it = touch.touch_points.begin();
|
||||||
while (touch_it != touch.touch_points.end()) {
|
while (touch_it != touch.touch_points.end()) {
|
||||||
auto &hid_tp = *touch_it;
|
auto &hid_tp = *touch_it;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <cstring>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/precise_timer.h"
|
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
#include "structuredmessage.h"
|
#include "structuredmessage.h"
|
||||||
|
|
||||||
@@ -218,8 +218,6 @@ bool Reader::set_comm_state(DWORD BaudRate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::wait_for_handshake() {
|
bool Reader::wait_for_handshake() {
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
// baud rates
|
// baud rates
|
||||||
DWORD baud_rates[] = { CBR_57600, CBR_38400, CBR_19200, CBR_9600 };
|
DWORD baud_rates[] = { CBR_57600, CBR_38400, CBR_19200, CBR_9600 };
|
||||||
|
|
||||||
@@ -270,7 +268,7 @@ bool Reader::wait_for_handshake() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sleep
|
// sleep
|
||||||
timer.sleep(50);
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
log_warning("reader", "{}: no handshake received for {} baud", this->port, baud_rates[i]);
|
log_warning("reader", "{}: no handshake received for {} baud", this->port, baud_rates[i]);
|
||||||
@@ -407,7 +405,6 @@ void start_reader_thread(const std::string &port, int id) {
|
|||||||
READER_THREAD_RUNNING = true;
|
READER_THREAD_RUNNING = true;
|
||||||
READER_THREADS.push_back(new std::thread([port, id]() {
|
READER_THREADS.push_back(new std::thread([port, id]() {
|
||||||
log_info("reader", "{}: starting reader thread", port);
|
log_info("reader", "{}: starting reader thread", port);
|
||||||
timeutils::PreciseSleepTimer timer;
|
|
||||||
|
|
||||||
while (READER_THREAD_RUNNING) {
|
while (READER_THREAD_RUNNING) {
|
||||||
|
|
||||||
@@ -445,22 +442,21 @@ void start_reader_thread(const std::string &port, int id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (did_read_card) {
|
if (did_read_card) {
|
||||||
timer.sleep(2500);
|
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.sleep(20);
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep between reader connection retries
|
// sleep between reader connection retries
|
||||||
if (READER_THREAD_RUNNING)
|
if (READER_THREAD_RUNNING)
|
||||||
timer.sleep(5000);
|
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// wait for thread to start
|
// wait for thread to start
|
||||||
timeutils::PreciseSleepTimer timer;
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
timer.sleep(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_reader_thread() {
|
void stop_reader_thread() {
|
||||||
|
|||||||
Reference in New Issue
Block a user