service/hid: Update mouse and keyboard to use ring lifo and the emulated device

This commit is contained in:
german77 2021-09-20 20:35:27 -05:00 committed by Narr the Reg
parent afe2d667d9
commit 800a66d25a
4 changed files with 70 additions and 157 deletions

View File

@ -5,14 +5,19 @@
#include <cstring> #include <cstring>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/keyboard.h" #include "core/hle/service/hid/controllers/keyboard.h"
namespace Service::HID { namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
constexpr u8 KEYS_PER_BYTE = 8; constexpr u8 KEYS_PER_BYTE = 8;
Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {} Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {
emulated_devices = system.HIDCore().GetEmulatedDevices();
}
Controller_Keyboard::~Controller_Keyboard() = default; Controller_Keyboard::~Controller_Keyboard() = default;
void Controller_Keyboard::OnInit() {} void Controller_Keyboard::OnInit() {}
@ -21,51 +26,26 @@ void Controller_Keyboard::OnRelease() {}
void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
std::size_t size) { std::size_t size) {
shared_memory.header.timestamp = core_timing.GetCPUTicks();
shared_memory.header.total_entry_count = 17;
if (!IsControllerActivated()) { if (!IsControllerActivated()) {
shared_memory.header.entry_count = 0; keyboard_lifo.entry_count = 0;
shared_memory.header.last_entry_index = 0; keyboard_lifo.last_entry_index = 0;
std::memcpy(data, &keyboard_lifo, sizeof(keyboard_lifo));
return; return;
} }
shared_memory.header.entry_count = 16;
const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; const auto& last_entry = keyboard_lifo.ReadCurrentEntry().state;
shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; next_state.sampling_number = last_entry.sampling_number + 1;
auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index];
cur_entry.sampling_number = last_entry.sampling_number + 1;
cur_entry.sampling_number2 = cur_entry.sampling_number;
cur_entry.key.fill(0);
if (Settings::values.keyboard_enabled) { if (Settings::values.keyboard_enabled) {
for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { const auto& keyboard_state = emulated_devices->GetKeyboard();
auto& entry = cur_entry.key[i / KEYS_PER_BYTE]; const auto& keyboard_modifier_state = emulated_devices->GetKeyboardModifier();
entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
}
using namespace Settings::NativeKeyboard; next_state.key = keyboard_state;
next_state.modifier = keyboard_modifier_state;
// TODO: Assign the correct key to all modifiers
cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus());
cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus());
cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus());
cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus());
cur_entry.modifier.gui.Assign(0);
cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus());
cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus());
cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus());
cur_entry.modifier.katakana.Assign(0);
cur_entry.modifier.hiragana.Assign(0);
} }
std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
keyboard_lifo.WriteNextEntry(next_state);
std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
} }
void Controller_Keyboard::OnLoadInputDevices() {
std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(),
keyboard_keys.begin(), Input::CreateDevice<Input::ButtonDevice>);
std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(),
keyboard_mods.begin(), Input::CreateDevice<Input::ButtonDevice>);
}
} // namespace Service::HID } // namespace Service::HID

View File

