Files
Xenia-Canary/src/xenia/hid/input_system.cc
beeanyew cd17f1846f [Input System] xe_mutex revert
On request from chrisps, revert xe_mutex back to xe_unlikely_mutex to avoid mutex deadlocks while initializing hid-winkey.
2022-09-18 15:18:29 +02:00

145 lines
4.5 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/hid/input_system.h"
#include "xenia/base/profiling.h"
#include "xenia/hid/hid_flags.h"
#include "xenia/hid/input_driver.h"
namespace xe {
namespace hid {
DEFINE_bool(vibration, true, "Toggle controller vibration.", "HID");
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {}
InputSystem::~InputSystem() = default;
X_STATUS InputSystem::Setup() { return X_STATUS_SUCCESS; }
void InputSystem::AddDriver(std::unique_ptr<InputDriver> driver) {
drivers_.push_back(std::move(driver));
}
void InputSystem::UpdateUsedSlot(uint8_t slot, bool connected) {
if (slot == 0xFF) {
slot = 0;
}
if (connected) {
connected_slot |= (1 << slot);
} else {
connected_slot &= ~(1 << slot);
}
}
X_RESULT InputSystem::GetCapabilities(uint32_t user_index, uint32_t flags,
X_INPUT_CAPABILITIES* out_caps) {
SCOPE_profile_cpu_f("hid");
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->GetCapabilities(user_index, flags, out_caps);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
X_RESULT InputSystem::GetState(uint32_t user_index, X_INPUT_STATE* out_state) {
SCOPE_profile_cpu_f("hid");
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->GetState(user_index, out_state);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
X_RESULT InputSystem::SetState(uint32_t user_index,
X_INPUT_VIBRATION* vibration) {
SCOPE_profile_cpu_f("hid");
X_INPUT_VIBRATION modified_vibration = ModifyVibrationLevel(vibration);
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->SetState(user_index, &modified_vibration);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) {
SCOPE_profile_cpu_f("hid");
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->GetKeystroke(user_index, flags, out_keystroke);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS || result == X_ERROR_EMPTY) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
void InputSystem::ToggleVibration() {
OVERRIDE_bool(vibration, !cvars::vibration);
// Send instant update to vibration state to prevent awaiting for next tick.
X_INPUT_VIBRATION vibration = X_INPUT_VIBRATION();
for (uint8_t user_index = 0; user_index < 4; user_index++) {
SetState(user_index, &vibration);
}
}
X_INPUT_VIBRATION InputSystem::ModifyVibrationLevel(
X_INPUT_VIBRATION* vibration) {
X_INPUT_VIBRATION modified_vibration = *vibration;
if (cvars::vibration) {
return modified_vibration;
}
// TODO(Gliniak): Use modifier instead of boolean value.
modified_vibration.left_motor_speed = 0;
modified_vibration.right_motor_speed = 0;
return modified_vibration;
}
std::unique_lock<xe_unlikely_mutex> InputSystem::lock() {
return std::unique_lock<xe_unlikely_mutex>{lock_};
}
} // namespace hid
} // namespace xe