@ -10,8 +10,14 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/ring_lifo.h"
namespace Core::HID {
class EmulatedDevices;
struct KeyboardModifier;
struct KeyboardKey;
} // namespace Core::HID
namespace Service::HID { namespace Service::HID {
class Controller_Keyboard final : public ControllerBase { class Controller_Keyboard final : public ControllerBase {
@ -28,47 +34,20 @@ public:
// When the controller is requesting an update for the shared memory // When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
// Called when input devices should be loaded
void OnLoadInputDevices() override;
private: private:
struct Modifiers { // This is nn::hid::detail::KeyboardState
union {
u32_le raw{};
BitField<0, 1, u32> control;
BitField<1, 1, u32> shift;
BitField<2, 1, u32> left_alt;
BitField<3, 1, u32> right_alt;
BitField<4, 1, u32> gui;
BitField<8, 1, u32> caps_lock;
BitField<9, 1, u32> scroll_lock;
BitField<10, 1, u32> num_lock;
BitField<11, 1, u32> katakana;
BitField<12, 1, u32> hiragana;
};
};
static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size");
struct KeyboardState { struct KeyboardState {
s64_le sampling_number; s64_le sampling_number;
s64_le sampling_number2; Core::HID::KeyboardModifier modifier;
Core::HID::KeyboardKey key;
Modifiers modifier;
std::array<u8, 32> key;
}; };
static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size"); static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
struct SharedMemory { // This is nn::hid::detail::KeyboardLifo
CommonHeader header; Lifo<KeyboardState> keyboard_lifo{};
std::array<KeyboardState, 17> pad_states; static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
INSERT_PADDING_BYTES(0x28); KeyboardState next_state{};
};
static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size");
SharedMemory shared_memory{};
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeKeyboard::NumKeyboardKeys> Core::HID::EmulatedDevices* emulated_devices;
keyboard_keys;
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeKeyboard::NumKeyboardMods>
keyboard_mods;
}; };
} // namespace Service::HID } // namespace Service::HID

View File

@ -4,14 +4,19 @@
#include <cstring> #include <cstring>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/frontend/emu_window.h" #include "core/frontend/emu_window.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/mouse.h" #include "core/hle/service/hid/controllers/mouse.h"
namespace Service::HID { namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {} Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {
emulated_devices = system.HIDCore().GetEmulatedDevices();
}
Controller_Mouse::~Controller_Mouse() = default; Controller_Mouse::~Controller_Mouse() = default;
void Controller_Mouse::OnInit() {} void Controller_Mouse::OnInit() {}
@ -19,50 +24,35 @@ void Controller_Mouse::OnRelease() {}
void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
std::size_t size) { std::size_t size) {
shared_memory.header.timestamp = core_timing.GetCPUTicks(); mouse_lifo.timestamp = core_timing.GetCPUTicks();
shared_memory.header.total_entry_count = 17;
if (!IsControllerActivated()) { if (!IsControllerActivated()) {
shared_memory.header.entry_count = 0; mouse_lifo.entry_count = 0;
shared_memory.header.last_entry_index = 0; mouse_lifo.last_entry_index = 0;
std::memcpy(data, &mouse_lifo, sizeof(mouse_lifo));
return; return;
} }
shared_memory.header.entry_count = 16;
auto& last_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index]; const auto& last_entry = mouse_lifo.ReadCurrentEntry().state;
shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; next_state.sampling_number = last_entry.sampling_number + 1;
auto& cur_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index];
cur_entry.sampling_number = last_entry.sampling_number + 1; next_state.attribute.raw = 0;
cur_entry.sampling_number2 = cur_entry.sampling_number;
cur_entry.attribute.raw = 0;
if (Settings::values.mouse_enabled) { if (Settings::values.mouse_enabled) {
const auto [px, py, sx, sy] = mouse_device->GetStatus(); const auto& mouse_button_state = emulated_devices->GetMouseButtons();
const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width); const auto& mouse_position_state = emulated_devices->GetMousePosition();
const auto y = static_cast<s32>(py * Layout::ScreenUndocked::Height); next_state.attribute.is_connected.Assign(1);
cur_entry.x = x; next_state.x = mouse_position_state.x;
cur_entry.y = y; next_state.y = mouse_position_state.y;
cur_entry.delta_x = x - last_entry.x; next_state.delta_x = next_state.x - last_entry.x;
cur_entry.delta_y = y - last_entry.y; next_state.delta_y = next_state.y - last_entry.y;
cur_entry.mouse_wheel_x = sx; next_state.delta_wheel_x = mouse_position_state.delta_wheel_x;
cur_entry.mouse_wheel_y = sy; next_state.delta_wheel_y = mouse_position_state.delta_wheel_y;
cur_entry.attribute.is_connected.Assign(1);
using namespace Settings::NativeMouseButton; next_state.button = mouse_button_state;
cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus());
cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus());
cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus());
cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus());
cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus());
} }
std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); mouse_lifo.WriteNextEntry(next_state);
std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
} }
void Controller_Mouse::OnLoadInputDevices() {
//mouse_device = Input::CreateDevice<Input::MouseDevice>(Settings::values.mouse_device);
std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(),
mouse_button_devices.begin(), Input::CreateDevice<Input::ButtonDevice>);
}
} // namespace Service::HID } // namespace Service::HID

View File

@ -9,8 +9,13 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h" #include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/ring_lifo.h"
namespace Core::HID {
class EmulatedDevices;
struct MouseState;
} // namespace Core::HID
namespace Service::HID { namespace Service::HID {
class Controller_Mouse final : public ControllerBase { class Controller_Mouse final : public ControllerBase {
@ -27,53 +32,12 @@ public:
// When the controller is requesting an update for the shared memory // When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
// Called when input devices should be loaded
void OnLoadInputDevices() override;
private: private:
struct Buttons { // This is nn::hid::detail::MouseLifo
union { Lifo<Core::HID::MouseState> mouse_lifo{};
u32_le raw{}; static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
BitField<0, 1, u32> left; Core::HID::MouseState next_state{};
BitField<1, 1, u32> right;
BitField<2, 1, u32> middle;
BitField<3, 1, u32> forward;
BitField<4, 1, u32> back;
};
};
static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size");
struct Attributes { Core::HID::EmulatedDevices* emulated_devices;
union {
u32_le raw{};
BitField<0, 1, u32> transferable;
BitField<1, 1, u32> is_connected;
};
};
static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
struct MouseState {
s64_le sampling_number;
s64_le sampling_number2;
s32_le x;
s32_le y;
s32_le delta_x;
s32_le delta_y;
s32_le mouse_wheel_x;
s32_le mouse_wheel_y;
Buttons button;
Attributes attribute;
};
static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size");
struct SharedMemory {
CommonHeader header;
std::array<MouseState, 17> mouse_states;
};
SharedMemory shared_memory{};
std::unique_ptr<Input::MouseDevice> mouse_device;
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeMouseButton::NumMouseButtons>
mouse_button_devices;
}; };
} // namespace Service::HID } // namespace Service::HID