summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar Fernando S2021-11-27 11:52:08 +0100
committerGravatar GitHub2021-11-27 11:52:08 +0100
commit564f10527745f870621c08bbb5d16badee0ed861 (patch)
treee8ac8dee60086facf1837393882865f5df18c95e /src/core/hle
parentMerge pull request #7431 from liushuyu/fix-linux-decoding (diff)
parentconfig: Remove vibration configuration (diff)
downloadyuzu-564f10527745f870621c08bbb5d16badee0ed861.tar.gz
yuzu-564f10527745f870621c08bbb5d16badee0ed861.tar.xz
yuzu-564f10527745f870621c08bbb5d16badee0ed861.zip
Merge pull request #7255 from german77/kraken
Project Kraken: Input rewrite
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/am/applets/applet_controller.cpp19
-rw-r--r--src/core/hle/service/am/applets/applet_controller.h6
-rw-r--r--src/core/hle/service/am/applets/applets.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.cpp65
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.h44
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.h21
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp72
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h82
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp257
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h109
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp59
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h59
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp64
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h63
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp1617
-rw-r--r--src/core/hle/service/hid/controllers/npad.h649
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.cpp6
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.h13
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp139
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h86
-rw-r--r--src/core/hle/service/hid/controllers/xpad.cpp32
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h61
-rw-r--r--src/core/hle/service/hid/hid.cpp394
-rw-r--r--src/core/hle/service/hid/hid.h33
-rw-r--r--src/core/hle/service/hid/ring_lifo.h54
26 files changed, 1820 insertions, 2190 deletions
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 2721679c1..d073f2210 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -10,6 +10,9 @@
10#include "common/string_util.h" 10#include "common/string_util.h"
11#include "core/core.h" 11#include "core/core.h"
12#include "core/frontend/applets/controller.h" 12#include "core/frontend/applets/controller.h"
13#include "core/hid/emulated_controller.h"
14#include "core/hid/hid_core.h"
15#include "core/hid/hid_types.h"
13#include "core/hle/result.h" 16#include "core/hle/result.h"
14#include "core/hle/service/am/am.h" 17#include "core/hle/service/am/am.h"
15#include "core/hle/service/am/applets/applet_controller.h" 18#include "core/hle/service/am/applets/applet_controller.h"
@@ -25,7 +28,7 @@ namespace Service::AM::Applets {
25static Core::Frontend::ControllerParameters ConvertToFrontendParameters( 28static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
26 ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, 29 ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text,
27 std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) { 30 std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) {
28 HID::Controller_NPad::NpadStyleSet npad_style_set; 31 Core::HID::NpadStyleTag npad_style_set;
29 npad_style_set.raw = private_arg.style_set; 32 npad_style_set.raw = private_arg.style_set;
30 33
31 return { 34 return {
@@ -243,19 +246,11 @@ void Controller::Execute() {
243void Controller::ConfigurationComplete() { 246void Controller::ConfigurationComplete() {
244 ControllerSupportResultInfo result_info{}; 247 ControllerSupportResultInfo result_info{};
245 248
246 const auto& players = Settings::values.players.GetValue();
247
248 // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. 249 // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters.
249 // Otherwise, only count connected players from P1-P8. 250 // Otherwise, only count connected players from P1-P8.
250 result_info.player_count = 251 result_info.player_count = is_single_mode ? 1 : system.HIDCore().GetPlayerCount();
251 is_single_mode 252
252 ? 1 253 result_info.selected_id = static_cast<u32>(system.HIDCore().GetFirstNpadId());
253 : static_cast<s8>(std::count_if(players.begin(), players.end() - 2,
254 [](const auto& player) { return player.connected; }));
255
256 result_info.selected_id = HID::Controller_NPad::IndexToNPad(std::distance(
257 players.begin(), std::find_if(players.begin(), players.end(),
258 [](const auto& player) { return player.connected; })));
259 254
260 result_info.result = 0; 255 result_info.result = 0;
261 256
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h
index 0a34c4fc0..1a832505e 100644
--- a/src/core/hle/service/am/applets/applet_controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
@@ -16,6 +16,10 @@ namespace Core {
16class System; 16class System;
17} 17}
18 18
19namespace Core::HID {
20enum class NpadStyleSet : u32;
21}
22
19namespace Service::AM::Applets { 23namespace Service::AM::Applets {
20 24
21using IdentificationColor = std::array<u8, 4>; 25using IdentificationColor = std::array<u8, 4>;
@@ -52,7 +56,7 @@ struct ControllerSupportArgPrivate {
52 bool flag_1{}; 56 bool flag_1{};
53 ControllerSupportMode mode{}; 57 ControllerSupportMode mode{};
54 ControllerSupportCaller caller{}; 58 ControllerSupportCaller caller{};
55 u32 style_set{}; 59 Core::HID::NpadStyleSet style_set{};
56 u32 joy_hold_type{}; 60 u32 joy_hold_type{};
57}; 61};
58static_assert(sizeof(ControllerSupportArgPrivate) == 0x14, 62static_assert(sizeof(ControllerSupportArgPrivate) == 0x14,
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 7320b1c0f..134ac1ee2 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -231,7 +231,7 @@ void AppletManager::SetDefaultAppletFrontendSet() {
231void AppletManager::SetDefaultAppletsIfMissing() { 231void AppletManager::SetDefaultAppletsIfMissing() {
232 if (frontend.controller == nullptr) { 232 if (frontend.controller == nullptr) {
233 frontend.controller = 233 frontend.controller =
234 std::make_unique<Core::Frontend::DefaultControllerApplet>(system.ServiceManager()); 234 std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore());
235 } 235 }
236 236
237 if (frontend.error == nullptr) { 237 if (frontend.error == nullptr) {
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index bda6e2557..f0f3105dc 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -4,13 +4,18 @@
4 4
5#include "common/settings.h" 5#include "common/settings.h"
6#include "core/core_timing.h" 6#include "core/core_timing.h"
7#include "core/hid/emulated_console.h"
8#include "core/hid/hid_core.h"
7#include "core/hle/service/hid/controllers/console_sixaxis.h" 9#include "core/hle/service/hid/controllers/console_sixaxis.h"
8 10
9namespace Service::HID { 11namespace Service::HID {
10constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; 12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
11 13
12Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_) 14Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_)
13 : ControllerBase{system_} {} 15 : ControllerBase{hid_core_} {
16 console = hid_core.GetEmulatedConsole();
17}
18
14Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; 19Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default;
15 20
16void Controller_ConsoleSixAxis::OnInit() {} 21void Controller_ConsoleSixAxis::OnInit() {}
@@ -19,44 +24,31 @@ void Controller_ConsoleSixAxis::OnRelease() {}
19 24
20void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 25void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
21 std::size_t size) { 26 std::size_t size) {
22 seven_six_axis.header.timestamp = core_timing.GetCPUTicks();
23 seven_six_axis.header.total_entry_count = 17;
24
25 if (!IsControllerActivated() || !is_transfer_memory_set) { 27 if (!IsControllerActivated() || !is_transfer_memory_set) {
26 seven_six_axis.header.entry_count = 0; 28 seven_sixaxis_lifo.buffer_count = 0;
27 seven_six_axis.header.last_entry_index = 0; 29 seven_sixaxis_lifo.buffer_tail = 0;
28 return; 30 return;
29 } 31 }
30 seven_six_axis.header.entry_count = 16;
31
32 const auto& last_entry =
33 seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index];
34 seven_six_axis.header.last_entry_index = (seven_six_axis.header.last_entry_index + 1) % 17;
35 auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index];
36 32
37 cur_entry.sampling_number = last_entry.sampling_number + 1; 33 const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state;
38 cur_entry.sampling_number2 = cur_entry.sampling_number; 34 next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1;
39 35
40 // Try to read sixaxis sensor states 36 // Try to read sixaxis sensor states
41 MotionDevice motion_device{}; 37 const auto motion_status = console->GetMotion();
42 const auto& device = motions[0]; 38
43 if (device) { 39 console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
44 std::tie(motion_device.accel, motion_device.gyro, motion_device.rotation,
45 motion_device.orientation, motion_device.quaternion) = device->GetStatus();
46 console_six_axis.is_seven_six_axis_sensor_at_rest = motion_device.gyro.Length2() < 0.0001f;
47 }
48 40
49 cur_entry.accel = motion_device.accel; 41 next_seven_sixaxis_state.accel = motion_status.accel;
50 // Zero gyro values as they just mess up with the camera 42 // Zero gyro values as they just mess up with the camera
51 // Note: Probably a correct sensivity setting must be set 43 // Note: Probably a correct sensivity setting must be set
52 cur_entry.gyro = {}; 44 next_seven_sixaxis_state.gyro = {};
53 cur_entry.quaternion = { 45 next_seven_sixaxis_state.quaternion = {
54 { 46 {
55 motion_device.quaternion.xyz.y, 47 motion_status.quaternion.xyz.y,
56 motion_device.quaternion.xyz.x, 48 motion_status.quaternion.xyz.x,
57 -motion_device.quaternion.w, 49 -motion_status.quaternion.w,
58 }, 50 },
59 -motion_device.quaternion.xyz.z, 51 -motion_status.quaternion.xyz.z,
60 }; 52 };
61 53
62 console_six_axis.sampling_number++; 54 console_six_axis.sampling_number++;
@@ -67,14 +59,8 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
67 // Update console six axis shared memory 59 // Update console six axis shared memory
68 std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis)); 60 std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));
69 // Update seven six axis transfer memory 61 // Update seven six axis transfer memory
70 std::memcpy(transfer_memory, &seven_six_axis, sizeof(seven_six_axis)); 62 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
71} 63 std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo));
72
73void Controller_ConsoleSixAxis::OnLoadInputDevices() {
74 const auto player = Settings::values.players.GetValue()[0];
75 std::transform(player.motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
76 player.motions.begin() + Settings::NativeMotion::MOTION_HID_END, motions.begin(),
77 Input::CreateDevice<Input::MotionDevice>);
78} 64}
79 65
80void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) { 66void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
@@ -83,8 +69,7 @@ void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
83} 69}
84 70
85void Controller_ConsoleSixAxis::ResetTimestamp() { 71void Controller_ConsoleSixAxis::ResetTimestamp() {
86 auto& cur_entry = seven_six_axis.sevensixaxis_states[seven_six_axis.header.last_entry_index]; 72 seven_sixaxis_lifo.buffer_count = 0;
87 cur_entry.sampling_number = 0; 73 seven_sixaxis_lifo.buffer_tail = 0;
88 cur_entry.sampling_number2 = 0;
89} 74}
90} // namespace Service::HID 75} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index fd8a427af..279241858 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -5,16 +5,21 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include "common/bit_field.h" 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/quaternion.h" 10#include "common/quaternion.h"
11#include "core/frontend/input.h" 11#include "core/hid/hid_types.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 12#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h"
14
15namespace Core::HID {
16class EmulatedConsole;
17} // namespace Core::HID
13 18
14namespace Service::HID { 19namespace Service::HID {
15class Controller_ConsoleSixAxis final : public ControllerBase { 20class Controller_ConsoleSixAxis final : public ControllerBase {
16public: 21public:
17 explicit Controller_ConsoleSixAxis(Core::System& system_); 22 explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_);
18 ~Controller_ConsoleSixAxis() override; 23 ~Controller_ConsoleSixAxis() override;
19 24
20 // Called when the controller is initialized 25 // Called when the controller is initialized
@@ -26,9 +31,6 @@ public:
26 // When the controller is requesting an update for the shared memory 31 // When the controller is requesting an update for the shared memory
27 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; 32 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override;
28 33
29 // Called when input devices should be loaded
30 void OnLoadInputDevices() override;
31
32 // Called on InitializeSevenSixAxisSensor 34 // Called on InitializeSevenSixAxisSensor
33 void SetTransferMemoryPointer(u8* t_mem); 35 void SetTransferMemoryPointer(u8* t_mem);
34 36
@@ -38,43 +40,31 @@ public:
38private: 40private:
39 struct SevenSixAxisState { 41 struct SevenSixAxisState {
40 INSERT_PADDING_WORDS(4); // unused 42 INSERT_PADDING_WORDS(4); // unused
41 s64_le sampling_number{}; 43 s64 sampling_number{};
42 s64_le sampling_number2{};
43 u64 unknown{}; 44 u64 unknown{};
44 Common::Vec3f accel{}; 45 Common::Vec3f accel{};
45 Common::Vec3f gyro{}; 46 Common::Vec3f gyro{};
46 Common::Quaternion<f32> quaternion{}; 47 Common::Quaternion<f32> quaternion{};
47 }; 48 };
48 static_assert(sizeof(SevenSixAxisState) == 0x50, "SevenSixAxisState is an invalid size"); 49 static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
49
50 struct SevenSixAxisMemory {
51 CommonHeader header{};
52 std::array<SevenSixAxisState, 0x21> sevensixaxis_states{};
53 };
54 static_assert(sizeof(SevenSixAxisMemory) == 0xA70, "SevenSixAxisMemory is an invalid size");
55 50
51 // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
56 struct ConsoleSharedMemory { 52 struct ConsoleSharedMemory {
57 u64_le sampling_number{}; 53 u64 sampling_number{};
58 bool is_seven_six_axis_sensor_at_rest{}; 54 bool is_seven_six_axis_sensor_at_rest{};
55 INSERT_PADDING_BYTES(4); // padding
59 f32 verticalization_error{}; 56 f32 verticalization_error{};
60 Common::Vec3f gyro_bias{}; 57 Common::Vec3f gyro_bias{};
61 }; 58 };
62 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); 59 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
63 60
64 struct MotionDevice { 61 Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
65 Common::Vec3f accel; 62 static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
66 Common::Vec3f gyro;
67 Common::Vec3f rotation;
68 std::array<Common::Vec3f, 3> orientation;
69 Common::Quaternion<f32> quaternion;
70 };
71 63
72 using MotionArray = 64 Core::HID::EmulatedConsole* console;
73 std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>;
74 MotionArray motions;
75 u8* transfer_memory = nullptr; 65 u8* transfer_memory = nullptr;
76 bool is_transfer_memory_set = false; 66 bool is_transfer_memory_set = false;
77 ConsoleSharedMemory console_six_axis{}; 67 ConsoleSharedMemory console_six_axis{};
78 SevenSixAxisMemory seven_six_axis{}; 68 SevenSixAxisState next_seven_sixaxis_state{};
79}; 69};
80} // namespace Service::HID 70} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp
index 9d1e6db6a..788ae9ae7 100644
--- a/src/core/hle/service/hid/controllers/controller_base.cpp
+++ b/src/core/hle/service/hid/controllers/controller_base.cpp
@@ -6,12 +6,12 @@
6 6
7namespace Service::HID { 7namespace Service::HID {
8 8
9ControllerBase::ControllerBase(Core::System& system_) : system(system_) {} 9ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {}
10ControllerBase::~ControllerBase() = default; 10ControllerBase::~ControllerBase() = default;
11 11
12void ControllerBase::ActivateController() { 12void ControllerBase::ActivateController() {
13 if (is_activated) { 13 if (is_activated) {
14 OnRelease(); 14 return;
15 } 15 }
16 is_activated = true; 16 is_activated = true;
17 OnInit(); 17 OnInit();
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index 1556fb08e..7450eb20a 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -11,14 +11,14 @@ namespace Core::Timing {
11class CoreTiming; 11class CoreTiming;
12} 12}
13 13
14namespace Core { 14namespace Core::HID {
15class System; 15class HIDCore;
16} 16}
17 17
18namespace Service::HID { 18namespace Service::HID {
19class ControllerBase { 19class ControllerBase {
20public: 20public:
21 explicit ControllerBase(Core::System& system_); 21 explicit ControllerBase(Core::HID::HIDCore& hid_core_);
22 virtual ~ControllerBase(); 22 virtual ~ControllerBase();
23 23
24 // Called when the controller is initialized 24 // Called when the controller is initialized
@@ -35,26 +35,17 @@ public:
35 virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 35 virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
36 std::size_t size) {} 36 std::size_t size) {}
37 37
38 // Called when input devices should be loaded
39 virtual void OnLoadInputDevices() = 0;
40
41 void ActivateController(); 38 void ActivateController();
42 39
43 void DeactivateController(); 40 void DeactivateController();
44 41
45 bool IsControllerActivated() const; 42 bool IsControllerActivated() const;
46 43
44 static const std::size_t hid_entry_count = 17;
45
47protected: 46protected:
48 bool is_activated{false}; 47 bool is_activated{false};
49 48
50 struct CommonHeader { 49 Core::HID::HIDCore& hid_core;
51 s64_le timestamp;
52 s64_le total_entry_count;
53 s64_le last_entry_index;
54 s64_le entry_count;
55 };
56 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
57
58 Core::System& system;
59}; 50};
60} // namespace Service::HID 51} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index d439b8fb0..6a6fb9cab 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -6,15 +6,19 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/settings.h" 7#include "common/settings.h"
8#include "core/core_timing.h" 8#include "core/core_timing.h"
9#include "core/hid/emulated_controller.h"
10#include "core/hid/hid_core.h"
11#include "core/hid/hid_types.h"
9#include "core/hle/service/hid/controllers/debug_pad.h" 12#include "core/hle/service/hid/controllers/debug_pad.h"
10 13
11namespace Service::HID { 14namespace Service::HID {
15constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
12 16
13constexpr s32 HID_JOYSTICK_MAX = 0x7fff; 17Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_)
14[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; 18 : ControllerBase{hid_core_} {
15enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; 19 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
20}
16 21
17Controller_DebugPad::Controller_DebugPad(Core::System& system_) : ControllerBase{system_} {}
18Controller_DebugPad::~Controller_DebugPad() = default; 22Controller_DebugPad::~Controller_DebugPad() = default;
19 23
20void Controller_DebugPad::OnInit() {} 24void Controller_DebugPad::OnInit() {}
@@ -23,63 +27,29 @@ void Controller_DebugPad::OnRelease() {}
23 27
24void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 28void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
25 std::size_t size) { 29 std::size_t size) {
26 shared_memory.header.timestamp = core_timing.GetCPUTicks();
27 shared_memory.header.total_entry_count = 17;
28
29 if (!IsControllerActivated()) { 30 if (!IsControllerActivated()) {
30 shared_memory.header.entry_count = 0; 31 debug_pad_lifo.buffer_count = 0;
31 shared_memory.header.last_entry_index = 0; 32 debug_pad_lifo.buffer_tail = 0;
33 std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
32 return; 34 return;
33 } 35 }
34 shared_memory.header.entry_count = 16;
35 36
36 const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index]; 37 const auto& last_entry = debug_pad_lifo.ReadCurrentEntry().state;
37 shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; 38 next_state.sampling_number = last_entry.sampling_number + 1;
38 auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index];
39
40 cur_entry.sampling_number = last_entry.sampling_number + 1;
41 cur_entry.sampling_number2 = cur_entry.sampling_number;
42 39
43 if (Settings::values.debug_pad_enabled) { 40 if (Settings::values.debug_pad_enabled) {
44 cur_entry.attribute.connected.Assign(1); 41 next_state.attribute.connected.Assign(1);
45 auto& pad = cur_entry.pad_state;
46 42
47 using namespace Settings::NativeButton; 43 const auto& button_state = controller->GetDebugPadButtons();
48 pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); 44 const auto& stick_state = controller->GetSticks();
49 pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
50 pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
51 pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
52 pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
53 pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
54 pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
55 pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
56 pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
57 pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
58 pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
59 pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
60 pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
61 pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
62 45
63 const auto [stick_l_x_f, stick_l_y_f] = 46 next_state.pad_state = button_state;
64 analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus(); 47 next_state.l_stick = stick_state.left;
65 const auto [stick_r_x_f, stick_r_y_f] = 48 next_state.r_stick = stick_state.right;
66 analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
67 cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
68 cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
69 cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
70 cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
71 } 49 }
72 50
73 std::memcpy(data, &shared_memory, sizeof(SharedMemory)); 51 debug_pad_lifo.WriteNextEntry(next_state);
52 std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
74} 53}
75 54
76void Controller_DebugPad::OnLoadInputDevices() {
77 std::transform(Settings::values.debug_pad_buttons.begin(),
78 Settings::values.debug_pad_buttons.begin() +
79 Settings::NativeButton::NUM_BUTTONS_HID,
80 buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
81 std::transform(Settings::values.debug_pad_analogs.begin(),
82 Settings::values.debug_pad_analogs.end(), analogs.begin(),
83 Input::CreateDevice<Input::AnalogDevice>);
84}
85} // namespace Service::HID 55} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 1b1645184..afe374fc2 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -8,15 +8,20 @@
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/settings.h"
12#include "common/swap.h" 11#include "common/swap.h"
13#include "core/frontend/input.h"
14#include "core/hle/service/hid/controllers/controller_base.h" 12#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h"
14
15namespace Core::HID {
16class EmulatedController;
17struct DebugPadButton;
18struct AnalogStickState;
19} // namespace Core::HID
15 20
16namespace Service::HID { 21namespace Service::HID {
17class Controller_DebugPad final : public ControllerBase { 22class Controller_DebugPad final : public ControllerBase {
18public: 23public:
19 explicit Controller_DebugPad(Core::System& system_); 24 explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_);
20 ~Controller_DebugPad() override; 25 ~Controller_DebugPad() override;
21 26
22 // Called when the controller is initialized 27 // Called when the controller is initialized
@@ -28,66 +33,31 @@ public:
28 // When the controller is requesting an update for the shared memory 33 // When the controller is requesting an update for the shared memory
29 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 34 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
30 35
31 // Called when input devices should be loaded
32 void OnLoadInputDevices() override;
33
34private: 36private:
35 struct AnalogStick { 37 // This is nn::hid::DebugPadAttribute
36 s32_le x; 38 struct DebugPadAttribute {
37 s32_le y;
38 };
39 static_assert(sizeof(AnalogStick) == 0x8);
40
41 struct PadState {
42 union {
43 u32_le raw{};
44 BitField<0, 1, u32> a;
45 BitField<1, 1, u32> b;
46 BitField<2, 1, u32> x;
47 BitField<3, 1, u32> y;
48 BitField<4, 1, u32> l;
49 BitField<5, 1, u32> r;
50 BitField<6, 1, u32> zl;
51 BitField<7, 1, u32> zr;
52 BitField<8, 1, u32> plus;
53 BitField<9, 1, u32> minus;
54 BitField<10, 1, u32> d_left;
55 BitField<11, 1, u32> d_up;
56 BitField<12, 1, u32> d_right;
57 BitField<13, 1, u32> d_down;
58 };
59 };
60 static_assert(sizeof(PadState) == 0x4, "PadState is an invalid size");
61
62 struct Attributes {
63 union { 39 union {
64 u32_le raw{}; 40 u32 raw{};
65 BitField<0, 1, u32> connected; 41 BitField<0, 1, u32> connected;
66 }; 42 };
67 }; 43 };
68 static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); 44 static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
69 45
70 struct PadStates { 46 // This is nn::hid::DebugPadState
71 s64_le sampling_number; 47 struct DebugPadState {
72 s64_le sampling_number2; 48 s64 sampling_number;
73 Attributes attribute; 49 DebugPadAttribute attribute;
74 PadState pad_state; 50 Core::HID::DebugPadButton pad_state;
75 AnalogStick r_stick; 51 Core::HID::AnalogStickState r_stick;
76 AnalogStick l_stick; 52 Core::HID::AnalogStickState l_stick;
77 }; 53 };
78 static_assert(sizeof(PadStates) == 0x28, "PadStates is an invalid state"); 54 static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
79 55
80 struct SharedMemory { 56 // This is nn::hid::detail::DebugPadLifo
81 CommonHeader header; 57 Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
82 std::array<PadStates, 17> pad_states; 58 static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
83 INSERT_PADDING_BYTES(0x138); 59 DebugPadState next_state{};
84 };
85 static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size");
86 SharedMemory shared_memory{};
87 60
88 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> 61 Core::HID::EmulatedController* controller;
89 buttons;
90 std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>
91 analogs;
92}; 62};
93} // namespace Service::HID 63} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 764abb5b6..fe895c4f6 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -7,6 +7,7 @@
7#include "common/settings.h" 7#include "common/settings.h"
8#include "core/core_timing.h" 8#include "core/core_timing.h"
9#include "core/frontend/emu_window.h" 9#include "core/frontend/emu_window.h"
10#include "core/hid/hid_core.h"
10#include "core/hle/service/hid/controllers/gesture.h" 11#include "core/hle/service/hid/controllers/gesture.h"
11 12
12namespace Service::HID { 13namespace Service::HID {
@@ -23,16 +24,14 @@ constexpr f32 Square(s32 num) {
23 return static_cast<f32>(num * num); 24 return static_cast<f32>(num * num);
24} 25}
25 26
26Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {} 27Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) {
28 console = hid_core.GetEmulatedConsole();
29}
27Controller_Gesture::~Controller_Gesture() = default; 30Controller_Gesture::~Controller_Gesture() = default;
28 31
29void Controller_Gesture::OnInit() { 32void Controller_Gesture::OnInit() {
30 for (std::size_t id = 0; id < MAX_FINGERS; ++id) { 33 gesture_lifo.buffer_count = 0;
31 mouse_finger_id[id] = MAX_POINTS; 34 gesture_lifo.buffer_tail = 0;
32 keyboard_finger_id[id] = MAX_POINTS;
33 udp_finger_id[id] = MAX_POINTS;
34 }
35 shared_memory.header.entry_count = 0;
36 force_update = true; 35 force_update = true;
37} 36}
38 37
@@ -40,50 +39,38 @@ void Controller_Gesture::OnRelease() {}
40 39
41void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 40void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
42 std::size_t size) { 41 std::size_t size) {
43 shared_memory.header.timestamp = core_timing.GetCPUTicks();
44 shared_memory.header.total_entry_count = 17;
45
46 if (!IsControllerActivated()) { 42 if (!IsControllerActivated()) {
47 shared_memory.header.entry_count = 0; 43 gesture_lifo.buffer_count = 0;
48 shared_memory.header.last_entry_index = 0; 44 gesture_lifo.buffer_tail = 0;
45 std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
49 return; 46 return;
50 } 47 }
51 48
52 ReadTouchInput(); 49 ReadTouchInput();
53 50
54 GestureProperties gesture = GetGestureProperties(); 51 GestureProperties gesture = GetGestureProperties();
55 f32 time_difference = static_cast<f32>(shared_memory.header.timestamp - last_update_timestamp) / 52 f32 time_difference =
56 (1000 * 1000 * 1000); 53 static_cast<f32>(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000);
57 54
58 // Only update if necesary 55 // Only update if necesary
59 if (!ShouldUpdateGesture(gesture, time_difference)) { 56 if (!ShouldUpdateGesture(gesture, time_difference)) {
60 return; 57 return;
61 } 58 }
62 59
63 last_update_timestamp = shared_memory.header.timestamp; 60 last_update_timestamp = gesture_lifo.timestamp;
64 UpdateGestureSharedMemory(data, size, gesture, time_difference); 61 UpdateGestureSharedMemory(data, size, gesture, time_difference);
65} 62}
66 63
67void Controller_Gesture::ReadTouchInput() { 64void Controller_Gesture::ReadTouchInput() {
68 const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); 65 const auto touch_status = console->GetTouch();
69 const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); 66 for (std::size_t id = 0; id < fingers.size(); ++id) {
70 for (std::size_t id = 0; id < mouse_status.size(); ++id) { 67 fingers[id] = touch_status[id];
71 mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]);
72 udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]);
73 }
74
75 if (Settings::values.use_touch_from_button) {
76 const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus();
77 for (std::size_t id = 0; id < mouse_status.size(); ++id) {
78 keyboard_finger_id[id] =
79 UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]);
80 }
81 } 68 }
82} 69}
83 70
84bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, 71bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
85 f32 time_difference) { 72 f32 time_difference) {
86 const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; 73 const auto& last_entry = GetLastGestureEntry();
87 if (force_update) { 74 if (force_update) {
88 force_update = false; 75 force_update = false;
89 return true; 76 return true;
@@ -97,7 +84,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
97 } 84 }
98 85
99 // Update on press and hold event after 0.5 seconds 86 // Update on press and hold event after 0.5 seconds
100 if (last_entry.type == TouchType::Touch && last_entry.point_count == 1 && 87 if (last_entry.type == GestureType::Touch && last_entry.point_count == 1 &&
101 time_difference > press_delay) { 88 time_difference > press_delay) {
102 return enable_press_and_tap; 89 return enable_press_and_tap;
103 } 90 }
@@ -108,27 +95,19 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
108void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, 95void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
109 GestureProperties& gesture, 96 GestureProperties& gesture,
110 f32 time_difference) { 97 f32 time_difference) {
111 TouchType type = TouchType::Idle; 98 GestureType type = GestureType::Idle;
112 Attribute attributes{}; 99 GestureAttribute attributes{};
113 100
114 const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; 101 const auto& last_entry = gesture_lifo.ReadCurrentEntry().state;
115 shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17;
116 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
117 102
118 if (shared_memory.header.entry_count < 16) { 103 // Reset next state to default
119 shared_memory.header.entry_count++; 104 next_state.sampling_number = last_entry.sampling_number + 1;
120 } 105 next_state.delta = {};
121 106 next_state.vel_x = 0;
122 cur_entry.sampling_number = last_entry.sampling_number + 1; 107 next_state.vel_y = 0;
123 cur_entry.sampling_number2 = cur_entry.sampling_number; 108 next_state.direction = GestureDirection::None;
124 109 next_state.rotation_angle = 0;
125 // Reset values to default 110 next_state.scale = 0;
126 cur_entry.delta = {};
127 cur_entry.vel_x = 0;
128 cur_entry.vel_y = 0;
129 cur_entry.direction = Direction::None;
130 cur_entry.rotation_angle = 0;
131 cur_entry.scale = 0;
132 111
133 if (gesture.active_points > 0) { 112 if (gesture.active_points > 0) {
134 if (last_gesture.active_points == 0) { 113 if (last_gesture.active_points == 0) {
@@ -141,46 +120,47 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
141 } 120 }
142 121
143 // Apply attributes 122 // Apply attributes
144 cur_entry.detection_count = gesture.detection_count; 123 next_state.detection_count = gesture.detection_count;
145 cur_entry.type = type; 124 next_state.type = type;
146 cur_entry.attributes = attributes; 125 next_state.attributes = attributes;
147 cur_entry.pos = gesture.mid_point; 126 next_state.pos = gesture.mid_point;
148 cur_entry.point_count = static_cast<s32>(gesture.active_points); 127 next_state.point_count = static_cast<s32>(gesture.active_points);
149 cur_entry.points = gesture.points; 128 next_state.points = gesture.points;
150 last_gesture = gesture; 129 last_gesture = gesture;
151 130
152 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 131 gesture_lifo.WriteNextEntry(next_state);
132 std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
153} 133}
154 134
155void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type, 135void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
156 Attribute& attributes) { 136 GestureAttribute& attributes) {
157 const auto& last_entry = GetLastGestureEntry(); 137 const auto& last_entry = GetLastGestureEntry();
158 138
159 gesture.detection_count++; 139 gesture.detection_count++;
160 type = TouchType::Touch; 140 type = GestureType::Touch;
161 141
162 // New touch after cancel is not considered new 142 // New touch after cancel is not considered new
163 if (last_entry.type != TouchType::Cancel) { 143 if (last_entry.type != GestureType::Cancel) {
164 attributes.is_new_touch.Assign(1); 144 attributes.is_new_touch.Assign(1);
165 enable_press_and_tap = true; 145 enable_press_and_tap = true;
166 } 146 }
167} 147}
168 148
169void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type, 149void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
170 f32 time_difference) { 150 f32 time_difference) {
171 const auto& last_entry = GetLastGestureEntry(); 151 const auto& last_entry = GetLastGestureEntry();
172 152
173 // Promote to pan type if touch moved 153 // Promote to pan type if touch moved
174 for (size_t id = 0; id < MAX_POINTS; id++) { 154 for (size_t id = 0; id < MAX_POINTS; id++) {
175 if (gesture.points[id] != last_gesture.points[id]) { 155 if (gesture.points[id] != last_gesture.points[id]) {
176 type = TouchType::Pan; 156 type = GestureType::Pan;
177 break; 157 break;
178 } 158 }
179 } 159 }
180 160
181 // Number of fingers changed cancel the last event and clear data 161 // Number of fingers changed cancel the last event and clear data
182 if (gesture.active_points != last_gesture.active_points) { 162 if (gesture.active_points != last_gesture.active_points) {
183 type = TouchType::Cancel; 163 type = GestureType::Cancel;
184 enable_press_and_tap = false; 164 enable_press_and_tap = false;
185 gesture.active_points = 0; 165 gesture.active_points = 0;
186 gesture.mid_point = {}; 166 gesture.mid_point = {};
@@ -189,41 +169,41 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Touch
189 } 169 }
190 170
191 // Calculate extra parameters of panning 171 // Calculate extra parameters of panning
192 if (type == TouchType::Pan) { 172 if (type == GestureType::Pan) {
193 UpdatePanEvent(gesture, last_gesture, type, time_difference); 173 UpdatePanEvent(gesture, last_gesture, type, time_difference);
194 return; 174 return;
195 } 175 }
196 176
197 // Promote to press type 177 // Promote to press type
198 if (last_entry.type == TouchType::Touch) { 178 if (last_entry.type == GestureType::Touch) {
199 type = TouchType::Press; 179 type = GestureType::Press;
200 } 180 }
201} 181}
202 182
203void Controller_Gesture::EndGesture(GestureProperties& gesture, 183void Controller_Gesture::EndGesture(GestureProperties& gesture,
204 GestureProperties& last_gesture_props, TouchType& type, 184 GestureProperties& last_gesture_props, GestureType& type,
205 Attribute& attributes, f32 time_difference) { 185 GestureAttribute& attributes, f32 time_difference) {
206 const auto& last_entry = GetLastGestureEntry(); 186 const auto& last_entry = GetLastGestureEntry();
207 187
208 if (last_gesture_props.active_points != 0) { 188 if (last_gesture_props.active_points != 0) {
209 switch (last_entry.type) { 189 switch (last_entry.type) {
210 case TouchType::Touch: 190 case GestureType::Touch:
211 if (enable_press_and_tap) { 191 if (enable_press_and_tap) {
212 SetTapEvent(gesture, last_gesture_props, type, attributes); 192 SetTapEvent(gesture, last_gesture_props, type, attributes);
213 return; 193 return;
214 } 194 }
215 type = TouchType::Cancel; 195 type = GestureType::Cancel;
216 force_update = true; 196 force_update = true;
217 break; 197 break;
218 case TouchType::Press: 198 case GestureType::Press:
219 case TouchType::Tap: 199 case GestureType::Tap:
220 case TouchType::Swipe: 200 case GestureType::Swipe:
221 case TouchType::Pinch: 201 case GestureType::Pinch:
222 case TouchType::Rotate: 202 case GestureType::Rotate:
223 type = TouchType::Complete; 203 type = GestureType::Complete;
224 force_update = true; 204 force_update = true;
225 break; 205 break;
226 case TouchType::Pan: 206 case GestureType::Pan:
227 EndPanEvent(gesture, last_gesture_props, type, time_difference); 207 EndPanEvent(gesture, last_gesture_props, type, time_difference);
228 break; 208 break;
229 default: 209 default:
@@ -231,15 +211,15 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture,
231 } 211 }
232 return; 212 return;
233 } 213 }
234 if (last_entry.type == TouchType::Complete || last_entry.type == TouchType::Cancel) { 214 if (last_entry.type == GestureType::Complete || last_entry.type == GestureType::Cancel) {
235 gesture.detection_count++; 215 gesture.detection_count++;
236 } 216 }
237} 217}
238 218
239void Controller_Gesture::SetTapEvent(GestureProperties& gesture, 219void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
240 GestureProperties& last_gesture_props, TouchType& type, 220 GestureProperties& last_gesture_props, GestureType& type,
241 Attribute& attributes) { 221 GestureAttribute& attributes) {
242 type = TouchType::Tap; 222 type = GestureType::Tap;
243 gesture = last_gesture_props; 223 gesture = last_gesture_props;
244 force_update = true; 224 force_update = true;
245 f32 tap_time_difference = 225 f32 tap_time_difference =
@@ -251,44 +231,42 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
251} 231}
252 232
253void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, 233void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
254 GestureProperties& last_gesture_props, TouchType& type, 234 GestureProperties& last_gesture_props, GestureType& type,
255 f32 time_difference) { 235 f32 time_difference) {
256 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
257 const auto& last_entry = GetLastGestureEntry(); 236 const auto& last_entry = GetLastGestureEntry();
258 237
259 cur_entry.delta = gesture.mid_point - last_entry.pos; 238 next_state.delta = gesture.mid_point - last_entry.pos;
260 cur_entry.vel_x = static_cast<f32>(cur_entry.delta.x) / time_difference; 239 next_state.vel_x = static_cast<f32>(next_state.delta.x) / time_difference;
261 cur_entry.vel_y = static_cast<f32>(cur_entry.delta.y) / time_difference; 240 next_state.vel_y = static_cast<f32>(next_state.delta.y) / time_difference;
262 last_pan_time_difference = time_difference; 241 last_pan_time_difference = time_difference;
263 242
264 // Promote to pinch type 243 // Promote to pinch type
265 if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > 244 if (std::abs(gesture.average_distance - last_gesture_props.average_distance) >
266 pinch_threshold) { 245 pinch_threshold) {
267 type = TouchType::Pinch; 246 type = GestureType::Pinch;
268 cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance; 247 next_state.scale = gesture.average_distance / last_gesture_props.average_distance;
269 } 248 }
270 249
271 const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / 250 const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) /
272 (1 + (gesture.angle * last_gesture_props.angle))); 251 (1 + (gesture.angle * last_gesture_props.angle)));
273 // Promote to rotate type 252 // Promote to rotate type
274 if (std::abs(angle_between_two_lines) > angle_threshold) { 253 if (std::abs(angle_between_two_lines) > angle_threshold) {
275 type = TouchType::Rotate; 254 type = GestureType::Rotate;
276 cur_entry.scale = 0; 255 next_state.scale = 0;
277 cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; 256 next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
278 } 257 }
279} 258}
280 259
281void Controller_Gesture::EndPanEvent(GestureProperties& gesture, 260void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
282 GestureProperties& last_gesture_props, TouchType& type, 261 GestureProperties& last_gesture_props, GestureType& type,
283 f32 time_difference) { 262 f32 time_difference) {
284 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
285 const auto& last_entry = GetLastGestureEntry(); 263 const auto& last_entry = GetLastGestureEntry();
286 cur_entry.vel_x = 264 next_state.vel_x =
287 static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference); 265 static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
288 cur_entry.vel_y = 266 next_state.vel_y =
289 static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference); 267 static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference);
290 const f32 curr_vel = 268 const f32 curr_vel =
291 std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); 269 std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y));
292 270
293 // Set swipe event with parameters 271 // Set swipe event with parameters
294 if (curr_vel > swipe_threshold) { 272 if (curr_vel > swipe_threshold) {
@@ -297,105 +275,50 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
297 } 275 }
298 276
299 // End panning without swipe 277 // End panning without swipe
300 type = TouchType::Complete; 278 type = GestureType::Complete;
301 cur_entry.vel_x = 0; 279 next_state.vel_x = 0;
302 cur_entry.vel_y = 0; 280 next_state.vel_y = 0;
303 force_update = true; 281 force_update = true;
304} 282}
305 283
306void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, 284void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
307 GestureProperties& last_gesture_props, TouchType& type) { 285 GestureProperties& last_gesture_props, GestureType& type) {
308 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
309 const auto& last_entry = GetLastGestureEntry(); 286 const auto& last_entry = GetLastGestureEntry();
310 287
311 type = TouchType::Swipe; 288 type = GestureType::Swipe;
312 gesture = last_gesture_props; 289 gesture = last_gesture_props;
313 force_update = true; 290 force_update = true;
314 cur_entry.delta = last_entry.delta; 291 next_state.delta = last_entry.delta;
315 292
316 if (std::abs(cur_entry.delta.x) > std::abs(cur_entry.delta.y)) { 293 if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) {
317 if (cur_entry.delta.x > 0) { 294 if (next_state.delta.x > 0) {
318 cur_entry.direction = Direction::Right; 295 next_state.direction = GestureDirection::Right;
319 return; 296 return;
320 } 297 }
321 cur_entry.direction = Direction::Left; 298 next_state.direction = GestureDirection::Left;
322 return; 299 return;
323 } 300 }
324 if (cur_entry.delta.y > 0) { 301 if (next_state.delta.y > 0) {
325 cur_entry.direction = Direction::Down; 302 next_state.direction = GestureDirection::Down;
326 return; 303 return;
327 } 304 }
328 cur_entry.direction = Direction::Up; 305 next_state.direction = GestureDirection::Up;
329}
330
331void Controller_Gesture::OnLoadInputDevices() {
332 touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window");
333 touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp");
334 touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button");
335}
336
337std::optional<std::size_t> Controller_Gesture::GetUnusedFingerID() const {
338 // Dont assign any touch input to a point if disabled
339 if (!Settings::values.touchscreen.enabled) {
340 return std::nullopt;
341 }
342 std::size_t first_free_id = 0;
343 while (first_free_id < MAX_POINTS) {
344 if (!fingers[first_free_id].pressed) {
345 return first_free_id;
346 } else {
347 first_free_id++;
348 }
349 }
350 return std::nullopt;
351}
352
353Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() {
354 return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
355} 306}
356 307
357const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { 308const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const {
358 return shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; 309 return gesture_lifo.ReadCurrentEntry().state;
359}
360
361std::size_t Controller_Gesture::UpdateTouchInputEvent(
362 const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) {
363 const auto& [x, y, pressed] = touch_input;
364 if (finger_id > MAX_POINTS) {
365 LOG_ERROR(Service_HID, "Invalid finger id {}", finger_id);
366 return MAX_POINTS;
367 }
368 if (pressed) {
369 if (finger_id == MAX_POINTS) {
370 const auto first_free_id = GetUnusedFingerID();
371 if (!first_free_id) {
372 // Invalid finger id do nothing
373 return MAX_POINTS;
374 }
375 finger_id = first_free_id.value();
376 fingers[finger_id].pressed = true;
377 }
378 fingers[finger_id].pos = {x, y};
379 return finger_id;
380 }
381
382 if (finger_id != MAX_POINTS) {
383 fingers[finger_id].pressed = false;
384 }
385
386 return MAX_POINTS;
387} 310}
388 311
389Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { 312Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
390 GestureProperties gesture; 313 GestureProperties gesture;
391 std::array<Finger, MAX_POINTS> active_fingers; 314 std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
392 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), 315 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
393 [](const auto& finger) { return finger.pressed; }); 316 [](const auto& finger) { return finger.pressed; });
394 gesture.active_points = 317 gesture.active_points =
395 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); 318 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
396 319
397 for (size_t id = 0; id < gesture.active_points; ++id) { 320 for (size_t id = 0; id < gesture.active_points; ++id) {
398 const auto& [active_x, active_y] = active_fingers[id].pos; 321 const auto& [active_x, active_y] = active_fingers[id].position;
399 gesture.points[id] = { 322 gesture.points[id] = {
400 .x = static_cast<s32>(active_x * Layout::ScreenUndocked::Width), 323 .x = static_cast<s32>(active_x * Layout::ScreenUndocked::Width),
401 .y = static_cast<s32>(active_y * Layout::ScreenUndocked::Height), 324 .y = static_cast<s32>(active_y * Layout::ScreenUndocked::Height),
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 7e7ae6625..0936a3fa3 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -8,13 +8,14 @@
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/point.h" 10#include "common/point.h"
11#include "core/frontend/input.h" 11#include "core/hid/emulated_console.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 12#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h"
13 14
14namespace Service::HID { 15namespace Service::HID {
15class Controller_Gesture final : public ControllerBase { 16class Controller_Gesture final : public ControllerBase {
16public: 17public:
17 explicit Controller_Gesture(Core::System& system_); 18 explicit Controller_Gesture(Core::HID::HIDCore& hid_core_);
18 ~Controller_Gesture() override; 19 ~Controller_Gesture() override;
19 20
20 // Called when the controller is initialized 21 // Called when the controller is initialized
@@ -26,14 +27,12 @@ public:
26 // When the controller is requesting an update for the shared memory 27 // When the controller is requesting an update for the shared memory
27 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; 28 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override;
28 29
29 // Called when input devices should be loaded
30 void OnLoadInputDevices() override;
31
32private: 30private:
33 static constexpr size_t MAX_FINGERS = 16; 31 static constexpr size_t MAX_FINGERS = 16;
34 static constexpr size_t MAX_POINTS = 4; 32 static constexpr size_t MAX_POINTS = 4;
35 33
36 enum class TouchType : u32 { 34 // This is nn::hid::GestureType
35 enum class GestureType : u32 {
37 Idle, // Nothing touching the screen 36 Idle, // Nothing touching the screen
38 Complete, // Set at the end of a touch event 37 Complete, // Set at the end of a touch event
39 Cancel, // Set when the number of fingers change 38 Cancel, // Set when the number of fingers change
@@ -46,7 +45,8 @@ private:
46 Rotate, // All points rotating from the midpoint 45 Rotate, // All points rotating from the midpoint
47 }; 46 };
48 47
49 enum class Direction : u32 { 48 // This is nn::hid::GestureDirection
49 enum class GestureDirection : u32 {
50 None, 50 None,
51 Left, 51 Left,
52 Up, 52 Up,
@@ -54,51 +54,41 @@ private:
54 Down, 54 Down,
55 }; 55 };
56 56
57 struct Attribute { 57 // This is nn::hid::GestureAttribute
58 struct GestureAttribute {
58 union { 59 union {
59 u32_le raw{}; 60 u32 raw{};
60 61
61 BitField<4, 1, u32> is_new_touch; 62 BitField<4, 1, u32> is_new_touch;
62 BitField<8, 1, u32> is_double_tap; 63 BitField<8, 1, u32> is_double_tap;
63 }; 64 };
64 }; 65 };
65 static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); 66 static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
66 67
68 // This is nn::hid::GestureState
67 struct GestureState { 69 struct GestureState {
68 s64_le sampling_number; 70 s64 sampling_number;
69 s64_le sampling_number2; 71 s64 detection_count;
70 s64_le detection_count; 72 GestureType type;
71 TouchType type; 73 GestureDirection direction;
72 Direction direction; 74 Common::Point<s32> pos;
73 Common::Point<s32_le> pos; 75 Common::Point<s32> delta;
74 Common::Point<s32_le> delta;
75 f32 vel_x; 76 f32 vel_x;
76 f32 vel_y; 77 f32 vel_y;
77 Attribute attributes; 78 GestureAttribute attributes;
78 f32 scale; 79 f32 scale;
79 f32 rotation_angle; 80 f32 rotation_angle;
80 s32_le point_count; 81 s32 point_count;
81 std::array<Common::Point<s32_le>, 4> points; 82 std::array<Common::Point<s32>, 4> points;
82 };
83 static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size");
84
85 struct SharedMemory {
86 CommonHeader header;
87 std::array<GestureState, 17> gesture_states;
88 };
89 static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size");
90
91 struct Finger {
92 Common::Point<f32> pos{};
93 bool pressed{};
94 }; 83 };
84 static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
95 85
96 struct GestureProperties { 86 struct GestureProperties {
97 std::array<Common::Point<s32_le>, MAX_POINTS> points{}; 87 std::array<Common::Point<s32>, MAX_POINTS> points{};
98 std::size_t active_points{}; 88 std::size_t active_points{};
99 Common::Point<s32_le> mid_point{}; 89 Common::Point<s32> mid_point{};
100 s64_le detection_count{}; 90 s64 detection_count{};
101 u64_le delta_time{}; 91 u64 delta_time{};
102 f32 average_distance{}; 92 f32 average_distance{};
103 f32 angle{}; 93 f32 angle{};
104 }; 94 };
@@ -114,61 +104,48 @@ private:
114 f32 time_difference); 104 f32 time_difference);
115 105
116 // Initializes new gesture 106 // Initializes new gesture
117 void NewGesture(GestureProperties& gesture, TouchType& type, Attribute& attributes); 107 void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes);
118 108
119 // Updates existing gesture state 109 // Updates existing gesture state
120 void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference); 110 void UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference);
121 111
122 // Terminates exiting gesture 112 // Terminates exiting gesture
123 void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, 113 void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
124 TouchType& type, Attribute& attributes, f32 time_difference); 114 GestureType& type, GestureAttribute& attributes, f32 time_difference);
125 115
126 // Set current event to a tap event 116 // Set current event to a tap event
127 void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, 117 void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
128 TouchType& type, Attribute& attributes); 118 GestureType& type, GestureAttribute& attributes);
129 119
130 // Calculates and set the extra parameters related to a pan event 120 // Calculates and set the extra parameters related to a pan event
131 void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, 121 void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
132 TouchType& type, f32 time_difference); 122 GestureType& type, f32 time_difference);
133 123
134 // Terminates the pan event 124 // Terminates the pan event
135 void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, 125 void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
136 TouchType& type, f32 time_difference); 126 GestureType& type, f32 time_difference);
137 127
138 // Set current event to a swipe event 128 // Set current event to a swipe event
139 void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, 129 void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
140 TouchType& type); 130 GestureType& type);
141
142 // Returns an unused finger id, if there is no fingers available std::nullopt is returned.
143 [[nodiscard]] std::optional<size_t> GetUnusedFingerID() const;
144 131
145 // Retrieves the last gesture entry, as indicated by shared memory indices. 132 // Retrieves the last gesture entry, as indicated by shared memory indices.
146 [[nodiscard]] GestureState& GetLastGestureEntry();
147 [[nodiscard]] const GestureState& GetLastGestureEntry() const; 133 [[nodiscard]] const GestureState& GetLastGestureEntry() const;
148 134
149 /**
150 * If the touch is new it tries to assign a new finger id, if there is no fingers available no
151 * changes will be made. Updates the coordinates if the finger id it's already set. If the touch
152 * ends delays the output by one frame to set the end_touch flag before finally freeing the
153 * finger id
154 */
155 size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input,
156 size_t finger_id);
157
158 // Returns the average distance, angle and middle point of the active fingers 135 // Returns the average distance, angle and middle point of the active fingers
159 GestureProperties GetGestureProperties(); 136 GestureProperties GetGestureProperties();
160 137
161 SharedMemory shared_memory{}; 138 // This is nn::hid::detail::GestureLifo
162 std::unique_ptr<Input::TouchDevice> touch_mouse_device; 139 Lifo<GestureState, hid_entry_count> gesture_lifo{};
163 std::unique_ptr<Input::TouchDevice> touch_udp_device; 140 static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
164 std::unique_ptr<Input::TouchDevice> touch_btn_device; 141 GestureState next_state{};
165 std::array<size_t, MAX_FINGERS> mouse_finger_id{}; 142
166 std::array<size_t, MAX_FINGERS> keyboard_finger_id{}; 143 Core::HID::EmulatedConsole* console;
167 std::array<size_t, MAX_FINGERS> udp_finger_id{}; 144
168 std::array<Finger, MAX_POINTS> fingers{}; 145 std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
169 GestureProperties last_gesture{}; 146 GestureProperties last_gesture{};
170 s64_le last_update_timestamp{}; 147 s64 last_update_timestamp{};
171 s64_le last_tap_timestamp{}; 148 s64 last_tap_timestamp{};
172 f32 last_pan_time_difference{}; 149 f32 last_pan_time_difference{};
173 bool force_update{false}; 150 bool force_update{false};
174 bool enable_press_and_tap{false}; 151 bool enable_press_and_tap{false};
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index c6c620008..9588a6910 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -6,13 +6,18 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/settings.h" 7#include "common/settings.h"
8#include "core/core_timing.h" 8#include "core/core_timing.h"
9#include "core/hid/emulated_devices.h"
10#include "core/hid/hid_core.h"
9#include "core/hle/service/hid/controllers/keyboard.h" 11#include "core/hle/service/hid/controllers/keyboard.h"
10 12
11namespace Service::HID { 13namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; 14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
13constexpr u8 KEYS_PER_BYTE = 8;
14 15
15Controller_Keyboard::Controller_Keyboard(Core::System& system_) : ControllerBase{system_} {} 16Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_)
17 : ControllerBase{hid_core_} {
18 emulated_devices = hid_core.GetEmulatedDevices();
19}
20
16Controller_Keyboard::~Controller_Keyboard() = default; 21Controller_Keyboard::~Controller_Keyboard() = default;
17 22
18void Controller_Keyboard::OnInit() {} 23void Controller_Keyboard::OnInit() {}
@@ -21,51 +26,27 @@ void Controller_Keyboard::OnRelease() {}
21 26
22void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 27void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
23 std::size_t size) { 28 std::size_t size) {
24 shared_memory.header.timestamp = core_timing.GetCPUTicks();
25 shared_memory.header.total_entry_count = 17;
26
27 if (!IsControllerActivated()) { 29 if (!IsControllerActivated()) {
28 shared_memory.header.entry_count = 0; 30 keyboard_lifo.buffer_count = 0;
29 shared_memory.header.last_entry_index = 0; 31 keyboard_lifo.buffer_tail = 0;
32 std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
30 return; 33 return;
31 } 34 }
32 shared_memory.header.entry_count = 16;
33
34 const auto& last_entry = shared_memory.pad_states[shared_memory.header.last_entry_index];
35 shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17;
36 auto& cur_entry = shared_memory.pad_states[shared_memory.header.last_entry_index];
37 35
38 cur_entry.sampling_number = last_entry.sampling_number + 1; 36 const auto& last_entry = keyboard_lifo.ReadCurrentEntry().state;
39 cur_entry.sampling_number2 = cur_entry.sampling_number; 37 next_state.sampling_number = last_entry.sampling_number + 1;
40 38
41 cur_entry.key.fill(0);
42 if (Settings::values.keyboard_enabled) { 39 if (Settings::values.keyboard_enabled) {
43 for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { 40 const auto& keyboard_state = emulated_devices->GetKeyboard();
44 auto& entry = cur_entry.key[i / KEYS_PER_BYTE]; 41 const auto& keyboard_modifier_state = emulated_devices->GetKeyboardModifier();
45 entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
46 }
47 42
48 using namespace Settings::NativeKeyboard; 43 next_state.key = keyboard_state;
49 44 next_state.modifier = keyboard_modifier_state;
50 // TODO: Assign the correct key to all modifiers 45 next_state.attribute.is_connected.Assign(1);
51 cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus());
52 cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus());
53 cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus());
54 cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus());
55 cur_entry.modifier.gui.Assign(0);
56 cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus());
57 cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus());
58 cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus());
59 cur_entry.modifier.katakana.Assign(0);
60 cur_entry.modifier.hiragana.Assign(0);
61 } 46 }
62 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
63}
64 47
65void Controller_Keyboard::OnLoadInputDevices() { 48 keyboard_lifo.WriteNextEntry(next_state);
66 std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(), 49 std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
67 keyboard_keys.begin(), Input::CreateDevice<Input::ButtonDevice>);
68 std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(),
69 keyboard_mods.begin(), Input::CreateDevice<Input::ButtonDevice>);
70} 50}
51
71} // namespace Service::HID 52} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 172a80e9c..cf62d3896 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -8,15 +8,20 @@
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/settings.h"
12#include "common/swap.h" 11#include "common/swap.h"
13#include "core/frontend/input.h"
14#include "core/hle/service/hid/controllers/controller_base.h" 12#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h"
14
15namespace Core::HID {
16class EmulatedDevices;
17struct KeyboardModifier;
18struct KeyboardKey;
19} // namespace Core::HID
15 20
16namespace Service::HID { 21namespace Service::HID {
17class Controller_Keyboard final : public ControllerBase { 22class Controller_Keyboard final : public ControllerBase {
18public: 23public:
19 explicit Controller_Keyboard(Core::System& system_); 24 explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_);
20 ~Controller_Keyboard() override; 25 ~Controller_Keyboard() override;
21 26
22 // Called when the controller is initialized 27 // Called when the controller is initialized
@@ -28,47 +33,21 @@ public:
28 // When the controller is requesting an update for the shared memory 33 // When the controller is requesting an update for the shared memory
29 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 34 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
30 35
31 // Called when input devices should be loaded
32 void OnLoadInputDevices() override;
33
34private: 36private:
35 struct Modifiers { 37 // This is nn::hid::detail::KeyboardState
36 union {
37 u32_le raw{};
38 BitField<0, 1, u32> control;
39 BitField<1, 1, u32> shift;
40 BitField<2, 1, u32> left_alt;
41 BitField<3, 1, u32> right_alt;
42 BitField<4, 1, u32> gui;
43 BitField<8, 1, u32> caps_lock;
44 BitField<9, 1, u32> scroll_lock;
45 BitField<10, 1, u32> num_lock;
46 BitField<11, 1, u32> katakana;
47 BitField<12, 1, u32> hiragana;
48 };
49 };
50 static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size");
51
52 struct KeyboardState { 38 struct KeyboardState {
53 s64_le sampling_number; 39 s64 sampling_number;
54 s64_le sampling_number2; 40 Core::HID::KeyboardModifier modifier;
55 41 Core::HID::KeyboardAttribute attribute;
56 Modifiers modifier; 42 Core::HID::KeyboardKey key;
57 std::array<u8, 32> key;
58 }; 43 };
59 static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size"); 44 static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
60 45
61 struct SharedMemory { 46 // This is nn::hid::detail::KeyboardLifo
62 CommonHeader header; 47 Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
63 std::array<KeyboardState, 17> pad_states; 48 static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
64 INSERT_PADDING_BYTES(0x28); 49 KeyboardState next_state{};
65 };
66 static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size");
67 SharedMemory shared_memory{};
68 50
69 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeKeyboard::NumKeyboardKeys> 51 Core::HID::EmulatedDevices* emulated_devices;
70 keyboard_keys;
71 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeKeyboard::NumKeyboardMods>
72 keyboard_mods;
73}; 52};
74} // namespace Service::HID 53} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 544a71948..ba79888ae 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -6,12 +6,17 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/frontend/emu_window.h" 8#include "core/frontend/emu_window.h"
9#include "core/hid/emulated_devices.h"
10#include "core/hid/hid_core.h"
9#include "core/hle/service/hid/controllers/mouse.h" 11#include "core/hle/service/hid/controllers/mouse.h"
10 12
11namespace Service::HID { 13namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; 14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
13 15
14Controller_Mouse::Controller_Mouse(Core::System& system_) : ControllerBase{system_} {} 16Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {
17 emulated_devices = hid_core.GetEmulatedDevices();
18}
19
15Controller_Mouse::~Controller_Mouse() = default; 20Controller_Mouse::~Controller_Mouse() = default;
16 21
17void Controller_Mouse::OnInit() {} 22void Controller_Mouse::OnInit() {}
@@ -19,50 +24,35 @@ void Controller_Mouse::OnRelease() {}
19 24
20void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 25void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
21 std::size_t size) { 26 std::size_t size) {
22 shared_memory.header.timestamp = core_timing.GetCPUTicks();
23 shared_memory.header.total_entry_count = 17;
24
25 if (!IsControllerActivated()) { 27 if (!IsControllerActivated()) {
26 shared_memory.header.entry_count = 0; 28 mouse_lifo.buffer_count = 0;
27 shared_memory.header.last_entry_index = 0; 29 mouse_lifo.buffer_tail = 0;
30 std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
28 return; 31 return;
29 } 32 }
30 shared_memory.header.entry_count = 16;
31 33
32 auto& last_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index]; 34 const auto& last_entry = mouse_lifo.ReadCurrentEntry().state;
33 shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; 35 next_state.sampling_number = last_entry.sampling_number + 1;
34 auto& cur_entry = shared_memory.mouse_states[shared_memory.header.last_entry_index];
35 36
36 cur_entry.sampling_number = last_entry.sampling_number + 1; 37 next_state.attribute.raw = 0;
37 cur_entry.sampling_number2 = cur_entry.sampling_number;
38
39 cur_entry.attribute.raw = 0;
40 if (Settings::values.mouse_enabled) { 38 if (Settings::values.mouse_enabled) {
41 const auto [px, py, sx, sy] = mouse_device->GetStatus(); 39 const auto& mouse_button_state = emulated_devices->GetMouseButtons();
42 const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width); 40 const auto& mouse_position_state = emulated_devices->GetMousePosition();
43 const auto y = static_cast<s32>(py * Layout::ScreenUndocked::Height); 41 const auto& mouse_wheel_state = emulated_devices->GetMouseWheel();
44 cur_entry.x = x; 42 next_state.attribute.is_connected.Assign(1);
45 cur_entry.y = y; 43 next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width);
46 cur_entry.delta_x = x - last_entry.x; 44 next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height);
47 cur_entry.delta_y = y - last_entry.y; 45 next_state.delta_x = next_state.x - last_entry.x;
48 cur_entry.mouse_wheel_x = sx; 46 next_state.delta_y = next_state.y - last_entry.y;
49 cur_entry.mouse_wheel_y = sy; 47 next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x;
50 cur_entry.attribute.is_connected.Assign(1); 48 next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y;
51 49
52 using namespace Settings::NativeMouseButton; 50 last_mouse_wheel_state = mouse_wheel_state;
53 cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus()); 51 next_state.button = mouse_button_state;
54 cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus());
55 cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus());
56 cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus());
57 cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus());
58 } 52 }
59 53
60 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 54 mouse_lifo.WriteNextEntry(next_state);
55 std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
61} 56}
62 57
63void Controller_Mouse::OnLoadInputDevices() {
64 mouse_device = Input::CreateDevice<Input::MouseDevice>(Settings::values.mouse_device);
65 std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(),
66 mouse_button_devices.begin(), Input::CreateDevice<Input::ButtonDevice>);
67}
68} // namespace Service::HID 58} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 3d391a798..7559fc78d 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -7,15 +7,20 @@
7#include <array> 7#include <array>
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/settings.h"
11#include "common/swap.h" 10#include "common/swap.h"
12#include "core/frontend/input.h"
13#include "core/hle/service/hid/controllers/controller_base.h" 11#include "core/hle/service/hid/controllers/controller_base.h"
12#include "core/hle/service/hid/ring_lifo.h"
13
14namespace Core::HID {
15class EmulatedDevices;
16struct MouseState;
17struct AnalogStickState;
18} // namespace Core::HID
14 19
15namespace Service::HID { 20namespace Service::HID {
16class Controller_Mouse final : public ControllerBase { 21class Controller_Mouse final : public ControllerBase {
17public: 22public:
18 explicit Controller_Mouse(Core::System& system_); 23 explicit Controller_Mouse(Core::HID::HIDCore& hid_core_);
19 ~Controller_Mouse() override; 24 ~Controller_Mouse() override;
20 25
21 // Called when the controller is initialized 26 // Called when the controller is initialized
@@ -27,53 +32,13 @@ public:
27 // When the controller is requesting an update for the shared memory 32 // When the controller is requesting an update for the shared memory
28 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 33 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
29 34
30 // Called when input devices should be loaded
31 void OnLoadInputDevices() override;
32
33private: 35private:
34 struct Buttons { 36 // This is nn::hid::detail::MouseLifo
35 union { 37 Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
36 u32_le raw{}; 38 static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
37 BitField<0, 1, u32> left; 39 Core::HID::MouseState next_state{};
38 BitField<1, 1, u32> right;
39 BitField<2, 1, u32> middle;
40 BitField<3, 1, u32> forward;
41 BitField<4, 1, u32> back;
42 };
43 };
44 static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size");
45
46 struct Attributes {
47 union {
48 u32_le raw{};
49 BitField<0, 1, u32> transferable;
50 BitField<1, 1, u32> is_connected;
51 };
52 };
53 static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
54
55 struct MouseState {
56 s64_le sampling_number;
57 s64_le sampling_number2;
58 s32_le x;
59 s32_le y;
60 s32_le delta_x;
61 s32_le delta_y;
62 s32_le mouse_wheel_x;
63 s32_le mouse_wheel_y;
64 Buttons button;
65 Attributes attribute;
66 };
67 static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size");
68
69 struct SharedMemory {
70 CommonHeader header;
71 std::array<MouseState, 17> mouse_states;
72 };
73 SharedMemory shared_memory{};
74 40
75 std::unique_ptr<Input::MouseDevice> mouse_device; 41 Core::HID::AnalogStickState last_mouse_wheel_state;
76 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeMouseButton::NumMouseButtons> 42 Core::HID::EmulatedDevices* emulated_devices;
77 mouse_button_devices;
78}; 43};
79} // namespace Service::HID 44} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 196876810..dd4d954aa 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -10,9 +10,9 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/settings.h" 12#include "common/settings.h"
13#include "core/core.h"
14#include "core/core_timing.h" 13#include "core/core_timing.h"
15#include "core/frontend/input.h" 14#include "core/hid/emulated_controller.h"
15#include "core/hid/hid_core.h"
16#include "core/hle/kernel/k_event.h" 16#include "core/hle/kernel/k_event.h"
17#include "core/hle/kernel/k_readable_event.h" 17#include "core/hle/kernel/k_readable_event.h"
18#include "core/hle/kernel/k_writable_event.h" 18#include "core/hle/kernel/k_writable_event.h"
@@ -20,120 +20,26 @@
20#include "core/hle/service/kernel_helpers.h" 20#include "core/hle/service/kernel_helpers.h"
21 21
22namespace Service::HID { 22namespace Service::HID {
23constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
24constexpr s32 HID_TRIGGER_MAX = 0x7fff;
25[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
26constexpr std::size_t NPAD_OFFSET = 0x9A00; 23constexpr std::size_t NPAD_OFFSET = 0x9A00;
27constexpr u32 BATTERY_FULL = 2; 24constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
28constexpr u32 MAX_NPAD_ID = 7; 25 Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
29constexpr std::size_t HANDHELD_INDEX = 8; 26 Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
30constexpr std::array<u32, 10> npad_id_list{ 27 Core::HID::NpadIdType::Player7, Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other,
31 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, 28 Core::HID::NpadIdType::Handheld,
32}; 29};
33 30
34enum class JoystickId : std::size_t { 31bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
35 Joystick_Left,
36 Joystick_Right,
37};
38
39Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
40 Settings::ControllerType type) {
41 switch (type) {
42 case Settings::ControllerType::ProController:
43 return NPadControllerType::ProController;
44 case Settings::ControllerType::DualJoyconDetached:
45 return NPadControllerType::JoyDual;
46 case Settings::ControllerType::LeftJoycon:
47 return NPadControllerType::JoyLeft;
48 case Settings::ControllerType::RightJoycon:
49 return NPadControllerType::JoyRight;
50 case Settings::ControllerType::Handheld:
51 return NPadControllerType::Handheld;
52 case Settings::ControllerType::GameCube:
53 return NPadControllerType::GameCube;
54 default:
55 UNREACHABLE();
56 return NPadControllerType::ProController;
57 }
58}
59
60Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
61 Controller_NPad::NPadControllerType type) {
62 switch (type) {
63 case NPadControllerType::ProController:
64 return Settings::ControllerType::ProController;
65 case NPadControllerType::JoyDual:
66 return Settings::ControllerType::DualJoyconDetached;
67 case NPadControllerType::JoyLeft:
68 return Settings::ControllerType::LeftJoycon;
69 case NPadControllerType::JoyRight:
70 return Settings::ControllerType::RightJoycon;
71 case NPadControllerType::Handheld:
72 return Settings::ControllerType::Handheld;
73 case NPadControllerType::GameCube:
74 return Settings::ControllerType::GameCube;
75 default:
76 UNREACHABLE();
77 return Settings::ControllerType::ProController;
78 }
79}
80
81std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
82 switch (npad_id) { 32 switch (npad_id) {
83 case 0: 33 case Core::HID::NpadIdType::Player1:
84 case 1: 34 case Core::HID::NpadIdType::Player2:
85 case 2: 35 case Core::HID::NpadIdType::Player3:
86 case 3: 36 case Core::HID::NpadIdType::Player4:
87 case 4: 37 case Core::HID::NpadIdType::Player5:
88 case 5: 38 case Core::HID::NpadIdType::Player6:
89 case 6: 39 case Core::HID::NpadIdType::Player7:
90 case 7: 40 case Core::HID::NpadIdType::Player8:
91 return npad_id; 41 case Core::HID::NpadIdType::Other:
92 case HANDHELD_INDEX: 42 case Core::HID::NpadIdType::Handheld:
93 case NPAD_HANDHELD:
94 return HANDHELD_INDEX;
95 case 9:
96 case NPAD_UNKNOWN:
97 return 9;
98 default:
99 UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id);
100 return 0;
101 }
102}
103
104u32 Controller_NPad::IndexToNPad(std::size_t index) {
105 switch (index) {
106 case 0:
107 case 1:
108 case 2:
109 case 3:
110 case 4:
111 case 5:
112 case 6:
113 case 7:
114 return static_cast<u32>(index);
115 case HANDHELD_INDEX:
116 return NPAD_HANDHELD;
117 case 9:
118 return NPAD_UNKNOWN;
119 default:
120 UNIMPLEMENTED_MSG("Unknown npad index {}", index);
121 return 0;
122 }
123}
124
125bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
126 switch (npad_id) {
127 case 0:
128 case 1:
129 case 2:
130 case 3:
131 case 4:
132 case 5:
133 case 6:
134 case 7:
135 case NPAD_UNKNOWN:
136 case NPAD_HANDHELD:
137 return true; 43 return true;
138 default: 44 default:
139 LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id); 45 LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
@@ -141,131 +47,215 @@ bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
141 } 47 }
142} 48}
143 49
144bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) { 50bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
145 return IsNpadIdValid(device_handle.npad_id) && 51 return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
146 device_handle.npad_type < NpadType::MaxNpadType && 52 device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
147 device_handle.device_index < DeviceIndex::MaxDeviceIndex; 53 device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
54}
55
56bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) {
57 return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
58 device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
59 device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
148} 60}
149 61
150Controller_NPad::Controller_NPad(Core::System& system_, 62Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
151 KernelHelpers::ServiceContext& service_context_) 63 KernelHelpers::ServiceContext& service_context_)
152 : ControllerBase{system_}, service_context{service_context_} { 64 : ControllerBase{hid_core_}, service_context{service_context_} {
153 latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE}); 65 for (std::size_t i = 0; i < controller_data.size(); ++i) {
66 auto& controller = controller_data[i];
67 controller.device = hid_core.GetEmulatedControllerByIndex(i);
68 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
69 DEFAULT_VIBRATION_VALUE;
70 controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
71 DEFAULT_VIBRATION_VALUE;
72 Core::HID::ControllerUpdateCallback engine_callback{
73 .on_change = [this,
74 i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
75 .is_npad_service = true,
76 };
77 controller.callback_key = controller.device->SetCallback(engine_callback);
78 }
154} 79}
155 80
156Controller_NPad::~Controller_NPad() { 81Controller_NPad::~Controller_NPad() {
82 for (std::size_t i = 0; i < controller_data.size(); ++i) {
83 auto& controller = controller_data[i];
84 controller.device->DeleteCallback(controller.callback_key);
85 }
157 OnRelease(); 86 OnRelease();
158} 87}
159 88
160void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { 89void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
161 const auto controller_type = connected_controllers[controller_idx].type; 90 std::size_t controller_idx) {
162 auto& controller = shared_memory_entries[controller_idx]; 91 if (type == Core::HID::ControllerTriggerType::All) {
163 if (controller_type == NPadControllerType::None) { 92 ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
164 styleset_changed_events[controller_idx]->GetWritableEvent().Signal(); 93 ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
165 return; 94 return;
166 } 95 }
167 controller.style_set.raw = 0; // Zero out 96 if (controller_idx >= controller_data.size()) {
168 controller.device_type.raw = 0; 97 return;
169 controller.system_properties.raw = 0; 98 }
99
100 auto& controller = controller_data[controller_idx];
101 const auto is_connected = controller.device->IsConnected();
102 const auto npad_type = controller.device->GetNpadStyleIndex();
103 const auto npad_id = controller.device->GetNpadIdType();
104 switch (type) {
105 case Core::HID::ControllerTriggerType::Connected:
106 case Core::HID::ControllerTriggerType::Disconnected:
107 if (is_connected == controller.is_connected) {
108 return;
109 }
110 UpdateControllerAt(npad_type, npad_id, is_connected);
111 break;
112 case Core::HID::ControllerTriggerType::Battery: {
113 if (!controller.is_connected) {
114 return;
115 }
116 auto& shared_memory = controller.shared_memory_entry;
117 const auto& battery_level = controller.device->GetBattery();
118 shared_memory.battery_level_dual = battery_level.dual.battery_level;
119 shared_memory.battery_level_left = battery_level.left.battery_level;
120 shared_memory.battery_level_right = battery_level.right.battery_level;
121 break;
122 }
123 default:
124 break;
125 }
126}
127
128void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
129 LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
130 auto& controller = GetControllerFromNpadIdType(npad_id);
131 const auto controller_type = controller.device->GetNpadStyleIndex();
132 auto& shared_memory = controller.shared_memory_entry;
133 if (controller_type == Core::HID::NpadStyleIndex::None) {
134 controller.styleset_changed_event->GetWritableEvent().Signal();
135 return;
136 }
137 shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None;
138 shared_memory.device_type.raw = 0;
139 shared_memory.system_properties.raw = 0;
170 switch (controller_type) { 140 switch (controller_type) {
171 case NPadControllerType::None: 141 case Core::HID::NpadStyleIndex::None:
172 UNREACHABLE(); 142 UNREACHABLE();
173 break; 143 break;
174 case NPadControllerType::ProController: 144 case Core::HID::NpadStyleIndex::ProController:
175 controller.style_set.fullkey.Assign(1); 145 shared_memory.style_tag.fullkey.Assign(1);
176 controller.device_type.fullkey.Assign(1); 146 shared_memory.device_type.fullkey.Assign(1);
177 controller.system_properties.is_vertical.Assign(1); 147 shared_memory.system_properties.is_vertical.Assign(1);
178 controller.system_properties.use_plus.Assign(1); 148 shared_memory.system_properties.use_plus.Assign(1);
179 controller.system_properties.use_minus.Assign(1); 149 shared_memory.system_properties.use_minus.Assign(1);
180 controller.assignment_mode = NpadAssignments::Single; 150 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
181 controller.footer_type = AppletFooterUiType::SwitchProController; 151 shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
152 break;
153 case Core::HID::NpadStyleIndex::Handheld:
154 shared_memory.style_tag.handheld.Assign(1);
155 shared_memory.device_type.handheld_left.Assign(1);
156 shared_memory.device_type.handheld_right.Assign(1);
157 shared_memory.system_properties.is_vertical.Assign(1);
158 shared_memory.system_properties.use_plus.Assign(1);
159 shared_memory.system_properties.use_minus.Assign(1);
160 shared_memory.system_properties.use_directional_buttons.Assign(1);
161 shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
162 shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
163 break;
164 case Core::HID::NpadStyleIndex::JoyconDual:
165 shared_memory.style_tag.joycon_dual.Assign(1);
166 shared_memory.device_type.joycon_left.Assign(1);
167 shared_memory.device_type.joycon_right.Assign(1);
168 shared_memory.system_properties.is_vertical.Assign(1);
169 shared_memory.system_properties.use_plus.Assign(1);
170 shared_memory.system_properties.use_minus.Assign(1);
171 shared_memory.system_properties.use_directional_buttons.Assign(1);
172 shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
173 shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
182 break; 174 break;
183 case NPadControllerType::Handheld: 175 case Core::HID::NpadStyleIndex::JoyconLeft:
184 controller.style_set.handheld.Assign(1); 176 shared_memory.style_tag.joycon_left.Assign(1);
185 controller.device_type.handheld_left.Assign(1); 177 shared_memory.device_type.joycon_left.Assign(1);
186 controller.device_type.handheld_right.Assign(1); 178 shared_memory.system_properties.is_horizontal.Assign(1);
187 controller.system_properties.is_vertical.Assign(1); 179 shared_memory.system_properties.use_minus.Assign(1);
188 controller.system_properties.use_plus.Assign(1); 180 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
189 controller.system_properties.use_minus.Assign(1); 181 shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
190 controller.assignment_mode = NpadAssignments::Dual;
191 controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
192 break; 182 break;
193 case NPadControllerType::JoyDual: 183 case Core::HID::NpadStyleIndex::JoyconRight:
194 controller.style_set.joycon_dual.Assign(1); 184 shared_memory.style_tag.joycon_right.Assign(1);
195 controller.device_type.joycon_left.Assign(1); 185 shared_memory.device_type.joycon_right.Assign(1);
196 controller.device_type.joycon_right.Assign(1); 186 shared_memory.system_properties.is_horizontal.Assign(1);
197 controller.system_properties.is_vertical.Assign(1); 187 shared_memory.system_properties.use_plus.Assign(1);
198 controller.system_properties.use_plus.Assign(1); 188 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
199 controller.system_properties.use_minus.Assign(1); 189 shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
200 controller.assignment_mode = NpadAssignments::Dual;
201 controller.footer_type = AppletFooterUiType::JoyDual;
202 break; 190 break;
203 case NPadControllerType::JoyLeft: 191 case Core::HID::NpadStyleIndex::GameCube:
204 controller.style_set.joycon_left.Assign(1); 192 shared_memory.style_tag.gamecube.Assign(1);
205 controller.device_type.joycon_left.Assign(1); 193 shared_memory.device_type.fullkey.Assign(1);
206 controller.system_properties.is_horizontal.Assign(1); 194 shared_memory.system_properties.is_vertical.Assign(1);
207 controller.system_properties.use_minus.Assign(1); 195 shared_memory.system_properties.use_plus.Assign(1);
208 controller.assignment_mode = NpadAssignments::Single;
209 controller.footer_type = AppletFooterUiType::JoyLeftHorizontal;
210 break; 196 break;
211 case NPadControllerType::JoyRight: 197 case Core::HID::NpadStyleIndex::Pokeball:
212 controller.style_set.joycon_right.Assign(1); 198 shared_memory.style_tag.palma.Assign(1);
213 controller.device_type.joycon_right.Assign(1); 199 shared_memory.device_type.palma.Assign(1);
214 controller.system_properties.is_horizontal.Assign(1); 200 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
215 controller.system_properties.use_plus.Assign(1);
216 controller.assignment_mode = NpadAssignments::Single;
217 controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
218 break; 201 break;
219 case NPadControllerType::GameCube: 202 case Core::HID::NpadStyleIndex::NES:
220 controller.style_set.gamecube.Assign(1); 203 shared_memory.style_tag.lark.Assign(1);
221 // The GC Controller behaves like a wired Pro Controller 204 shared_memory.device_type.fullkey.Assign(1);
222 controller.device_type.fullkey.Assign(1);
223 controller.system_properties.is_vertical.Assign(1);
224 controller.system_properties.use_plus.Assign(1);
225 break; 205 break;
226 case NPadControllerType::Pokeball: 206 case Core::HID::NpadStyleIndex::SNES:
227 controller.style_set.palma.Assign(1); 207 shared_memory.style_tag.lucia.Assign(1);
228 controller.device_type.palma.Assign(1); 208 shared_memory.device_type.fullkey.Assign(1);
229 controller.assignment_mode = NpadAssignments::Single; 209 shared_memory.applet_footer.type = AppletFooterUiType::Lucia;
210 break;
211 case Core::HID::NpadStyleIndex::N64:
212 shared_memory.style_tag.lagoon.Assign(1);
213 shared_memory.device_type.fullkey.Assign(1);
214 shared_memory.applet_footer.type = AppletFooterUiType::Lagon;
215 break;
216 case Core::HID::NpadStyleIndex::SegaGenesis:
217 shared_memory.style_tag.lager.Assign(1);
218 shared_memory.device_type.fullkey.Assign(1);
219 break;
220 default:
230 break; 221 break;
231 } 222 }
232 223
233 controller.fullkey_color.attribute = ColorAttributes::Ok; 224 const auto& body_colors = controller.device->GetColors();
234 controller.fullkey_color.fullkey.body = 0;
235 controller.fullkey_color.fullkey.button = 0;
236 225
237 controller.joycon_color.attribute = ColorAttributes::Ok; 226 shared_memory.fullkey_color.attribute = ColorAttribute::Ok;
238 controller.joycon_color.left.body = 227 shared_memory.fullkey_color.fullkey = body_colors.fullkey;
239 Settings::values.players.GetValue()[controller_idx].body_color_left;
240 controller.joycon_color.left.button =
241 Settings::values.players.GetValue()[controller_idx].button_color_left;
242 controller.joycon_color.right.body =
243 Settings::values.players.GetValue()[controller_idx].body_color_right;
244 controller.joycon_color.right.button =
245 Settings::values.players.GetValue()[controller_idx].button_color_right;
246 228
247 // TODO: Investigate when we should report all batery types 229 shared_memory.joycon_color.attribute = ColorAttribute::Ok;
248 controller.battery_level_dual = BATTERY_FULL; 230 shared_memory.joycon_color.left = body_colors.left;
249 controller.battery_level_left = BATTERY_FULL; 231 shared_memory.joycon_color.right = body_colors.right;
250 controller.battery_level_right = BATTERY_FULL;
251 232
252 SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); 233 // TODO: Investigate when we should report all batery types
234 const auto& battery_level = controller.device->GetBattery();
235 shared_memory.battery_level_dual = battery_level.dual.battery_level;
236 shared_memory.battery_level_left = battery_level.left.battery_level;
237 shared_memory.battery_level_right = battery_level.right.battery_level;
238
239 controller.is_connected = true;
240 controller.device->Connect();
241 SignalStyleSetChangedEvent(npad_id);
242 WriteEmptyEntry(controller.shared_memory_entry);
253} 243}
254 244
255void Controller_NPad::OnInit() { 245void Controller_NPad::OnInit() {
256 for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
257 styleset_changed_events[i] =
258 service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
259 }
260
261 if (!IsControllerActivated()) { 246 if (!IsControllerActivated()) {
262 return; 247 return;
263 } 248 }
264 249
265 OnLoadInputDevices(); 250 for (std::size_t i = 0; i < controller_data.size(); ++i) {
251 auto& controller = controller_data[i];
252 controller.styleset_changed_event =
253 service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
254 }
266 255
267 if (style.raw == 0) { 256 if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) {
268 // We want to support all controllers 257 // We want to support all controllers
258 Core::HID::NpadStyleTag style{};
269 style.handheld.Assign(1); 259 style.handheld.Assign(1);
270 style.joycon_left.Assign(1); 260 style.joycon_left.Assign(1);
271 style.joycon_right.Assign(1); 261 style.joycon_right.Assign(1);
@@ -273,173 +263,120 @@ void Controller_NPad::OnInit() {
273 style.fullkey.Assign(1); 263 style.fullkey.Assign(1);
274 style.gamecube.Assign(1); 264 style.gamecube.Assign(1);
275 style.palma.Assign(1); 265 style.palma.Assign(1);
266 hid_core.SetSupportedStyleTag(style);
276 } 267 }
277 268
278 std::transform(Settings::values.players.GetValue().begin(), 269 supported_npad_id_types.resize(npad_id_list.size());
279 Settings::values.players.GetValue().end(), connected_controllers.begin(), 270 std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
280 [](const Settings::PlayerInput& player) { 271 npad_id_list.size() * sizeof(Core::HID::NpadIdType));
281 return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), 272
282 player.connected}; 273 // Prefill controller buffers
283 }); 274 for (auto& controller : controller_data) {
284 275 auto& npad = controller.shared_memory_entry;
285 // Connect the Player 1 or Handheld controller if none are connected. 276 npad.fullkey_color = {
286 if (std::none_of(connected_controllers.begin(), connected_controllers.end(), 277 .attribute = ColorAttribute::NoController,
287 [](const ControllerHolder& controller) { return controller.is_connected; })) { 278 .fullkey = {},
288 const auto controller = 279 };
289 MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type); 280 npad.joycon_color = {
290 if (controller == NPadControllerType::Handheld) { 281 .attribute = ColorAttribute::NoController,
291 Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; 282 .left = {},
292 connected_controllers[HANDHELD_INDEX] = {controller, true}; 283 .right = {},
293 } else { 284 };
294 Settings::values.players.GetValue()[0].connected = true; 285 // HW seems to initialize the first 19 entries
295 connected_controllers[0] = {controller, true}; 286 for (std::size_t i = 0; i < 19; ++i) {
287 WriteEmptyEntry(npad);
296 } 288 }
297 } 289 }
298 290
299 // Account for handheld 291 // Connect controllers
300 if (connected_controllers[HANDHELD_INDEX].is_connected) { 292 for (auto& controller : controller_data) {
301 connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; 293 const auto& device = controller.device;
294 if (device->IsConnected()) {
295 AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType());
296 }
302 } 297 }
298}
303 299
304 supported_npad_id_types.resize(npad_id_list.size()); 300void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) {
305 std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), 301 NPadGenericState dummy_pad_state{};
306 npad_id_list.size() * sizeof(u32)); 302 NpadGcTriggerState dummy_gc_state{};
303 dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
304 npad.fullkey_lifo.WriteNextEntry(dummy_pad_state);
305 dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1;
306 npad.handheld_lifo.WriteNextEntry(dummy_pad_state);
307 dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
308 npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state);
309 dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
310 npad.joy_left_lifo.WriteNextEntry(dummy_pad_state);
311 dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
312 npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
313 dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1;
314 npad.palma_lifo.WriteNextEntry(dummy_pad_state);
315 dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
316 npad.system_ext_lifo.WriteNextEntry(dummy_pad_state);
317 dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
318 npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
319}
307 320
308 for (std::size_t i = 0; i < connected_controllers.size(); ++i) { 321void Controller_NPad::OnRelease() {
309 const auto& controller = connected_controllers[i]; 322 for (std::size_t i = 0; i < controller_data.size(); ++i) {
310 if (controller.is_connected) { 323 auto& controller = controller_data[i];
311 AddNewControllerAt(controller.type, i); 324 service_context.CloseEvent(controller.styleset_changed_event);
325 for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
326 VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {});
312 } 327 }
313 } 328 }
314} 329}
315 330
316void Controller_NPad::OnLoadInputDevices() { 331void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
317 const auto& players = Settings::values.players.GetValue();
318
319 std::lock_guard lock{mutex}; 332 std::lock_guard lock{mutex};
320 for (std::size_t i = 0; i < players.size(); ++i) { 333 auto& controller = GetControllerFromNpadIdType(npad_id);
321 std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, 334 const auto controller_type = controller.device->GetNpadStyleIndex();
322 players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, 335 if (!controller.device->IsConnected()) {
323 buttons[i].begin(), Input::CreateDevice<Input::ButtonDevice>); 336 return;
324 std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
325 players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
326 sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
327 std::transform(players[i].vibrations.begin() +
328 Settings::NativeVibration::VIBRATION_HID_BEGIN,
329 players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END,
330 vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>);
331 std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
332 players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
333 motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
334 for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) {
335 InitializeVibrationDeviceAtIndex(i, device_idx);
336 }
337 } 337 }
338}
339 338
340void Controller_NPad::OnRelease() { 339 auto& pad_entry = controller.npad_pad_state;
341 for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { 340 auto& trigger_entry = controller.npad_trigger_state;
342 for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { 341 const auto button_state = controller.device->GetNpadButtons();
343 VibrateControllerAtIndex(npad_idx, device_idx, {}); 342 const auto stick_state = controller.device->GetSticks();
344 } 343
344 using btn = Core::HID::NpadButton;
345 pad_entry.npad_buttons.raw = btn::None;
346 if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
347 constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
348 btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
349 btn::StickRRight | btn::StickRDown;
350 pad_entry.npad_buttons.raw = button_state.raw & right_button_mask;
351 pad_entry.r_stick = stick_state.right;
345 } 352 }
346 353
347 for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { 354 if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
348 service_context.CloseEvent(styleset_changed_events[i]); 355 constexpr btn left_button_mask =
356 btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
357 btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
358 pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask;
359 pad_entry.l_stick = stick_state.left;
349 } 360 }
350}
351 361
352void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { 362 if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
353 std::lock_guard lock{mutex}; 363 pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
364 pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
365 }
354 366
355 const auto controller_idx = NPadIdToIndex(npad_id); 367 if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
356 const auto controller_type = connected_controllers[controller_idx].type; 368 pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
357 if (!connected_controllers[controller_idx].is_connected) { 369 pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
358 return;
359 } 370 }
360 auto& pad_state = npad_pad_states[controller_idx].pad_states; 371
361 auto& lstick_entry = npad_pad_states[controller_idx].l_stick; 372 if (controller_type == Core::HID::NpadStyleIndex::GameCube) {
362 auto& rstick_entry = npad_pad_states[controller_idx].r_stick; 373 const auto& trigger_state = controller.device->GetTriggers();
363 auto& trigger_entry = npad_trigger_states[controller_idx]; 374 trigger_entry.l_analog = trigger_state.left;
364 const auto& button_state = buttons[controller_idx]; 375 trigger_entry.r_analog = trigger_state.right;
365 const auto& analog_state = sticks[controller_idx]; 376 pad_entry.npad_buttons.zl.Assign(false);
366 const auto [stick_l_x_f, stick_l_y_f] = 377 pad_entry.npad_buttons.zr.Assign(button_state.r);
367 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus(); 378 pad_entry.npad_buttons.l.Assign(button_state.zl);
368 const auto [stick_r_x_f, stick_r_y_f] = 379 pad_entry.npad_buttons.r.Assign(button_state.zr);
369 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
370
371 using namespace Settings::NativeButton;
372 if (controller_type != NPadControllerType::JoyLeft) {
373 pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
374 pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
375 pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
376 pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
377 pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
378 pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
379 pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
380 pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
381
382 pad_state.r_stick_right.Assign(
383 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
384 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
385 pad_state.r_stick_left.Assign(
386 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
387 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
388 pad_state.r_stick_up.Assign(
389 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
390 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
391 pad_state.r_stick_down.Assign(
392 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
393 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
394 rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
395 rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
396 }
397
398 if (controller_type != NPadControllerType::JoyRight) {
399 pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
400 pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
401 pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
402 pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
403 pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
404 pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
405 pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
406 pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
407
408 pad_state.l_stick_right.Assign(
409 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
410 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
411 pad_state.l_stick_left.Assign(
412 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
413 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
414 pad_state.l_stick_up.Assign(
415 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
416 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
417 pad_state.l_stick_down.Assign(
418 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
419 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
420 lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
421 lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
422 }
423
424 if (controller_type == NPadControllerType::JoyLeft) {
425 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
426 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
427 }
428
429 if (controller_type == NPadControllerType::JoyRight) {
430 pad_state.right_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
431 pad_state.right_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
432 }
433
434 if (controller_type == NPadControllerType::GameCube) {
435 trigger_entry.l_analog = static_cast<s32>(
436 button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
437 trigger_entry.r_analog = static_cast<s32>(
438 button_state[ZR - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
439 pad_state.zl.Assign(false);
440 pad_state.zr.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
441 pad_state.l.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
442 pad_state.r.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
443 } 380 }
444} 381}
445 382
@@ -448,173 +385,132 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
448 if (!IsControllerActivated()) { 385 if (!IsControllerActivated()) {
449 return; 386 return;
450 } 387 }
451 for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
452 auto& npad = shared_memory_entries[i];
453 const std::array<NPadGeneric*, 7> controller_npads{
454 &npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states,
455 &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
456 &npad.system_ext_states};
457
458 // There is the posibility to have more controllers with analog triggers
459 const std::array<TriggerGeneric*, 1> controller_triggers{
460 &npad.gc_trigger_states,
461 };
462
463 for (auto* main_controller : controller_npads) {
464 main_controller->common.entry_count = 16;
465 main_controller->common.total_entry_count = 17;
466
467 const auto& last_entry =
468 main_controller->npad[main_controller->common.last_entry_index];
469
470 main_controller->common.timestamp = core_timing.GetCPUTicks();
471 main_controller->common.last_entry_index =
472 (main_controller->common.last_entry_index + 1) % 17;
473
474 auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index];
475
476 cur_entry.timestamp = last_entry.timestamp + 1;
477 cur_entry.timestamp2 = cur_entry.timestamp;
478 }
479
480 for (auto* analog_trigger : controller_triggers) {
481 analog_trigger->entry_count = 16;
482 analog_trigger->total_entry_count = 17;
483 388
484 const auto& last_entry = analog_trigger->trigger[analog_trigger->last_entry_index]; 389 for (std::size_t i = 0; i < controller_data.size(); ++i) {
390 auto& controller = controller_data[i];
391 auto& npad = controller.shared_memory_entry;
485 392
486 analog_trigger->timestamp = core_timing.GetCPUTicks(); 393 const auto& controller_type = controller.device->GetNpadStyleIndex();
487 analog_trigger->last_entry_index = (analog_trigger->last_entry_index + 1) % 17;
488 394
489 auto& cur_entry = analog_trigger->trigger[analog_trigger->last_entry_index]; 395 if (controller_type == Core::HID::NpadStyleIndex::None ||
490 396 !controller.device->IsConnected()) {
491 cur_entry.timestamp = last_entry.timestamp + 1; 397 // Refresh shared memory
492 cur_entry.timestamp2 = cur_entry.timestamp; 398 std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
493 } 399 &controller.shared_memory_entry, sizeof(NpadInternalState));
494
495 const auto& controller_type = connected_controllers[i].type;
496
497 if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
498 continue; 400 continue;
499 } 401 }
500 const u32 npad_index = static_cast<u32>(i);
501
502 RequestPadStateUpdate(npad_index);
503 auto& pad_state = npad_pad_states[npad_index];
504 auto& trigger_state = npad_trigger_states[npad_index];
505
506 auto& main_controller =
507 npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
508 auto& handheld_entry =
509 npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
510 auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index];
511 auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index];
512 auto& right_entry =
513 npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index];
514 auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
515 auto& libnx_entry =
516 npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
517 auto& trigger_entry =
518 npad.gc_trigger_states.trigger[npad.gc_trigger_states.last_entry_index];
519
520 libnx_entry.connection_status.raw = 0;
521 libnx_entry.connection_status.is_connected.Assign(1);
522 402
403 RequestPadStateUpdate(controller.device->GetNpadIdType());
404 auto& pad_state = controller.npad_pad_state;
405 auto& libnx_state = controller.npad_libnx_state;
406 auto& trigger_state = controller.npad_trigger_state;
407
408 // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
409 // any controllers.
410 libnx_state.connection_status.raw = 0;
411 libnx_state.connection_status.is_connected.Assign(1);
523 switch (controller_type) { 412 switch (controller_type) {
524 case NPadControllerType::None: 413 case Core::HID::NpadStyleIndex::None:
525 UNREACHABLE(); 414 UNREACHABLE();
526 break; 415 break;
527 case NPadControllerType::ProController: 416 case Core::HID::NpadStyleIndex::ProController:
528 main_controller.connection_status.raw = 0; 417 case Core::HID::NpadStyleIndex::NES:
529 main_controller.connection_status.is_connected.Assign(1); 418 case Core::HID::NpadStyleIndex::SNES:
530 main_controller.connection_status.is_wired.Assign(1); 419 case Core::HID::NpadStyleIndex::N64:
531 main_controller.pad.pad_states.raw = pad_state.pad_states.raw; 420 case Core::HID::NpadStyleIndex::SegaGenesis:
532 main_controller.pad.l_stick = pad_state.l_stick; 421 pad_state.connection_status.raw = 0;
533 main_controller.pad.r_stick = pad_state.r_stick; 422 pad_state.connection_status.is_connected.Assign(1);
534 423 pad_state.connection_status.is_wired.Assign(1);
535 libnx_entry.connection_status.is_wired.Assign(1); 424
425 libnx_state.connection_status.is_wired.Assign(1);
426 pad_state.sampling_number =
427 npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
428 npad.fullkey_lifo.WriteNextEntry(pad_state);
429 break;
430 case Core::HID::NpadStyleIndex::Handheld:
431 pad_state.connection_status.raw = 0;
432 pad_state.connection_status.is_connected.Assign(1);
433 pad_state.connection_status.is_wired.Assign(1);
434 pad_state.connection_status.is_left_connected.Assign(1);
435 pad_state.connection_status.is_right_connected.Assign(1);
436 pad_state.connection_status.is_left_wired.Assign(1);
437 pad_state.connection_status.is_right_wired.Assign(1);
438
439 libnx_state.connection_status.is_wired.Assign(1);
440 libnx_state.connection_status.is_left_connected.Assign(1);
441 libnx_state.connection_status.is_right_connected.Assign(1);
442 libnx_state.connection_status.is_left_wired.Assign(1);
443 libnx_state.connection_status.is_right_wired.Assign(1);
444 pad_state.sampling_number =
445 npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
446 npad.handheld_lifo.WriteNextEntry(pad_state);
536 break; 447 break;
537 case NPadControllerType::Handheld: 448 case Core::HID::NpadStyleIndex::JoyconDual:
538 handheld_entry.connection_status.raw = 0; 449 pad_state.connection_status.raw = 0;
539 handheld_entry.connection_status.is_connected.Assign(1); 450 pad_state.connection_status.is_connected.Assign(1);
540 handheld_entry.connection_status.is_wired.Assign(1); 451 pad_state.connection_status.is_left_connected.Assign(1);
541 handheld_entry.connection_status.is_left_connected.Assign(1); 452 pad_state.connection_status.is_right_connected.Assign(1);
542 handheld_entry.connection_status.is_right_connected.Assign(1); 453
543 handheld_entry.connection_status.is_left_wired.Assign(1); 454 libnx_state.connection_status.is_left_connected.Assign(1);
544 handheld_entry.connection_status.is_right_wired.Assign(1); 455 libnx_state.connection_status.is_right_connected.Assign(1);
545 handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; 456 pad_state.sampling_number =
546 handheld_entry.pad.l_stick = pad_state.l_stick; 457 npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
547 handheld_entry.pad.r_stick = pad_state.r_stick; 458 npad.joy_dual_lifo.WriteNextEntry(pad_state);
548
549 libnx_entry.connection_status.is_wired.Assign(1);
550 libnx_entry.connection_status.is_left_connected.Assign(1);
551 libnx_entry.connection_status.is_right_connected.Assign(1);
552 libnx_entry.connection_status.is_left_wired.Assign(1);
553 libnx_entry.connection_status.is_right_wired.Assign(1);
554 break; 459 break;
555 case NPadControllerType::JoyDual: 460 case Core::HID::NpadStyleIndex::JoyconLeft:
556 dual_entry.connection_status.raw = 0; 461 pad_state.connection_status.raw = 0;
557 dual_entry.connection_status.is_connected.Assign(1); 462 pad_state.connection_status.is_connected.Assign(1);
558 dual_entry.connection_status.is_left_connected.Assign(1); 463 pad_state.connection_status.is_left_connected.Assign(1);
559 dual_entry.connection_status.is_right_connected.Assign(1); 464
560 dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; 465 libnx_state.connection_status.is_left_connected.Assign(1);
561 dual_entry.pad.l_stick = pad_state.l_stick; 466 pad_state.sampling_number =
562 dual_entry.pad.r_stick = pad_state.r_stick; 467 npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
563 468 npad.joy_left_lifo.WriteNextEntry(pad_state);
564 libnx_entry.connection_status.is_left_connected.Assign(1);
565 libnx_entry.connection_status.is_right_connected.Assign(1);
566 break; 469 break;
567 case NPadControllerType::JoyLeft: 470 case Core::HID::NpadStyleIndex::JoyconRight:
568 left_entry.connection_status.raw = 0; 471 pad_state.connection_status.raw = 0;
569 left_entry.connection_status.is_connected.Assign(1); 472 pad_state.connection_status.is_connected.Assign(1);
570 left_entry.connection_status.is_left_connected.Assign(1); 473 pad_state.connection_status.is_right_connected.Assign(1);
571 left_entry.pad.pad_states.raw = pad_state.pad_states.raw; 474
572 left_entry.pad.l_stick = pad_state.l_stick; 475 libnx_state.connection_status.is_right_connected.Assign(1);
573 left_entry.pad.r_stick = pad_state.r_stick; 476 pad_state.sampling_number =
574 477 npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
575 libnx_entry.connection_status.is_left_connected.Assign(1); 478 npad.joy_right_lifo.WriteNextEntry(pad_state);
576 break; 479 break;
577 case NPadControllerType::JoyRight: 480 case Core::HID::NpadStyleIndex::GameCube:
578 right_entry.connection_status.raw = 0; 481 pad_state.connection_status.raw = 0;
579 right_entry.connection_status.is_connected.Assign(1); 482 pad_state.connection_status.is_connected.Assign(1);
580 right_entry.connection_status.is_right_connected.Assign(1); 483 pad_state.connection_status.is_wired.Assign(1);
581 right_entry.pad.pad_states.raw = pad_state.pad_states.raw; 484
582 right_entry.pad.l_stick = pad_state.l_stick; 485 libnx_state.connection_status.is_wired.Assign(1);
583 right_entry.pad.r_stick = pad_state.r_stick; 486 pad_state.sampling_number =
584 487 npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
585 libnx_entry.connection_status.is_right_connected.Assign(1); 488 trigger_state.sampling_number =
489 npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1;
490 npad.fullkey_lifo.WriteNextEntry(pad_state);
491 npad.gc_trigger_lifo.WriteNextEntry(trigger_state);
586 break; 492 break;
587 case NPadControllerType::GameCube: 493 case Core::HID::NpadStyleIndex::Pokeball:
588 main_controller.connection_status.raw = 0; 494 pad_state.connection_status.raw = 0;
589 main_controller.connection_status.is_connected.Assign(1); 495 pad_state.connection_status.is_connected.Assign(1);
590 main_controller.connection_status.is_wired.Assign(1); 496 pad_state.sampling_number =
591 main_controller.pad.pad_states.raw = pad_state.pad_states.raw; 497 npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
592 main_controller.pad.l_stick = pad_state.l_stick; 498 npad.palma_lifo.WriteNextEntry(pad_state);
593 main_controller.pad.r_stick = pad_state.r_stick;
594 trigger_entry.l_analog = trigger_state.l_analog;
595 trigger_entry.r_analog = trigger_state.r_analog;
596
597 libnx_entry.connection_status.is_wired.Assign(1);
598 break; 499 break;
599 case NPadControllerType::Pokeball: 500 default:
600 pokeball_entry.connection_status.raw = 0;
601 pokeball_entry.connection_status.is_connected.Assign(1);
602 pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
603 pokeball_entry.pad.l_stick = pad_state.l_stick;
604 pokeball_entry.pad.r_stick = pad_state.r_stick;
605 break; 501 break;
606 } 502 }
607 503
608 // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate 504 libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
609 // any controllers. 505 libnx_state.l_stick = pad_state.l_stick;
610 libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; 506 libnx_state.r_stick = pad_state.r_stick;
611 libnx_entry.pad.l_stick = pad_state.l_stick; 507 npad.system_ext_lifo.WriteNextEntry(pad_state);
612 libnx_entry.pad.r_stick = pad_state.r_stick;
613 508
614 press_state |= static_cast<u32>(pad_state.pad_states.raw); 509 press_state |= static_cast<u32>(pad_state.npad_buttons.raw);
510
511 std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
512 &controller.shared_memory_entry, sizeof(NpadInternalState));
615 } 513 }
616 std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
617 shared_memory_entries.size() * sizeof(NPadEntry));
618} 514}
619 515
620void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 516void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
@@ -622,145 +518,138 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
622 if (!IsControllerActivated()) { 518 if (!IsControllerActivated()) {
623 return; 519 return;
624 } 520 }
625 for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
626 auto& npad = shared_memory_entries[i];
627
628 const auto& controller_type = connected_controllers[i].type;
629
630 if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
631 continue;
632 }
633 521
634 const std::array<SixAxisGeneric*, 6> controller_sixaxes{ 522 for (std::size_t i = 0; i < controller_data.size(); ++i) {
635 &npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left, 523 auto& controller = controller_data[i];
636 &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
637 };
638 524
639 for (auto* sixaxis_sensor : controller_sixaxes) { 525 const auto& controller_type = controller.device->GetNpadStyleIndex();
640 sixaxis_sensor->common.entry_count = 16;
641 sixaxis_sensor->common.total_entry_count = 17;
642 526
643 const auto& last_entry = 527 if (controller_type == Core::HID::NpadStyleIndex::None ||
644 sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index]; 528 !controller.device->IsConnected()) {
645 529 continue;
646 sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks();
647 sixaxis_sensor->common.last_entry_index =
648 (sixaxis_sensor->common.last_entry_index + 1) % 17;
649
650 auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
651
652 cur_entry.timestamp = last_entry.timestamp + 1;
653 cur_entry.timestamp2 = cur_entry.timestamp;
654 } 530 }
655 531
656 // Try to read sixaxis sensor states 532 auto& npad = controller.shared_memory_entry;
657 std::array<MotionDevice, 2> motion_devices; 533 const auto& motion_state = controller.device->GetMotions();
658 534 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
659 if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { 535 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
660 sixaxis_at_rest = true; 536 auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
661 for (std::size_t e = 0; e < motion_devices.size(); ++e) { 537 auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
662 const auto& device = motions[i][e]; 538 auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
663 if (device) { 539 auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
664 std::tie(motion_devices[e].accel, motion_devices[e].gyro, 540
665 motion_devices[e].rotation, motion_devices[e].orientation, 541 if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
666 motion_devices[e].quaternion) = device->GetStatus(); 542 controller.sixaxis_at_rest = true;
667 sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f; 543 for (std::size_t e = 0; e < motion_state.size(); ++e) {
668 } 544 controller.sixaxis_at_rest =
545 controller.sixaxis_at_rest && motion_state[e].is_at_rest;
669 } 546 }
670 } 547 }
671 548
672 auto& full_sixaxis_entry =
673 npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index];
674 auto& handheld_sixaxis_entry =
675 npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
676 auto& dual_left_sixaxis_entry =
677 npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
678 auto& dual_right_sixaxis_entry =
679 npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
680 auto& left_sixaxis_entry =
681 npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
682 auto& right_sixaxis_entry =
683 npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
684
685 switch (controller_type) { 549 switch (controller_type) {
686 case NPadControllerType::None: 550 case Core::HID::NpadStyleIndex::None:
687 UNREACHABLE(); 551 UNREACHABLE();
688 break; 552 break;
689 case NPadControllerType::ProController: 553 case Core::HID::NpadStyleIndex::ProController:
690 full_sixaxis_entry.attribute.raw = 0; 554 sixaxis_fullkey_state.attribute.raw = 0;
691 if (sixaxis_sensors_enabled && motions[i][0]) { 555 if (controller.sixaxis_sensor_enabled) {
692 full_sixaxis_entry.attribute.is_connected.Assign(1); 556 sixaxis_fullkey_state.attribute.is_connected.Assign(1);
693 full_sixaxis_entry.accel = motion_devices[0].accel; 557 sixaxis_fullkey_state.accel = motion_state[0].accel;
694 full_sixaxis_entry.gyro = motion_devices[0].gyro; 558 sixaxis_fullkey_state.gyro = motion_state[0].gyro;
695 full_sixaxis_entry.rotation = motion_devices[0].rotation; 559 sixaxis_fullkey_state.rotation = motion_state[0].rotation;
696 full_sixaxis_entry.orientation = motion_devices[0].orientation; 560 sixaxis_fullkey_state.orientation = motion_state[0].orientation;
697 } 561 }
698 break; 562 break;
699 case NPadControllerType::Handheld: 563 case Core::HID::NpadStyleIndex::Handheld:
700 handheld_sixaxis_entry.attribute.raw = 0; 564 sixaxis_handheld_state.attribute.raw = 0;
701 if (sixaxis_sensors_enabled && motions[i][0]) { 565 if (controller.sixaxis_sensor_enabled) {
702 handheld_sixaxis_entry.attribute.is_connected.Assign(1); 566 sixaxis_handheld_state.attribute.is_connected.Assign(1);
703 handheld_sixaxis_entry.accel = motion_devices[0].accel; 567 sixaxis_handheld_state.accel = motion_state[0].accel;
704 handheld_sixaxis_entry.gyro = motion_devices[0].gyro; 568 sixaxis_handheld_state.gyro = motion_state[0].gyro;
705 handheld_sixaxis_entry.rotation = motion_devices[0].rotation; 569 sixaxis_handheld_state.rotation = motion_state[0].rotation;
706 handheld_sixaxis_entry.orientation = motion_devices[0].orientation; 570 sixaxis_handheld_state.orientation = motion_state[0].orientation;
707 } 571 }
708 break; 572 break;
709 case NPadControllerType::JoyDual: 573 case Core::HID::NpadStyleIndex::JoyconDual:
710 dual_left_sixaxis_entry.attribute.raw = 0; 574 sixaxis_dual_left_state.attribute.raw = 0;
711 dual_right_sixaxis_entry.attribute.raw = 0; 575 sixaxis_dual_right_state.attribute.raw = 0;
712 if (sixaxis_sensors_enabled && motions[i][0]) { 576 if (controller.sixaxis_sensor_enabled) {
713 // Set motion for the left joycon 577 // Set motion for the left joycon
714 dual_left_sixaxis_entry.attribute.is_connected.Assign(1); 578 sixaxis_dual_left_state.attribute.is_connected.Assign(1);
715 dual_left_sixaxis_entry.accel = motion_devices[0].accel; 579 sixaxis_dual_left_state.accel = motion_state[0].accel;
716 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro; 580 sixaxis_dual_left_state.gyro = motion_state[0].gyro;
717 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation; 581 sixaxis_dual_left_state.rotation = motion_state[0].rotation;
718 dual_left_sixaxis_entry.orientation = motion_devices[0].orientation; 582 sixaxis_dual_left_state.orientation = motion_state[0].orientation;
719 } 583 }
720 if (sixaxis_sensors_enabled && motions[i][1]) { 584 if (controller.sixaxis_sensor_enabled) {
721 // Set motion for the right joycon 585 // Set motion for the right joycon
722 dual_right_sixaxis_entry.attribute.is_connected.Assign(1); 586 sixaxis_dual_right_state.attribute.is_connected.Assign(1);
723 dual_right_sixaxis_entry.accel = motion_devices[1].accel; 587 sixaxis_dual_right_state.accel = motion_state[1].accel;
724 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro; 588 sixaxis_dual_right_state.gyro = motion_state[1].gyro;
725 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation; 589 sixaxis_dual_right_state.rotation = motion_state[1].rotation;
726 dual_right_sixaxis_entry.orientation = motion_devices[1].orientation; 590 sixaxis_dual_right_state.orientation = motion_state[1].orientation;
727 } 591 }
728 break; 592 break;
729 case NPadControllerType::JoyLeft: 593 case Core::HID::NpadStyleIndex::JoyconLeft:
730 left_sixaxis_entry.attribute.raw = 0; 594 sixaxis_left_lifo_state.attribute.raw = 0;
731 if (sixaxis_sensors_enabled && motions[i][0]) { 595 if (controller.sixaxis_sensor_enabled) {
732 left_sixaxis_entry.attribute.is_connected.Assign(1); 596 sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
733 left_sixaxis_entry.accel = motion_devices[0].accel; 597 sixaxis_left_lifo_state.accel = motion_state[0].accel;
734 left_sixaxis_entry.gyro = motion_devices[0].gyro; 598 sixaxis_left_lifo_state.gyro = motion_state[0].gyro;
735 left_sixaxis_entry.rotation = motion_devices[0].rotation; 599 sixaxis_left_lifo_state.rotation = motion_state[0].rotation;
736 left_sixaxis_entry.orientation = motion_devices[0].orientation; 600 sixaxis_left_lifo_state.orientation = motion_state[0].orientation;
737 } 601 }
738 break; 602 break;
739 case NPadControllerType::JoyRight: 603 case Core::HID::NpadStyleIndex::JoyconRight:
740 right_sixaxis_entry.attribute.raw = 0; 604 sixaxis_right_lifo_state.attribute.raw = 0;
741 if (sixaxis_sensors_enabled && motions[i][1]) { 605 if (controller.sixaxis_sensor_enabled) {
742 right_sixaxis_entry.attribute.is_connected.Assign(1); 606 sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
743 right_sixaxis_entry.accel = motion_devices[1].accel; 607 sixaxis_right_lifo_state.accel = motion_state[1].accel;
744 right_sixaxis_entry.gyro = motion_devices[1].gyro; 608 sixaxis_right_lifo_state.gyro = motion_state[1].gyro;
745 right_sixaxis_entry.rotation = motion_devices[1].rotation; 609 sixaxis_right_lifo_state.rotation = motion_state[1].rotation;
746 right_sixaxis_entry.orientation = motion_devices[1].orientation; 610 sixaxis_right_lifo_state.orientation = motion_state[1].orientation;
747 } 611 }
748 break; 612 break;
749 case NPadControllerType::GameCube: 613 default:
750 case NPadControllerType::Pokeball:
751 break; 614 break;
752 } 615 }
616
617 sixaxis_fullkey_state.sampling_number =
618 npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
619 sixaxis_handheld_state.sampling_number =
620 npad.sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
621 sixaxis_dual_left_state.sampling_number =
622 npad.sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
623 sixaxis_dual_right_state.sampling_number =
624 npad.sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
625 sixaxis_left_lifo_state.sampling_number =
626 npad.sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
627 sixaxis_right_lifo_state.sampling_number =
628 npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
629
630 if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
631 // This buffer only is updated on handheld on HW
632 npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
633 } else {
634 // Hanheld doesn't update this buffer on HW
635 npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
636 }
637
638 npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
639 npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
640 npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
641 npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
642 std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
643 &controller.shared_memory_entry, sizeof(NpadInternalState));
753 } 644 }
754 std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
755 shared_memory_entries.size() * sizeof(NPadEntry));
756} 645}
757 646
758void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) { 647void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
759 style.raw = style_set.raw; 648 hid_core.SetSupportedStyleTag(style_set);
760} 649}
761 650
762Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { 651Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
763 return style; 652 return hid_core.GetSupportedStyleTag();
764} 653}
765 654
766void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { 655void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
@@ -779,11 +668,11 @@ std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
779 return supported_npad_id_types.size(); 668 return supported_npad_id_types.size();
780} 669}
781 670
782void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { 671void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
783 hold_type = joy_hold_type; 672 hold_type = joy_hold_type;
784} 673}
785 674
786Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const { 675Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
787 return hold_type; 676 return hold_type;
788} 677}
789 678
@@ -803,29 +692,35 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
803 return communication_mode; 692 return communication_mode;
804} 693}
805 694
806void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { 695void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
807 const std::size_t npad_index = NPadIdToIndex(npad_id); 696 NpadJoyAssignmentMode assignment_mode) {
808 ASSERT(npad_index < shared_memory_entries.size()); 697 if (!IsNpadIdValid(npad_id)) {
809 if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) { 698 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
810 shared_memory_entries[npad_index].assignment_mode = assignment_mode; 699 return;
700 }
701
702 auto& controller = GetControllerFromNpadIdType(npad_id);
703 if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
704 controller.shared_memory_entry.assignment_mode = assignment_mode;
811 } 705 }
812} 706}
813 707
814bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, 708bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
815 const VibrationValue& vibration_value) { 709 std::size_t device_index,
816 if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) { 710 const Core::HID::VibrationValue& vibration_value) {
711 auto& controller = GetControllerFromNpadIdType(npad_id);
712 if (!controller.device->IsConnected()) {
817 return false; 713 return false;
818 } 714 }
819 715
820 const auto& player = Settings::values.players.GetValue()[npad_index]; 716 if (!controller.device->IsVibrationEnabled()) {
821 717 if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
822 if (!player.vibration_enabled) { 718 controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
823 if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f ||
824 latest_vibration_values[npad_index][device_index].amp_high != 0.0f) {
825 // Send an empty vibration to stop any vibrations. 719 // Send an empty vibration to stop any vibrations.
826 vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f); 720 Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
721 controller.device->SetVibration(device_index, vibration);
827 // Then reset the vibration value to its default value. 722 // Then reset the vibration value to its default value.
828 latest_vibration_values[npad_index][device_index] = DEFAULT_VIBRATION_VALUE; 723 controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
829 } 724 }
830 725
831 return false; 726 return false;
@@ -839,27 +734,25 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size
839 const auto now = steady_clock::now(); 734 const auto now = steady_clock::now();
840 735
841 // Filter out non-zero vibrations that are within 10ms of each other. 736 // Filter out non-zero vibrations that are within 10ms of each other.
842 if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && 737 if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
843 duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) < 738 duration_cast<milliseconds>(
739 now - controller.vibration[device_index].last_vibration_timepoint) <
844 milliseconds(10)) { 740 milliseconds(10)) {
845 return false; 741 return false;
846 } 742 }
847 743
848 last_vibration_timepoints[npad_index][device_index] = now; 744 controller.vibration[device_index].last_vibration_timepoint = now;
849 } 745 }
850 746
851 auto& vibration = vibrations[npad_index][device_index]; 747 Core::HID::VibrationValue vibration{
852 const auto player_vibration_strength = static_cast<f32>(player.vibration_strength); 748 vibration_value.low_amplitude, vibration_value.low_frequency,
853 const auto amp_low = 749 vibration_value.high_amplitude, vibration_value.high_frequency};
854 std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f); 750 return controller.device->SetVibration(device_index, vibration);
855 const auto amp_high =
856 std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f);
857 return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high,
858 vibration_value.freq_high);
859} 751}
860 752
861void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, 753void Controller_NPad::VibrateController(
862 const VibrationValue& vibration_value) { 754 const Core::HID::VibrationDeviceHandle& vibration_device_handle,
755 const Core::HID::VibrationValue& vibration_value) {
863 if (!IsDeviceHandleValid(vibration_device_handle)) { 756 if (!IsDeviceHandleValid(vibration_device_handle)) {
864 return; 757 return;
865 } 758 }
@@ -868,42 +761,45 @@ void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_han
868 return; 761 return;
869 } 762 }
870 763
871 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); 764 auto& controller = GetControllerFromHandle(vibration_device_handle);
872 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); 765 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
873 766
874 if (!vibration_devices_mounted[npad_index][device_index] || 767 if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
875 !connected_controllers[npad_index].is_connected) {
876 return; 768 return;
877 } 769 }
878 770
879 if (vibration_device_handle.device_index == DeviceIndex::None) { 771 if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
880 UNREACHABLE_MSG("DeviceIndex should never be None!"); 772 UNREACHABLE_MSG("DeviceIndex should never be None!");
881 return; 773 return;
882 } 774 }
883 775
884 // Some games try to send mismatched parameters in the device handle, block these. 776 // Some games try to send mismatched parameters in the device handle, block these.
885 if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && 777 if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
886 (vibration_device_handle.npad_type == NpadType::JoyconRight || 778 (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
887 vibration_device_handle.device_index == DeviceIndex::Right)) || 779 vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
888 (connected_controllers[npad_index].type == NPadControllerType::JoyRight && 780 (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
889 (vibration_device_handle.npad_type == NpadType::JoyconLeft || 781 (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
890 vibration_device_handle.device_index == DeviceIndex::Left))) { 782 vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
891 return; 783 return;
892 } 784 }
893 785
894 // Filter out vibrations with equivalent values to reduce unnecessary state changes. 786 // Filter out vibrations with equivalent values to reduce unnecessary state changes.
895 if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && 787 if (vibration_value.low_amplitude ==
896 vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { 788 controller.vibration[device_index].latest_vibration_value.low_amplitude &&
789 vibration_value.high_amplitude ==
790 controller.vibration[device_index].latest_vibration_value.high_amplitude) {
897 return; 791 return;
898 } 792 }
899 793
900 if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { 794 if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index,
901 latest_vibration_values[npad_index][device_index] = vibration_value; 795 vibration_value)) {
796 controller.vibration[device_index].latest_vibration_value = vibration_value;
902 } 797 }
903} 798}
904 799
905void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, 800void Controller_NPad::VibrateControllers(
906 const std::vector<VibrationValue>& vibration_values) { 801 const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
802 const std::vector<Core::HID::VibrationValue>& vibration_values) {
907 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { 803 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
908 return; 804 return;
909 } 805 }
@@ -918,167 +814,231 @@ void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibrat
918 } 814 }
919} 815}
920 816
921Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( 817Core::HID::VibrationValue Controller_NPad::GetLastVibration(
922 const DeviceHandle& vibration_device_handle) const { 818 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
923 if (!IsDeviceHandleValid(vibration_device_handle)) { 819 if (!IsDeviceHandleValid(vibration_device_handle)) {
924 return {}; 820 return {};
925 } 821 }
926 822
927 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); 823 const auto& controller = GetControllerFromHandle(vibration_device_handle);
928 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); 824 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
929 return latest_vibration_values[npad_index][device_index]; 825 return controller.vibration[device_index].latest_vibration_value;
930} 826}
931 827
932void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { 828void Controller_NPad::InitializeVibrationDevice(
829 const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
933 if (!IsDeviceHandleValid(vibration_device_handle)) { 830 if (!IsDeviceHandleValid(vibration_device_handle)) {
934 return; 831 return;
935 } 832 }
936 833
937 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); 834 const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
938 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); 835 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
939 InitializeVibrationDeviceAtIndex(npad_index, device_index); 836 InitializeVibrationDeviceAtIndex(npad_index, device_index);
940} 837}
941 838
942void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, 839void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
943 std::size_t device_index) { 840 std::size_t device_index) {
841 auto& controller = GetControllerFromNpadIdType(npad_id);
944 if (!Settings::values.vibration_enabled.GetValue()) { 842 if (!Settings::values.vibration_enabled.GetValue()) {
945 vibration_devices_mounted[npad_index][device_index] = false; 843 controller.vibration[device_index].device_mounted = false;
946 return; 844 return;
947 } 845 }
948 846
949 if (vibrations[npad_index][device_index]) { 847 controller.vibration[device_index].device_mounted =
950 vibration_devices_mounted[npad_index][device_index] = 848 controller.device->TestVibration(device_index);
951 vibrations[npad_index][device_index]->GetStatus() == 1;
952 } else {
953 vibration_devices_mounted[npad_index][device_index] = false;
954 }
955} 849}
956 850
957void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { 851void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
958 permit_vibration_session_enabled = permit_vibration_session; 852 permit_vibration_session_enabled = permit_vibration_session;
959} 853}
960 854
961bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { 855bool Controller_NPad::IsVibrationDeviceMounted(
856 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
962 if (!IsDeviceHandleValid(vibration_device_handle)) { 857 if (!IsDeviceHandleValid(vibration_device_handle)) {
963 return false; 858 return false;
964 } 859 }
965 860
966 const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); 861 const auto& controller = GetControllerFromHandle(vibration_device_handle);
967 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); 862 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
968 return vibration_devices_mounted[npad_index][device_index]; 863 return controller.vibration[device_index].device_mounted;
969} 864}
970 865
971Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) { 866Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
972 return styleset_changed_events[NPadIdToIndex(npad_id)]->GetReadableEvent(); 867 if (!IsNpadIdValid(npad_id)) {
868 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
869 // Fallback to player 1
870 const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1);
871 return controller.styleset_changed_event->GetReadableEvent();
872 }
873
874 const auto& controller = GetControllerFromNpadIdType(npad_id);
875 return controller.styleset_changed_event->GetReadableEvent();
973} 876}
974 877
975void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { 878void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
976 styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent().Signal(); 879 const auto& controller = GetControllerFromNpadIdType(npad_id);
880 controller.styleset_changed_event->GetWritableEvent().Signal();
977} 881}
978 882
979void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { 883void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
980 UpdateControllerAt(controller, npad_index, true); 884 Core::HID::NpadIdType npad_id) {
885 UpdateControllerAt(controller, npad_id, true);
981} 886}
982 887
983void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, 888void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
984 bool connected) { 889 Core::HID::NpadIdType npad_id, bool connected) {
890 auto& controller = GetControllerFromNpadIdType(npad_id);
985 if (!connected) { 891 if (!connected) {
986 DisconnectNpadAtIndex(npad_index); 892 DisconnectNpad(npad_id);
987 return; 893 return;
988 } 894 }
989 895
990 if (controller == NPadControllerType::Handheld && npad_index == HANDHELD_INDEX) { 896 controller.device->SetNpadStyleIndex(type);
991 Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = 897 InitNewlyAddedController(npad_id);
992 MapNPadToSettingsType(controller);
993 Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
994 connected_controllers[HANDHELD_INDEX] = {controller, true};
995 InitNewlyAddedController(HANDHELD_INDEX);
996 return;
997 }
998
999 Settings::values.players.GetValue()[npad_index].controller_type =
1000 MapNPadToSettingsType(controller);
1001 Settings::values.players.GetValue()[npad_index].connected = true;
1002 connected_controllers[npad_index] = {controller, true};
1003 InitNewlyAddedController(npad_index);
1004} 898}
1005 899
1006void Controller_NPad::DisconnectNpad(u32 npad_id) { 900void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1007 DisconnectNpadAtIndex(NPadIdToIndex(npad_id)); 901 if (!IsNpadIdValid(npad_id)) {
1008} 902 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
903 return;
904 }
1009 905
1010void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { 906 LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
1011 for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { 907 auto& controller = GetControllerFromNpadIdType(npad_id);
908 for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
1012 // Send an empty vibration to stop any vibrations. 909 // Send an empty vibration to stop any vibrations.
1013 VibrateControllerAtIndex(npad_index, device_idx, {}); 910 VibrateControllerAtIndex(npad_id, device_idx, {});
1014 vibration_devices_mounted[npad_index][device_idx] = false; 911 controller.vibration[device_idx].device_mounted = false;
1015 } 912 }
1016 913
1017 Settings::values.players.GetValue()[npad_index].connected = false; 914 auto& shared_memory_entry = controller.shared_memory_entry;
1018 connected_controllers[npad_index].is_connected = false; 915 shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
916 shared_memory_entry.device_type.raw = 0;
917 shared_memory_entry.system_properties.raw = 0;
918 shared_memory_entry.button_properties.raw = 0;
919 shared_memory_entry.battery_level_dual = 0;
920 shared_memory_entry.battery_level_left = 0;
921 shared_memory_entry.battery_level_right = 0;
922 shared_memory_entry.fullkey_color = {
923 .attribute = ColorAttribute::NoController,
924 .fullkey = {},
925 };
926 shared_memory_entry.joycon_color = {
927 .attribute = ColorAttribute::NoController,
928 .left = {},
929 .right = {},
930 };
931 shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
932 shared_memory_entry.applet_footer.type = AppletFooterUiType::None;
1019 933
1020 auto& controller = shared_memory_entries[npad_index]; 934 controller.is_connected = false;
1021 controller.style_set.raw = 0; // Zero out 935 controller.device->Disconnect();
1022 controller.device_type.raw = 0; 936 SignalStyleSetChangedEvent(npad_id);
1023 controller.system_properties.raw = 0; 937 WriteEmptyEntry(controller.shared_memory_entry);
1024 controller.button_properties.raw = 0; 938}
1025 controller.battery_level_dual = 0;
1026 controller.battery_level_left = 0;
1027 controller.battery_level_right = 0;
1028 controller.fullkey_color = {};
1029 controller.joycon_color = {};
1030 controller.assignment_mode = NpadAssignments::Dual;
1031 controller.footer_type = AppletFooterUiType::None;
1032 939
1033 SignalStyleSetChangedEvent(IndexToNPad(npad_index)); 940void Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
941 GyroscopeZeroDriftMode drift_mode) {
942 if (!IsDeviceHandleValid(sixaxis_handle)) {
943 LOG_ERROR(Service_HID, "Invalid handle");
944 return;
945 }
946 auto& controller = GetControllerFromHandle(sixaxis_handle);
947 controller.gyroscope_zero_drift_mode = drift_mode;
1034} 948}
1035 949
1036void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { 950Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode(
1037 gyroscope_zero_drift_mode = drift_mode; 951 Core::HID::SixAxisSensorHandle sixaxis_handle) const {
952 if (!IsDeviceHandleValid(sixaxis_handle)) {
953 LOG_ERROR(Service_HID, "Invalid handle");
954 // Return the default value
955 return GyroscopeZeroDriftMode::Standard;
956 }
957 const auto& controller = GetControllerFromHandle(sixaxis_handle);
958 return controller.gyroscope_zero_drift_mode;
1038} 959}
1039 960
1040Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const { 961bool Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const {
1041 return gyroscope_zero_drift_mode; 962 if (!IsDeviceHandleValid(sixaxis_handle)) {
963 LOG_ERROR(Service_HID, "Invalid handle");
964 // Return the default value
965 return true;
966 }
967 const auto& controller = GetControllerFromHandle(sixaxis_handle);
968 return controller.sixaxis_at_rest;
1042} 969}
1043 970
1044bool Controller_NPad::IsSixAxisSensorAtRest() const { 971void Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
1045 return sixaxis_at_rest; 972 bool sixaxis_status) {
973 if (!IsDeviceHandleValid(sixaxis_handle)) {
974 LOG_ERROR(Service_HID, "Invalid handle");
975 return;
976 }
977 auto& controller = GetControllerFromHandle(sixaxis_handle);
978 controller.sixaxis_sensor_enabled = sixaxis_status;
1046} 979}
1047 980
1048void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) { 981void Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
1049 sixaxis_sensors_enabled = six_axis_status; 982 bool sixaxis_fusion_status) {
983 if (!IsDeviceHandleValid(sixaxis_handle)) {
984 LOG_ERROR(Service_HID, "Invalid handle");
985 return;
986 }
987 auto& controller = GetControllerFromHandle(sixaxis_handle);
988 controller.sixaxis_fusion_enabled = sixaxis_fusion_status;
1050} 989}
1051 990
1052void Controller_NPad::SetSixAxisFusionParameters(f32 parameter1, f32 parameter2) { 991void Controller_NPad::SetSixAxisFusionParameters(
1053 sixaxis_fusion_parameter1 = parameter1; 992 Core::HID::SixAxisSensorHandle sixaxis_handle,
1054 sixaxis_fusion_parameter2 = parameter2; 993 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
994 if (!IsDeviceHandleValid(sixaxis_handle)) {
995 LOG_ERROR(Service_HID, "Invalid handle");
996 return;
997 }
998 auto& controller = GetControllerFromHandle(sixaxis_handle);
999 controller.sixaxis_fusion = sixaxis_fusion_parameters;
1055} 1000}
1056 1001
1057std::pair<f32, f32> Controller_NPad::GetSixAxisFusionParameters() { 1002Core::HID::SixAxisSensorFusionParameters Controller_NPad::GetSixAxisFusionParameters(
1058 return { 1003 Core::HID::SixAxisSensorHandle sixaxis_handle) {
1059 sixaxis_fusion_parameter1, 1004 if (!IsDeviceHandleValid(sixaxis_handle)) {
1060 sixaxis_fusion_parameter2, 1005 LOG_ERROR(Service_HID, "Invalid handle");
1061 }; 1006 // Since these parameters are unknow just return zeros
1007 return {};
1008 }
1009 auto& controller = GetControllerFromHandle(sixaxis_handle);
1010 return controller.sixaxis_fusion;
1062} 1011}
1063 1012
1064void Controller_NPad::ResetSixAxisFusionParameters() { 1013void Controller_NPad::ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle) {
1065 sixaxis_fusion_parameter1 = 0.0f; 1014 if (!IsDeviceHandleValid(sixaxis_handle)) {
1066 sixaxis_fusion_parameter2 = 0.0f; 1015 LOG_ERROR(Service_HID, "Invalid handle");
1016 return;
1017 }
1018 auto& controller = GetControllerFromHandle(sixaxis_handle);
1019 // Since these parameters are unknow just fill with zeros
1020 controller.sixaxis_fusion = {};
1067} 1021}
1068 1022
1069void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { 1023void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1070 const auto npad_index_1 = NPadIdToIndex(npad_id_1); 1024 Core::HID::NpadIdType npad_id_2) {
1071 const auto npad_index_2 = NPadIdToIndex(npad_id_2); 1025 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1026 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1027 npad_id_2);
1028 return;
1029 }
1030 auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
1031 auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
1072 1032
1073 // If the controllers at both npad indices form a pair of left and right joycons, merge them. 1033 // If the controllers at both npad indices form a pair of left and right joycons, merge them.
1074 // Otherwise, do nothing. 1034 // Otherwise, do nothing.
1075 if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft && 1035 if ((controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
1076 connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) || 1036 controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) ||
1077 (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && 1037 (controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
1078 connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { 1038 controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) {
1079 // Disconnect the joycon at the second id and connect the dual joycon at the first index. 1039 // Disconnect the joycon at the second id and connect the dual joycon at the first index.
1080 DisconnectNpad(npad_id_2); 1040 DisconnectNpad(npad_id_2);
1081 AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); 1041 AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
1082 } 1042 }
1083} 1043}
1084 1044
@@ -1092,61 +1052,61 @@ void Controller_NPad::StopLRAssignmentMode() {
1092 is_in_lr_assignment_mode = false; 1052 is_in_lr_assignment_mode = false;
1093} 1053}
1094 1054
1095bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { 1055bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1096 if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN || 1056 Core::HID::NpadIdType npad_id_2) {
1097 npad_id_2 == NPAD_UNKNOWN) { 1057 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1058 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1059 npad_id_2);
1060 return false;
1061 }
1062 if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
1063 npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
1064 npad_id_2 == Core::HID::NpadIdType::Other) {
1098 return true; 1065 return true;
1099 } 1066 }
1100 const auto npad_index_1 = NPadIdToIndex(npad_id_1); 1067 const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
1101 const auto npad_index_2 = NPadIdToIndex(npad_id_2); 1068 const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
1069 const auto type_index_1 = controller_1->GetNpadStyleIndex();
1070 const auto type_index_2 = controller_2->GetNpadStyleIndex();
1102 1071
1103 if (!IsControllerSupported(connected_controllers[npad_index_1].type) || 1072 if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) {
1104 !IsControllerSupported(connected_controllers[npad_index_2].type)) {
1105 return false; 1073 return false;
1106 } 1074 }
1107 1075
1108 std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); 1076 AddNewControllerAt(type_index_2, npad_id_1);
1109 1077 AddNewControllerAt(type_index_1, npad_id_2);
1110 AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
1111 AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
1112 1078
1113 return true; 1079 return true;
1114} 1080}
1115 1081
1116Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { 1082Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) {
1117 if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { 1083 if (!IsNpadIdValid(npad_id)) {
1118 // These are controllers without led patterns 1084 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1119 return LedPattern{0, 0, 0, 0}; 1085 return Core::HID::LedPattern{0, 0, 0, 0};
1120 }
1121 switch (npad_id) {
1122 case 0:
1123 return LedPattern{1, 0, 0, 0};
1124 case 1:
1125 return LedPattern{1, 1, 0, 0};
1126 case 2:
1127 return LedPattern{1, 1, 1, 0};
1128 case 3:
1129 return LedPattern{1, 1, 1, 1};
1130 case 4:
1131 return LedPattern{1, 0, 0, 1};
1132 case 5:
1133 return LedPattern{1, 0, 1, 0};
1134 case 6:
1135 return LedPattern{1, 0, 1, 1};
1136 case 7:
1137 return LedPattern{0, 1, 1, 0};
1138 default:
1139 return LedPattern{0, 0, 0, 0};
1140 } 1086 }
1087 const auto& controller = GetControllerFromNpadIdType(npad_id).device;
1088 return controller->GetLedPattern();
1141} 1089}
1142 1090
1143bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const { 1091bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
1144 return unintended_home_button_input_protection[NPadIdToIndex(npad_id)]; 1092 Core::HID::NpadIdType npad_id) const {
1093 if (!IsNpadIdValid(npad_id)) {
1094 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1095 // Return the default value
1096 return false;
1097 }
1098 const auto& controller = GetControllerFromNpadIdType(npad_id);
1099 return controller.unintended_home_button_input_protection;
1145} 1100}
1146 1101
1147void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, 1102void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
1148 u32 npad_id) { 1103 Core::HID::NpadIdType npad_id) {
1149 unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; 1104 if (!IsNpadIdValid(npad_id)) {
1105 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1106 return;
1107 }
1108 auto& controller = GetControllerFromNpadIdType(npad_id);
1109 controller.unintended_home_button_input_protection = is_protection_enabled;
1150} 1110}
1151 1111
1152void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { 1112void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
@@ -1154,32 +1114,34 @@ void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
1154} 1114}
1155 1115
1156void Controller_NPad::ClearAllConnectedControllers() { 1116void Controller_NPad::ClearAllConnectedControllers() {
1157 for (auto& controller : connected_controllers) { 1117 for (auto& controller : controller_data) {
1158 if (controller.is_connected && controller.type != NPadControllerType::None) { 1118 if (controller.device->IsConnected() &&
1159 controller.type = NPadControllerType::None; 1119 controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
1160 controller.is_connected = false; 1120 controller.device->Disconnect();
1121 controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
1161 } 1122 }
1162 } 1123 }
1163} 1124}
1164 1125
1165void Controller_NPad::DisconnectAllConnectedControllers() { 1126void Controller_NPad::DisconnectAllConnectedControllers() {
1166 for (auto& controller : connected_controllers) { 1127 for (auto& controller : controller_data) {
1167 controller.is_connected = false; 1128 controller.device->Disconnect();
1168 } 1129 }
1169} 1130}
1170 1131
1171void Controller_NPad::ConnectAllDisconnectedControllers() { 1132void Controller_NPad::ConnectAllDisconnectedControllers() {
1172 for (auto& controller : connected_controllers) { 1133 for (auto& controller : controller_data) {
1173 if (controller.type != NPadControllerType::None && !controller.is_connected) { 1134 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
1174 controller.is_connected = true; 1135 !controller.device->IsConnected()) {
1136 controller.device->Connect();
1175 } 1137 }
1176 } 1138 }
1177} 1139}
1178 1140
1179void Controller_NPad::ClearAllControllers() { 1141void Controller_NPad::ClearAllControllers() {
1180 for (auto& controller : connected_controllers) { 1142 for (auto& controller : controller_data) {
1181 controller.type = NPadControllerType::None; 1143 controller.device->Disconnect();
1182 controller.is_connected = false; 1144 controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
1183 } 1145 }
1184} 1146}
1185 1147
@@ -1187,16 +1149,16 @@ u32 Controller_NPad::GetAndResetPressState() {
1187 return press_state.exchange(0); 1149 return press_state.exchange(0);
1188} 1150}
1189 1151
1190bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { 1152bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
1191 if (controller == NPadControllerType::Handheld) { 1153 if (controller == Core::HID::NpadStyleIndex::Handheld) {
1192 const bool support_handheld = 1154 const bool support_handheld =
1193 std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 1155 std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
1194 NPAD_HANDHELD) != supported_npad_id_types.end(); 1156 Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end();
1195 // Handheld is not even a supported type, lets stop here 1157 // Handheld is not even a supported type, lets stop here
1196 if (!support_handheld) { 1158 if (!support_handheld) {
1197 return false; 1159 return false;
1198 } 1160 }
1199 // Handheld should not be supported in docked mode 1161 // Handheld shouldn't be supported in docked mode
1200 if (Settings::values.use_docked_mode.GetValue()) { 1162 if (Settings::values.use_docked_mode.GetValue()) {
1201 return false; 1163 return false;
1202 } 1164 }
@@ -1205,20 +1167,31 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1205 } 1167 }
1206 1168
1207 if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), 1169 if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
1208 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { 1170 [](Core::HID::NpadIdType npad_id) {
1171 return npad_id <= Core::HID::NpadIdType::Player8;
1172 })) {
1173 Core::HID::NpadStyleTag style = GetSupportedStyleSet();
1209 switch (controller) { 1174 switch (controller) {
1210 case NPadControllerType::ProController: 1175 case Core::HID::NpadStyleIndex::ProController:
1211 return style.fullkey; 1176 return style.fullkey;
1212 case NPadControllerType::JoyDual: 1177 case Core::HID::NpadStyleIndex::JoyconDual:
1213 return style.joycon_dual; 1178 return style.joycon_dual;
1214 case NPadControllerType::JoyLeft: 1179 case Core::HID::NpadStyleIndex::JoyconLeft:
1215 return style.joycon_left; 1180 return style.joycon_left;
1216 case NPadControllerType::JoyRight: 1181 case Core::HID::NpadStyleIndex::JoyconRight:
1217 return style.joycon_right; 1182 return style.joycon_right;
1218 case NPadControllerType::GameCube: 1183 case Core::HID::NpadStyleIndex::GameCube:
1219 return style.gamecube; 1184 return style.gamecube;
1220 case NPadControllerType::Pokeball: 1185 case Core::HID::NpadStyleIndex::Pokeball:
1221 return style.palma; 1186 return style.palma;
1187 case Core::HID::NpadStyleIndex::NES:
1188 return style.lark;
1189 case Core::HID::NpadStyleIndex::SNES:
1190 return style.lucia;
1191 case Core::HID::NpadStyleIndex::N64:
1192 return style.lagoon;
1193 case Core::HID::NpadStyleIndex::SegaGenesis:
1194 return style.lager;
1222 default: 1195 default:
1223 return false; 1196 return false;
1224 } 1197 }
@@ -1227,4 +1200,48 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1227 return false; 1200 return false;
1228} 1201}
1229 1202
1203Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
1204 const Core::HID::SixAxisSensorHandle& device_handle) {
1205 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1206 return GetControllerFromNpadIdType(npad_id);
1207}
1208
1209const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
1210 const Core::HID::SixAxisSensorHandle& device_handle) const {
1211 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1212 return GetControllerFromNpadIdType(npad_id);
1213}
1214
1215Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
1216 const Core::HID::VibrationDeviceHandle& device_handle) {
1217 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1218 return GetControllerFromNpadIdType(npad_id);
1219}
1220
1221const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
1222 const Core::HID::VibrationDeviceHandle& device_handle) const {
1223 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1224 return GetControllerFromNpadIdType(npad_id);
1225}
1226
1227Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
1228 Core::HID::NpadIdType npad_id) {
1229 if (!IsNpadIdValid(npad_id)) {
1230 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1231 npad_id = Core::HID::NpadIdType::Player1;
1232 }
1233 const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
1234 return controller_data[npad_index];
1235}
1236
1237const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
1238 Core::HID::NpadIdType npad_id) const {
1239 if (!IsNpadIdValid(npad_id)) {
1240 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1241 npad_id = Core::HID::NpadIdType::Player1;
1242 }
1243 const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
1244 return controller_data[npad_index];
1245}
1246
1230} // namespace Service::HID 1247} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 9ee146caf..9fa113bb6 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -11,9 +11,14 @@
11#include "common/bit_field.h" 11#include "common/bit_field.h"
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/quaternion.h" 13#include "common/quaternion.h"
14#include "common/settings.h" 14#include "core/hid/hid_types.h"
15#include "core/frontend/input.h"
16#include "core/hle/service/hid/controllers/controller_base.h" 15#include "core/hle/service/hid/controllers/controller_base.h"
16#include "core/hle/service/hid/ring_lifo.h"
17
18namespace Core::HID {
19class EmulatedController;
20enum class ControllerTriggerType;
21} // namespace Core::HID
17 22
18namespace Kernel { 23namespace Kernel {
19class KEvent; 24class KEvent;
@@ -26,12 +31,9 @@ class ServiceContext;
26 31
27namespace Service::HID { 32namespace Service::HID {
28 33
29constexpr u32 NPAD_HANDHELD = 32;
30constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this?
31
32class Controller_NPad final : public ControllerBase { 34class Controller_NPad final : public ControllerBase {
33public: 35public:
34 explicit Controller_NPad(Core::System& system_, 36 explicit Controller_NPad(Core::HID::HIDCore& hid_core_,
35 KernelHelpers::ServiceContext& service_context_); 37 KernelHelpers::ServiceContext& service_context_);
36 ~Controller_NPad() override; 38 ~Controller_NPad() override;
37 39
@@ -48,60 +50,39 @@ public:
48 void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 50 void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
49 std::size_t size) override; 51 std::size_t size) override;
50 52
51 // Called when input devices should be loaded 53 // This is nn::hid::GyroscopeZeroDriftMode
52 void OnLoadInputDevices() override;
53
54 enum class NPadControllerType {
55 None,
56 ProController,
57 Handheld,
58 JoyDual,
59 JoyLeft,
60 JoyRight,
61 GameCube,
62 Pokeball,
63 };
64
65 enum class NpadType : u8 {
66 ProController = 3,
67 Handheld = 4,
68 JoyconDual = 5,
69 JoyconLeft = 6,
70 JoyconRight = 7,
71 GameCube = 8,
72 Pokeball = 9,
73 MaxNpadType = 10,
74 };
75
76 enum class DeviceIndex : u8 {
77 Left = 0,
78 Right = 1,
79 None = 2,
80 MaxDeviceIndex = 3,
81 };
82
83 enum class GyroscopeZeroDriftMode : u32 { 54 enum class GyroscopeZeroDriftMode : u32 {
84 Loose = 0, 55 Loose = 0,
85 Standard = 1, 56 Standard = 1,
86 Tight = 2, 57 Tight = 2,
87 }; 58 };
88 59
89 enum class NpadHoldType : u64 { 60 // This is nn::hid::NpadJoyHoldType
61 enum class NpadJoyHoldType : u64 {
90 Vertical = 0, 62 Vertical = 0,
91 Horizontal = 1, 63 Horizontal = 1,
92 }; 64 };
93 65
94 enum class NpadAssignments : u32 { 66 // This is nn::hid::NpadJoyAssignmentMode
67 enum class NpadJoyAssignmentMode : u32 {
95 Dual = 0, 68 Dual = 0,
96 Single = 1, 69 Single = 1,
97 }; 70 };
98 71
72 // This is nn::hid::NpadJoyDeviceType
73 enum class NpadJoyDeviceType : s64 {
74 Left = 0,
75 Right = 1,
76 };
77
78 // This is nn::hid::NpadHandheldActivationMode
99 enum class NpadHandheldActivationMode : u64 { 79 enum class NpadHandheldActivationMode : u64 {
100 Dual = 0, 80 Dual = 0,
101 Single = 1, 81 Single = 1,
102 None = 2, 82 None = 2,
103 }; 83 };
104 84
85 // This is nn::hid::NpadCommunicationMode
105 enum class NpadCommunicationMode : u64 { 86 enum class NpadCommunicationMode : u64 {
106 Mode_5ms = 0, 87 Mode_5ms = 0,
107 Mode_10ms = 1, 88 Mode_10ms = 1,
@@ -109,74 +90,22 @@ public:
109 Default = 3, 90 Default = 3,
110 }; 91 };
111 92
112 struct DeviceHandle { 93 static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{
113 NpadType npad_type; 94 .low_amplitude = 0.0f,
114 u8 npad_id; 95 .low_frequency = 160.0f,
115 DeviceIndex device_index; 96 .high_amplitude = 0.0f,
116 INSERT_PADDING_BYTES_NOINIT(1); 97 .high_frequency = 320.0f,
117 }; 98 };
118 static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size");
119 99
120 struct NpadStyleSet { 100 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
121 union { 101 Core::HID::NpadStyleTag GetSupportedStyleSet() const;
122 u32_le raw{};
123
124 BitField<0, 1, u32> fullkey;
125 BitField<1, 1, u32> handheld;
126 BitField<2, 1, u32> joycon_dual;
127 BitField<3, 1, u32> joycon_left;
128 BitField<4, 1, u32> joycon_right;
129 BitField<5, 1, u32> gamecube;
130 BitField<6, 1, u32> palma;
131 BitField<7, 1, u32> lark;
132 BitField<8, 1, u32> handheld_lark;
133 BitField<9, 1, u32> lucia;
134 BitField<29, 1, u32> system_ext;
135 BitField<30, 1, u32> system;
136 };
137 };
138 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
139
140 struct VibrationValue {
141 f32 amp_low;
142 f32 freq_low;
143 f32 amp_high;
144 f32 freq_high;
145 };
146 static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size");
147
148 static constexpr VibrationValue DEFAULT_VIBRATION_VALUE{
149 .amp_low = 0.0f,
150 .freq_low = 160.0f,
151 .amp_high = 0.0f,
152 .freq_high = 320.0f,
153 };
154
155 struct LedPattern {
156 explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
157 position1.Assign(light1);
158 position2.Assign(light2);
159 position3.Assign(light3);
160 position4.Assign(light4);
161 }
162 union {
163 u64 raw{};
164 BitField<0, 1, u64> position1;
165 BitField<1, 1, u64> position2;
166 BitField<2, 1, u64> position3;
167 BitField<3, 1, u64> position4;
168 };
169 };
170
171 void SetSupportedStyleSet(NpadStyleSet style_set);
172 NpadStyleSet GetSupportedStyleSet() const;
173 102
174 void SetSupportedNpadIdTypes(u8* data, std::size_t length); 103 void SetSupportedNpadIdTypes(u8* data, std::size_t length);
175 void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); 104 void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
176 std::size_t GetSupportedNpadIdTypesSize() const; 105 std::size_t GetSupportedNpadIdTypesSize() const;
177 106
178 void SetHoldType(NpadHoldType joy_hold_type); 107 void SetHoldType(NpadJoyHoldType joy_hold_type);
179 NpadHoldType GetHoldType() const; 108 NpadJoyHoldType GetHoldType() const;
180 109
181 void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); 110 void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode);
182 NpadHandheldActivationMode GetNpadHandheldActivationMode() const; 111 NpadHandheldActivationMode GetNpadHandheldActivationMode() const;
@@ -184,162 +113,106 @@ public:
184 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); 113 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
185 NpadCommunicationMode GetNpadCommunicationMode() const; 114 NpadCommunicationMode GetNpadCommunicationMode() const;
186 115
187 void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); 116 void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyAssignmentMode assignment_mode);
188 117
189 bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, 118 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
190 const VibrationValue& vibration_value); 119 const Core::HID::VibrationValue& vibration_value);
191 120
192 void VibrateController(const DeviceHandle& vibration_device_handle, 121 void VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle,
193 const VibrationValue& vibration_value); 122 const Core::HID::VibrationValue& vibration_value);
194 123
195 void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, 124 void VibrateControllers(
196 const std::vector<VibrationValue>& vibration_values); 125 const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
126 const std::vector<Core::HID::VibrationValue>& vibration_values);
197 127
198 VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; 128 Core::HID::VibrationValue GetLastVibration(
129 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
199 130
200 void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle); 131 void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle);
201 132
202 void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); 133 void InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index);
203 134
204 void SetPermitVibrationSession(bool permit_vibration_session); 135 void SetPermitVibrationSession(bool permit_vibration_session);
205 136
206 bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; 137 bool IsVibrationDeviceMounted(
138 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
207 139
208 Kernel::KReadableEvent& GetStyleSetChangedEvent(u32 npad_id); 140 Kernel::KReadableEvent& GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id);
209 void SignalStyleSetChangedEvent(u32 npad_id) const; 141 void SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const;
210 142
211 // Adds a new controller at an index. 143 // Adds a new controller at an index.
212 void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); 144 void AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id);
213 // Adds a new controller at an index with connection status. 145 // Adds a new controller at an index with connection status.
214 void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); 146 void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id,
215 147 bool connected);
216 void DisconnectNpad(u32 npad_id); 148
217 void DisconnectNpadAtIndex(std::size_t index); 149 void DisconnectNpad(Core::HID::NpadIdType npad_id);
218 150
219 void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); 151 void SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
220 GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; 152 GyroscopeZeroDriftMode drift_mode);
221 bool IsSixAxisSensorAtRest() const; 153 GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode(
222 void SetSixAxisEnabled(bool six_axis_status); 154 Core::HID::SixAxisSensorHandle sixaxis_handle) const;
223 void SetSixAxisFusionParameters(f32 parameter1, f32 parameter2); 155 bool IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const;
224 std::pair<f32, f32> GetSixAxisFusionParameters(); 156 void SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle, bool sixaxis_status);
225 void ResetSixAxisFusionParameters(); 157 void SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
226 LedPattern GetLedPattern(u32 npad_id); 158 bool sixaxis_fusion_status);
227 bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; 159 void SetSixAxisFusionParameters(
228 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); 160 Core::HID::SixAxisSensorHandle sixaxis_handle,
161 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
162 Core::HID::SixAxisSensorFusionParameters GetSixAxisFusionParameters(
163 Core::HID::SixAxisSensorHandle sixaxis_handle);
164 void ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle);
165 Core::HID::LedPattern GetLedPattern(Core::HID::NpadIdType npad_id);
166 bool IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id) const;
167 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
168 Core::HID::NpadIdType npad_id);
229 void SetAnalogStickUseCenterClamp(bool use_center_clamp); 169 void SetAnalogStickUseCenterClamp(bool use_center_clamp);
230 void ClearAllConnectedControllers(); 170 void ClearAllConnectedControllers();
231 void DisconnectAllConnectedControllers(); 171 void DisconnectAllConnectedControllers();
232 void ConnectAllDisconnectedControllers(); 172 void ConnectAllDisconnectedControllers();
233 void ClearAllControllers(); 173 void ClearAllControllers();
234 174
235 void MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2); 175 void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
236 void StartLRAssignmentMode(); 176 void StartLRAssignmentMode();
237 void StopLRAssignmentMode(); 177 void StopLRAssignmentMode();
238 bool SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2); 178 bool SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
239 179
240 // Logical OR for all buttons presses on all controllers 180 // Logical OR for all buttons presses on all controllers
241 // Specifically for cheat engine and other features. 181 // Specifically for cheat engine and other features.
242 u32 GetAndResetPressState(); 182 u32 GetAndResetPressState();
243 183
244 static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); 184 static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
245 static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); 185 static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle);
246 static std::size_t NPadIdToIndex(u32 npad_id); 186 static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
247 static u32 IndexToNPad(std::size_t index);
248 static bool IsNpadIdValid(u32 npad_id);
249 static bool IsDeviceHandleValid(const DeviceHandle& device_handle);
250 187
251private: 188private:
252 struct CommonHeader { 189 // This is nn::hid::detail::ColorAttribute
253 s64_le timestamp; 190 enum class ColorAttribute : u32 {
254 s64_le total_entry_count;
255 s64_le last_entry_index;
256 s64_le entry_count;
257 };
258 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
259
260 enum class ColorAttributes : u32_le {
261 Ok = 0, 191 Ok = 0,
262 ReadError = 1, 192 ReadError = 1,
263 NoController = 2, 193 NoController = 2,
264 }; 194 };
265 static_assert(sizeof(ColorAttributes) == 4, "ColorAttributes is an invalid size"); 195 static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
266 196
267 struct ControllerColor { 197 // This is nn::hid::detail::NpadFullKeyColorState
268 u32_le body; 198 struct NpadFullKeyColorState {
269 u32_le button; 199 ColorAttribute attribute;
200 Core::HID::NpadControllerColor fullkey;
270 }; 201 };
271 static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size"); 202 static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
272 203
273 struct FullKeyColor { 204 // This is nn::hid::detail::NpadJoyColorState
274 ColorAttributes attribute; 205 struct NpadJoyColorState {
275 ControllerColor fullkey; 206 ColorAttribute attribute;
207 Core::HID::NpadControllerColor left;
208 Core::HID::NpadControllerColor right;
276 }; 209 };
277 static_assert(sizeof(FullKeyColor) == 0xC, "FullKeyColor is an invalid size"); 210 static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
278 211
279 struct JoyconColor { 212 // This is nn::hid::NpadAttribute
280 ColorAttributes attribute; 213 struct NpadAttribute {
281 ControllerColor left;
282 ControllerColor right;
283 };
284 static_assert(sizeof(JoyconColor) == 0x14, "JoyconColor is an invalid size");
285
286 struct ControllerPadState {
287 union {
288 u64_le raw{};
289 // Button states
290 BitField<0, 1, u64> a;
291 BitField<1, 1, u64> b;
292 BitField<2, 1, u64> x;
293 BitField<3, 1, u64> y;
294 BitField<4, 1, u64> l_stick;
295 BitField<5, 1, u64> r_stick;
296 BitField<6, 1, u64> l;
297 BitField<7, 1, u64> r;
298 BitField<8, 1, u64> zl;
299 BitField<9, 1, u64> zr;
300 BitField<10, 1, u64> plus;
301 BitField<11, 1, u64> minus;
302
303 // D-Pad
304 BitField<12, 1, u64> d_left;
305 BitField<13, 1, u64> d_up;
306 BitField<14, 1, u64> d_right;
307 BitField<15, 1, u64> d_down;
308
309 // Left JoyStick
310 BitField<16, 1, u64> l_stick_left;
311 BitField<17, 1, u64> l_stick_up;
312 BitField<18, 1, u64> l_stick_right;
313 BitField<19, 1, u64> l_stick_down;
314
315 // Right JoyStick
316 BitField<20, 1, u64> r_stick_left;
317 BitField<21, 1, u64> r_stick_up;
318 BitField<22, 1, u64> r_stick_right;
319 BitField<23, 1, u64> r_stick_down;
320
321 // Not always active?
322 BitField<24, 1, u64> left_sl;
323 BitField<25, 1, u64> left_sr;
324
325 BitField<26, 1, u64> right_sl;
326 BitField<27, 1, u64> right_sr;
327
328 BitField<28, 1, u64> palma;
329 BitField<30, 1, u64> handheld_left_b;
330 };
331 };
332 static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
333
334 struct AnalogPosition {
335 s32_le x;
336 s32_le y;
337 };
338 static_assert(sizeof(AnalogPosition) == 8, "AnalogPosition is an invalid size");
339
340 struct ConnectionState {
341 union { 214 union {
342 u32_le raw{}; 215 u32 raw{};
343 BitField<0, 1, u32> is_connected; 216 BitField<0, 1, u32> is_connected;
344 BitField<1, 1, u32> is_wired; 217 BitField<1, 1, u32> is_wired;
345 BitField<2, 1, u32> is_left_connected; 218 BitField<2, 1, u32> is_left_connected;
@@ -348,79 +221,60 @@ private:
348 BitField<5, 1, u32> is_right_wired; 221 BitField<5, 1, u32> is_right_wired;
349 }; 222 };
350 }; 223 };
351 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); 224 static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
352 225
353 struct ControllerPad { 226 // This is nn::hid::NpadFullKeyState
354 ControllerPadState pad_states; 227 // This is nn::hid::NpadHandheldState
355 AnalogPosition l_stick; 228 // This is nn::hid::NpadJoyDualState
356 AnalogPosition r_stick; 229 // This is nn::hid::NpadJoyLeftState
357 }; 230 // This is nn::hid::NpadJoyRightState
358 static_assert(sizeof(ControllerPad) == 0x18, "ControllerPad is an invalid size"); 231 // This is nn::hid::NpadPalmaState
359 232 // This is nn::hid::NpadSystemExtState
360 struct GenericStates { 233 struct NPadGenericState {
361 s64_le timestamp; 234 s64_le sampling_number;
362 s64_le timestamp2; 235 Core::HID::NpadButtonState npad_buttons;
363 ControllerPad pad; 236 Core::HID::AnalogStickState l_stick;
364 ConnectionState connection_status; 237 Core::HID::AnalogStickState r_stick;
365 }; 238 NpadAttribute connection_status;
366 static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size"); 239 INSERT_PADDING_BYTES(4); // Reserved
367
368 struct NPadGeneric {
369 CommonHeader common;
370 std::array<GenericStates, 17> npad;
371 }; 240 };
372 static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); 241 static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
373 242
374 struct SixAxisAttributes { 243 // This is nn::hid::SixAxisSensorAttribute
244 struct SixAxisSensorAttribute {
375 union { 245 union {
376 u32_le raw{}; 246 u32 raw{};
377 BitField<0, 1, u32> is_connected; 247 BitField<0, 1, u32> is_connected;
378 BitField<1, 1, u32> is_interpolated; 248 BitField<1, 1, u32> is_interpolated;
379 }; 249 };
380 }; 250 };
381 static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size"); 251 static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
382 252
383 struct SixAxisStates { 253 // This is nn::hid::SixAxisSensorState
384 s64_le timestamp{}; 254 struct SixAxisSensorState {
385 INSERT_PADDING_WORDS(2); 255 s64 delta_time{};
386 s64_le timestamp2{}; 256 s64 sampling_number{};
387 Common::Vec3f accel{}; 257 Common::Vec3f accel{};
388 Common::Vec3f gyro{}; 258 Common::Vec3f gyro{};
389 Common::Vec3f rotation{}; 259 Common::Vec3f rotation{};
390 std::array<Common::Vec3f, 3> orientation{}; 260 std::array<Common::Vec3f, 3> orientation{};
391 SixAxisAttributes attribute; 261 SixAxisSensorAttribute attribute;
392 INSERT_PADDING_BYTES(4); // Reserved 262 INSERT_PADDING_BYTES(4); // Reserved
393 }; 263 };
394 static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size"); 264 static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
395
396 struct SixAxisGeneric {
397 CommonHeader common{};
398 std::array<SixAxisStates, 17> sixaxis{};
399 };
400 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
401 265
402 struct TriggerState { 266 // This is nn::hid::server::NpadGcTriggerState
403 s64_le timestamp{}; 267 struct NpadGcTriggerState {
404 s64_le timestamp2{}; 268 s64 sampling_number{};
405 s32_le l_analog{}; 269 s32 l_analog{};
406 s32_le r_analog{}; 270 s32 r_analog{};
407 }; 271 };
408 static_assert(sizeof(TriggerState) == 0x18, "TriggerState is an invalid size"); 272 static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
409
410 struct TriggerGeneric {
411 INSERT_PADDING_BYTES(0x4);
412 s64_le timestamp;
413 INSERT_PADDING_BYTES(0x4);
414 s64_le total_entry_count;
415 s64_le last_entry_index;
416 s64_le entry_count;
417 std::array<TriggerState, 17> trigger{};
418 };
419 static_assert(sizeof(TriggerGeneric) == 0x1C8, "TriggerGeneric is an invalid size");
420 273
274 // This is nn::hid::NpadSystemProperties
421 struct NPadSystemProperties { 275 struct NPadSystemProperties {
422 union { 276 union {
423 s64_le raw{}; 277 s64 raw{};
424 BitField<0, 1, s64> is_charging_joy_dual; 278 BitField<0, 1, s64> is_charging_joy_dual;
425 BitField<1, 1, s64> is_charging_joy_left; 279 BitField<1, 1, s64> is_charging_joy_left;
426 BitField<2, 1, s64> is_charging_joy_right; 280 BitField<2, 1, s64> is_charging_joy_right;
@@ -438,17 +292,20 @@ private:
438 }; 292 };
439 static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); 293 static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
440 294
441 struct NPadButtonProperties { 295 // This is nn::hid::NpadSystemButtonProperties
296 struct NpadSystemButtonProperties {
442 union { 297 union {
443 s32_le raw{}; 298 s32 raw{};
444 BitField<0, 1, s32> is_home_button_protection_enabled; 299 BitField<0, 1, s32> is_home_button_protection_enabled;
445 }; 300 };
446 }; 301 };
447 static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size"); 302 static_assert(sizeof(NpadSystemButtonProperties) == 0x4,
303 "NPadButtonProperties is an invalid size");
448 304
449 struct NPadDevice { 305 // This is nn::hid::system::DeviceType
306 struct DeviceType {
450 union { 307 union {
451 u32_le raw{}; 308 u32 raw{};
452 BitField<0, 1, s32> fullkey; 309 BitField<0, 1, s32> fullkey;
453 BitField<1, 1, s32> debug_pad; 310 BitField<1, 1, s32> debug_pad;
454 BitField<2, 1, s32> handheld_left; 311 BitField<2, 1, s32> handheld_left;
@@ -465,26 +322,29 @@ private:
465 BitField<13, 1, s32> handheld_lark_nes_left; 322 BitField<13, 1, s32> handheld_lark_nes_left;
466 BitField<14, 1, s32> handheld_lark_nes_right; 323 BitField<14, 1, s32> handheld_lark_nes_right;
467 BitField<15, 1, s32> lucia; 324 BitField<15, 1, s32> lucia;
325 BitField<16, 1, s32> lagon;
326 BitField<17, 1, s32> lager;
468 BitField<31, 1, s32> system; 327 BitField<31, 1, s32> system;
469 }; 328 };
470 }; 329 };
471 330
472 struct MotionDevice { 331 // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
473 Common::Vec3f accel; 332 struct NfcXcdDeviceHandleStateImpl {
474 Common::Vec3f gyro; 333 u64 handle;
475 Common::Vec3f rotation; 334 bool is_available;
476 std::array<Common::Vec3f, 3> orientation; 335 bool is_activated;
477 Common::Quaternion<f32> quaternion; 336 INSERT_PADDING_BYTES(0x6); // Reserved
478 }; 337 u64 sampling_number;
479
480 struct NfcXcdHandle {
481 INSERT_PADDING_BYTES(0x60);
482 }; 338 };
339 static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
340 "NfcXcdDeviceHandleStateImpl is an invalid size");
483 341
342 // This is nn::hid::system::AppletFooterUiAttributesSet
484 struct AppletFooterUiAttributes { 343 struct AppletFooterUiAttributes {
485 INSERT_PADDING_BYTES(0x4); 344 INSERT_PADDING_BYTES(0x4);
486 }; 345 };
487 346
347 // This is nn::hid::system::AppletFooterUiType
488 enum class AppletFooterUiType : u8 { 348 enum class AppletFooterUiType : u8 {
489 None = 0, 349 None = 0,
490 HandheldNone = 1, 350 HandheldNone = 1,
@@ -510,95 +370,150 @@ private:
510 Lagon = 21, 370 Lagon = 21,
511 }; 371 };
512 372
513 struct NPadEntry { 373 struct AppletFooterUi {
514 NpadStyleSet style_set; 374 AppletFooterUiAttributes attributes;
515 NpadAssignments assignment_mode; 375 AppletFooterUiType type;
516 FullKeyColor fullkey_color; 376 INSERT_PADDING_BYTES(0x5B); // Reserved
517 JoyconColor joycon_color; 377 };
518 378 static_assert(sizeof(AppletFooterUi) == 0x60, "AppletFooterUi is an invalid size");
519 NPadGeneric fullkey_states; 379
520 NPadGeneric handheld_states; 380 // This is nn::hid::NpadLarkType
521 NPadGeneric joy_dual_states; 381 enum class NpadLarkType : u32 {
522 NPadGeneric joy_left_states; 382 Invalid,
523 NPadGeneric joy_right_states; 383 H1,
524 NPadGeneric palma_states; 384 H2,
525 NPadGeneric system_ext_states; 385 NL,
526 SixAxisGeneric sixaxis_fullkey; 386 NR,
527 SixAxisGeneric sixaxis_handheld; 387 };
528 SixAxisGeneric sixaxis_dual_left; 388
529 SixAxisGeneric sixaxis_dual_right; 389 // This is nn::hid::NpadLuciaType
530 SixAxisGeneric sixaxis_left; 390 enum class NpadLuciaType : u32 {
531 SixAxisGeneric sixaxis_right; 391 Invalid,
532 NPadDevice device_type; 392 J,
533 INSERT_PADDING_BYTES(0x4); // reserved 393 E,
394 U,
395 };
396
397 // This is nn::hid::NpadLagonType
398 enum class NpadLagonType : u32 {
399 Invalid,
400 };
401
402 // This is nn::hid::NpadLagerType
403 enum class NpadLagerType : u32 {
404 Invalid,
405 J,
406 E,
407 U,
408 };
409
410 // This is nn::hid::detail::NpadInternalState
411 struct NpadInternalState {
412 Core::HID::NpadStyleTag style_tag;
413 NpadJoyAssignmentMode assignment_mode;
414 NpadFullKeyColorState fullkey_color;
415 NpadJoyColorState joycon_color;
416 Lifo<NPadGenericState, hid_entry_count> fullkey_lifo;
417 Lifo<NPadGenericState, hid_entry_count> handheld_lifo;
418 Lifo<NPadGenericState, hid_entry_count> joy_dual_lifo;
419 Lifo<NPadGenericState, hid_entry_count> joy_left_lifo;
420 Lifo<NPadGenericState, hid_entry_count> joy_right_lifo;
421 Lifo<NPadGenericState, hid_entry_count> palma_lifo;
422 Lifo<NPadGenericState, hid_entry_count> system_ext_lifo;
423 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo;
424 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo;
425 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo;
426 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo;
427 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_left_lifo;
428 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_right_lifo;
429 DeviceType device_type;
430 INSERT_PADDING_BYTES(0x4); // Reserved
534 NPadSystemProperties system_properties; 431 NPadSystemProperties system_properties;
535 NPadButtonProperties button_properties; 432 NpadSystemButtonProperties button_properties;
536 u32 battery_level_dual; 433 Core::HID::NpadBatteryLevel battery_level_dual;
537 u32 battery_level_left; 434 Core::HID::NpadBatteryLevel battery_level_left;
538 u32 battery_level_right; 435 Core::HID::NpadBatteryLevel battery_level_right;
539 AppletFooterUiAttributes footer_attributes; 436 union {
540 AppletFooterUiType footer_type; 437 Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo{};
541 // nfc_states needs to be checked switchbrew does not match with HW 438 AppletFooterUi applet_footer;
542 NfcXcdHandle nfc_states; 439 };
543 INSERT_PADDING_BYTES(0x8); // Mutex 440 INSERT_PADDING_BYTES(0x20); // Unknown
544 TriggerGeneric gc_trigger_states; 441 Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo;
545 INSERT_PADDING_BYTES(0xc1f); 442 NpadLarkType lark_type_l_and_main;
546 }; 443 NpadLarkType lark_type_r;
547 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); 444 NpadLuciaType lucia_type;
548 445 NpadLagonType lagon_type;
549 struct ControllerHolder { 446 NpadLagerType lager_type;
550 NPadControllerType type; 447 // FW 13.x Investigate there is some sort of bitflag related to joycons
551 bool is_connected; 448 INSERT_PADDING_BYTES(0x4);
552 }; 449 INSERT_PADDING_BYTES(0xc08); // Unknown
553 450 };
554 void InitNewlyAddedController(std::size_t controller_idx); 451 static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
555 bool IsControllerSupported(NPadControllerType controller) const; 452
556 void RequestPadStateUpdate(u32 npad_id); 453 struct VibrationData {
454 bool device_mounted{};
455 Core::HID::VibrationValue latest_vibration_value{};
456 std::chrono::steady_clock::time_point last_vibration_timepoint{};
457 };
458
459 struct NpadControllerData {
460 Core::HID::EmulatedController* device;
461 Kernel::KEvent* styleset_changed_event{};
462 NpadInternalState shared_memory_entry{};
463
464 std::array<VibrationData, 2> vibration{};
465 bool unintended_home_button_input_protection{};
466 bool is_connected{};
467 Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None};
468
469 // Motion parameters
470 bool sixaxis_at_rest{true};
471 bool sixaxis_sensor_enabled{true};
472 bool sixaxis_fusion_enabled{false};
473 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion{};
474 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
475
476 // Current pad state
477 NPadGenericState npad_pad_state{};
478 NPadGenericState npad_libnx_state{};
479 NpadGcTriggerState npad_trigger_state{};
480 SixAxisSensorState sixaxis_fullkey_state{};
481 SixAxisSensorState sixaxis_handheld_state{};
482 SixAxisSensorState sixaxis_dual_left_state{};
483 SixAxisSensorState sixaxis_dual_right_state{};
484 SixAxisSensorState sixaxis_left_lifo_state{};
485 SixAxisSensorState sixaxis_right_lifo_state{};
486 int callback_key;
487 };
488
489 void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx);
490 void InitNewlyAddedController(Core::HID::NpadIdType npad_id);
491 bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const;
492 void RequestPadStateUpdate(Core::HID::NpadIdType npad_id);
493 void WriteEmptyEntry(NpadInternalState& npad);
494
495 NpadControllerData& GetControllerFromHandle(
496 const Core::HID::SixAxisSensorHandle& device_handle);
497 const NpadControllerData& GetControllerFromHandle(
498 const Core::HID::SixAxisSensorHandle& device_handle) const;
499 NpadControllerData& GetControllerFromHandle(
500 const Core::HID::VibrationDeviceHandle& device_handle);
501 const NpadControllerData& GetControllerFromHandle(
502 const Core::HID::VibrationDeviceHandle& device_handle) const;
503 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
504 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
557 505
558 std::atomic<u32> press_state{}; 506 std::atomic<u32> press_state{};
559 507
560 NpadStyleSet style{}; 508 std::array<NpadControllerData, 10> controller_data{};
561 std::array<NPadEntry, 10> shared_memory_entries{};
562 using ButtonArray = std::array<
563 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
564 10>;
565 using StickArray = std::array<
566 std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
567 10>;
568 using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>,
569 Settings::NativeVibration::NUM_VIBRATIONS_HID>,
570 10>;
571 using MotionArray = std::array<
572 std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>,
573 10>;
574
575 KernelHelpers::ServiceContext& service_context; 509 KernelHelpers::ServiceContext& service_context;
576 std::mutex mutex; 510 std::mutex mutex;
577 ButtonArray buttons; 511 std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
578 StickArray sticks; 512 NpadJoyHoldType hold_type{NpadJoyHoldType::Vertical};
579 VibrationArray vibrations;
580 MotionArray motions;
581 std::vector<u32> supported_npad_id_types{};
582 NpadHoldType hold_type{NpadHoldType::Vertical};
583 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; 513 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
584 NpadCommunicationMode communication_mode{NpadCommunicationMode::Default}; 514 NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
585 // Each controller should have their own styleset changed event
586 std::array<Kernel::KEvent*, 10> styleset_changed_events{};
587 std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10>
588 last_vibration_timepoints{};
589 std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
590 bool permit_vibration_session_enabled{false}; 515 bool permit_vibration_session_enabled{false};
591 std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
592 std::array<ControllerHolder, 10> connected_controllers{};
593 std::array<bool, 10> unintended_home_button_input_protection{};
594 bool analog_stick_use_center_clamp{}; 516 bool analog_stick_use_center_clamp{};
595 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
596 bool sixaxis_sensors_enabled{true};
597 f32 sixaxis_fusion_parameter1{};
598 f32 sixaxis_fusion_parameter2{};
599 bool sixaxis_at_rest{true};
600 std::array<ControllerPad, 10> npad_pad_states{};
601 std::array<TriggerState, 10> npad_trigger_states{};
602 bool is_in_lr_assignment_mode{false}; 517 bool is_in_lr_assignment_mode{false};
603}; 518};
604} // namespace Service::HID 519} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp
index 772c20453..b7d7a5756 100644
--- a/src/core/hle/service/hid/controllers/stubbed.cpp
+++ b/src/core/hle/service/hid/controllers/stubbed.cpp
@@ -5,11 +5,12 @@
5#include <cstring> 5#include <cstring>
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/stubbed.h" 9#include "core/hle/service/hid/controllers/stubbed.h"
9 10
10namespace Service::HID { 11namespace Service::HID {
11 12
12Controller_Stubbed::Controller_Stubbed(Core::System& system_) : ControllerBase{system_} {} 13Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {}
13Controller_Stubbed::~Controller_Stubbed() = default; 14Controller_Stubbed::~Controller_Stubbed() = default;
14 15
15void Controller_Stubbed::OnInit() {} 16void Controller_Stubbed::OnInit() {}
@@ -31,10 +32,9 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
31 std::memcpy(data + common_offset, &header, sizeof(CommonHeader)); 32 std::memcpy(data + common_offset, &header, sizeof(CommonHeader));
32} 33}
33 34
34void Controller_Stubbed::OnLoadInputDevices() {}
35
36void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) { 35void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
37 common_offset = off; 36 common_offset = off;
38 smart_update = true; 37 smart_update = true;
39} 38}
39
40} // namespace Service::HID 40} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 21092af0d..0044a4efa 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -10,7 +10,7 @@
10namespace Service::HID { 10namespace Service::HID {
11class Controller_Stubbed final : public ControllerBase { 11class Controller_Stubbed final : public ControllerBase {
12public: 12public:
13 explicit Controller_Stubbed(Core::System& system_); 13 explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_);
14 ~Controller_Stubbed() override; 14 ~Controller_Stubbed() override;
15 15
16 // Called when the controller is initialized 16 // Called when the controller is initialized
@@ -22,12 +22,17 @@ public:
22 // When the controller is requesting an update for the shared memory 22 // When the controller is requesting an update for the shared memory
23 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 23 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
24 24
25 // Called when input devices should be loaded
26 void OnLoadInputDevices() override;
27
28 void SetCommonHeaderOffset(std::size_t off); 25 void SetCommonHeaderOffset(std::size_t off);
29 26
30private: 27private:
28 struct CommonHeader {
29 s64 timestamp;
30 s64 total_entry_count;
31 s64 last_entry_index;
32 s64 entry_count;
33 };
34 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
35
31 bool smart_update{}; 36 bool smart_update{};
32 std::size_t common_offset{}; 37 std::size_t common_offset{};
33}; 38};
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 6ef17acc5..48978e5c6 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -7,72 +7,82 @@
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/settings.h" 9#include "common/settings.h"
10#include "core/core.h"
10#include "core/core_timing.h" 11#include "core/core_timing.h"
11#include "core/frontend/emu_window.h" 12#include "core/frontend/emu_window.h"
12#include "core/frontend/input.h" 13#include "core/hid/emulated_console.h"
14#include "core/hid/hid_core.h"
13#include "core/hle/service/hid/controllers/touchscreen.h" 15#include "core/hle/service/hid/controllers/touchscreen.h"
14 16
15namespace Service::HID { 17namespace Service::HID {
16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; 18constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
17 19
18Controller_Touchscreen::Controller_Touchscreen(Core::System& system_) : ControllerBase{system_} {} 20Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_)
21 : ControllerBase{hid_core_} {
22 console = hid_core.GetEmulatedConsole();
23}
24
19Controller_Touchscreen::~Controller_Touchscreen() = default; 25Controller_Touchscreen::~Controller_Touchscreen() = default;
20 26
21void Controller_Touchscreen::OnInit() { 27void Controller_Touchscreen::OnInit() {}
22 for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
23 mouse_finger_id[id] = MAX_FINGERS;
24 keyboard_finger_id[id] = MAX_FINGERS;
25 udp_finger_id[id] = MAX_FINGERS;
26 }
27}
28 28
29void Controller_Touchscreen::OnRelease() {} 29void Controller_Touchscreen::OnRelease() {}
30 30
31void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 31void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
32 std::size_t size) { 32 std::size_t size) {
33 shared_memory.header.timestamp = core_timing.GetCPUTicks(); 33 touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
34 shared_memory.header.total_entry_count = 17;
35 34
36 if (!IsControllerActivated()) { 35 if (!IsControllerActivated()) {
37 shared_memory.header.entry_count = 0; 36 touch_screen_lifo.buffer_count = 0;
38 shared_memory.header.last_entry_index = 0; 37 touch_screen_lifo.buffer_tail = 0;
38 std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo));
39 return; 39 return;
40 } 40 }
41 shared_memory.header.entry_count = 16;
42 41
43 const auto& last_entry = 42 const auto touch_status = console->GetTouch();
44 shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; 43 for (std::size_t id = 0; id < MAX_FINGERS; id++) {
45 shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; 44 const auto& current_touch = touch_status[id];
46 auto& cur_entry = shared_memory.shared_memory_entries[shared_memory.header.last_entry_index]; 45 auto& finger = fingers[id];
46 finger.position = current_touch.position;
47 finger.id = current_touch.id;
47 48
48 cur_entry.sampling_number = last_entry.sampling_number + 1; 49 if (finger.attribute.start_touch) {
49 cur_entry.sampling_number2 = cur_entry.sampling_number; 50 finger.attribute.raw = 0;
51 continue;
52 }
50 53
51 const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); 54 if (finger.attribute.end_touch) {
52 const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); 55 finger.attribute.raw = 0;
53 for (std::size_t id = 0; id < mouse_status.size(); ++id) { 56 finger.pressed = false;
54 mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]); 57 continue;
55 udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]); 58 }
56 } 59
60 if (!finger.pressed && current_touch.pressed) {
61 finger.attribute.start_touch.Assign(1);
62 finger.pressed = true;
63 continue;
64 }
57 65
58 if (Settings::values.use_touch_from_button) { 66 if (finger.pressed && !current_touch.pressed) {
59 const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus(); 67 finger.attribute.raw = 0;
60 for (std::size_t id = 0; id < mouse_status.size(); ++id) { 68 finger.attribute.end_touch.Assign(1);
61 keyboard_finger_id[id] =
62 UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]);
63 } 69 }
64 } 70 }
65 71
66 std::array<Finger, 16> active_fingers; 72 std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers;
67 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), 73 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
68 [](const auto& finger) { return finger.pressed; }); 74 [](const auto& finger) { return finger.pressed; });
69 const auto active_fingers_count = 75 const auto active_fingers_count =
70 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); 76 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
71 77
72 const u64 tick = core_timing.GetCPUTicks(); 78 const u64 tick = core_timing.GetCPUTicks();
73 cur_entry.entry_count = static_cast<s32_le>(active_fingers_count); 79 const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state;
80
81 next_state.sampling_number = last_entry.sampling_number + 1;
82 next_state.entry_count = static_cast<s32>(active_fingers_count);
83
74 for (std::size_t id = 0; id < MAX_FINGERS; ++id) { 84 for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
75 auto& touch_entry = cur_entry.states[id]; 85 auto& touch_entry = next_state.states[id];
76 if (id < active_fingers_count) { 86 if (id < active_fingers_count) {
77 const auto& [active_x, active_y] = active_fingers[id].position; 87 const auto& [active_x, active_y] = active_fingers[id].position;
78 touch_entry.position = { 88 touch_entry.position = {
@@ -97,66 +107,9 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
97 touch_entry.finger = 0; 107 touch_entry.finger = 0;
98 } 108 }
99 } 109 }
100 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(TouchScreenSharedMemory));
101}
102
103void Controller_Touchscreen::OnLoadInputDevices() {
104 touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window");
105 touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp");
106 touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button");
107}
108
109std::optional<std::size_t> Controller_Touchscreen::GetUnusedFingerID() const {
110 // Dont assign any touch input to a finger if disabled
111 if (!Settings::values.touchscreen.enabled) {
112 return std::nullopt;
113 }
114 std::size_t first_free_id = 0;
115 while (first_free_id < MAX_FINGERS) {
116 if (!fingers[first_free_id].pressed) {
117 return first_free_id;
118 } else {
119 first_free_id++;
120 }
121 }
122 return std::nullopt;
123}
124
125std::size_t Controller_Touchscreen::UpdateTouchInputEvent(
126 const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) {
127 const auto& [x, y, pressed] = touch_input;
128 if (finger_id > MAX_FINGERS) {
129 LOG_ERROR(Service_HID, "Invalid finger id {}", finger_id);
130 return MAX_FINGERS;
131 }
132 if (pressed) {
133 Attributes attribute{};
134 if (finger_id == MAX_FINGERS) {
135 const auto first_free_id = GetUnusedFingerID();
136 if (!first_free_id) {
137 // Invalid finger id do nothing
138 return MAX_FINGERS;
139 }
140 finger_id = first_free_id.value();
141 fingers[finger_id].pressed = true;
142 fingers[finger_id].id = static_cast<u32_le>(finger_id);
143 attribute.start_touch.Assign(1);
144 }
145 fingers[finger_id].position = {x, y};
146 fingers[finger_id].attribute = attribute;
147 return finger_id;
148 }
149
150 if (finger_id != MAX_FINGERS) {
151 if (!fingers[finger_id].attribute.end_touch) {
152 fingers[finger_id].attribute.end_touch.Assign(1);
153 fingers[finger_id].attribute.start_touch.Assign(0);
154 return finger_id;
155 }
156 fingers[finger_id].pressed = false;
157 }
158 110
159 return MAX_FINGERS; 111 touch_screen_lifo.WriteNextEntry(next_state);
112 std::memcpy(data + SHARED_MEMORY_OFFSET, &touch_screen_lifo, sizeof(touch_screen_lifo));
160} 113}
161 114
162} // namespace Service::HID 115} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 8e9b40c0a..708dde4f0 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -9,18 +9,25 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/point.h" 10#include "common/point.h"
11#include "common/swap.h" 11#include "common/swap.h"
12#include "core/frontend/input.h" 12#include "core/hid/hid_types.h"
13#include "core/hle/service/hid/controllers/controller_base.h" 13#include "core/hle/service/hid/controllers/controller_base.h"
14#include "core/hle/service/hid/ring_lifo.h"
15
16namespace Core::HID {
17class EmulatedConsole;
18} // namespace Core::HID
14 19
15namespace Service::HID { 20namespace Service::HID {
16class Controller_Touchscreen final : public ControllerBase { 21class Controller_Touchscreen final : public ControllerBase {
17public: 22public:
23 // This is nn::hid::TouchScreenModeForNx
18 enum class TouchScreenModeForNx : u8 { 24 enum class TouchScreenModeForNx : u8 {
19 UseSystemSetting, 25 UseSystemSetting,
20 Finger, 26 Finger,
21 Heat2, 27 Heat2,
22 }; 28 };
23 29
30 // This is nn::hid::TouchScreenConfigurationForNx
24 struct TouchScreenConfigurationForNx { 31 struct TouchScreenConfigurationForNx {
25 TouchScreenModeForNx mode; 32 TouchScreenModeForNx mode;
26 INSERT_PADDING_BYTES_NOINIT(0x7); 33 INSERT_PADDING_BYTES_NOINIT(0x7);
@@ -29,7 +36,7 @@ public:
29 static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17, 36 static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
30 "TouchScreenConfigurationForNx is an invalid size"); 37 "TouchScreenConfigurationForNx is an invalid size");
31 38
32 explicit Controller_Touchscreen(Core::System& system_); 39 explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_);
33 ~Controller_Touchscreen() override; 40 ~Controller_Touchscreen() override;
34 41
35 // Called when the controller is initialized 42 // Called when the controller is initialized
@@ -41,73 +48,24 @@ public:
41 // When the controller is requesting an update for the shared memory 48 // When the controller is requesting an update for the shared memory
42 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 49 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
43 50
44 // Called when input devices should be loaded
45 void OnLoadInputDevices() override;
46
47private: 51private:
48 static constexpr std::size_t MAX_FINGERS = 16; 52 static constexpr std::size_t MAX_FINGERS = 16;
49 53
50 // Returns an unused finger id, if there is no fingers available std::nullopt will be returned 54 // This is nn::hid::TouchScreenState
51 std::optional<std::size_t> GetUnusedFingerID() const; 55 struct TouchScreenState {
52 56 s64 sampling_number;
53 // If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no 57 s32 entry_count;
54 // changes will be made. Updates the coordinates if the finger id it's already set. If the touch 58 INSERT_PADDING_BYTES(4); // Reserved
55 // ends delays the output by one frame to set the end_touch flag before finally freeing the 59 std::array<Core::HID::TouchState, MAX_FINGERS> states;
56 // finger id
57 std::size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input,
58 std::size_t finger_id);
59
60 struct Attributes {
61 union {
62 u32 raw{};
63 BitField<0, 1, u32> start_touch;
64 BitField<1, 1, u32> end_touch;
65 };
66 };
67 static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
68
69 struct TouchState {
70 u64_le delta_time;
71 Attributes attribute;
72 u32_le finger;
73 Common::Point<u32_le> position;
74 u32_le diameter_x;
75 u32_le diameter_y;
76 u32_le rotation_angle;
77 }; 60 };
78 static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); 61 static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
79 62
80 struct TouchScreenEntry { 63 // This is nn::hid::detail::TouchScreenLifo
81 s64_le sampling_number; 64 Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
82 s64_le sampling_number2; 65 static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
83 s32_le entry_count; 66 TouchScreenState next_state{};
84 std::array<TouchState, MAX_FINGERS> states;
85 };
86 static_assert(sizeof(TouchScreenEntry) == 0x298, "TouchScreenEntry is an invalid size");
87
88 struct TouchScreenSharedMemory {
89 CommonHeader header;
90 std::array<TouchScreenEntry, 17> shared_memory_entries{};
91 INSERT_PADDING_BYTES(0x3c8);
92 };
93 static_assert(sizeof(TouchScreenSharedMemory) == 0x3000,
94 "TouchScreenSharedMemory is an invalid size");
95
96 struct Finger {
97 u64_le last_touch{};
98 Common::Point<float> position;
99 u32_le id{};
100 bool pressed{};
101 Attributes attribute;
102 };
103 67
104 TouchScreenSharedMemory shared_memory{}; 68 std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers;
105 std::unique_ptr<Input::TouchDevice> touch_mouse_device; 69 Core::HID::EmulatedConsole* console;
106 std::unique_ptr<Input::TouchDevice> touch_udp_device;
107 std::unique_ptr<Input::TouchDevice> touch_btn_device;
108 std::array<std::size_t, MAX_FINGERS> mouse_finger_id;
109 std::array<std::size_t, MAX_FINGERS> keyboard_finger_id;
110 std::array<std::size_t, MAX_FINGERS> udp_finger_id;
111 std::array<Finger, MAX_FINGERS> fingers;
112}; 70};
113} // namespace Service::HID 71} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index 41dc22cf9..e4da16466 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -5,12 +5,13 @@
5#include <cstring> 5#include <cstring>
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/xpad.h" 9#include "core/hle/service/hid/controllers/xpad.h"
9 10
10namespace Service::HID { 11namespace Service::HID {
11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; 12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
12 13
13Controller_XPad::Controller_XPad(Core::System& system_) : ControllerBase{system_} {} 14Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {}
14Controller_XPad::~Controller_XPad() = default; 15Controller_XPad::~Controller_XPad() = default;
15 16
16void Controller_XPad::OnInit() {} 17void Controller_XPad::OnInit() {}
@@ -19,28 +20,19 @@ void Controller_XPad::OnRelease() {}
19 20
20void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 21void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
21 std::size_t size) { 22 std::size_t size) {
22 for (auto& xpad_entry : shared_memory.shared_memory_entries) { 23 if (!IsControllerActivated()) {
23 xpad_entry.header.timestamp = core_timing.GetCPUTicks(); 24 basic_xpad_lifo.buffer_count = 0;
24 xpad_entry.header.total_entry_count = 17; 25 basic_xpad_lifo.buffer_tail = 0;
25 26 std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
26 if (!IsControllerActivated()) { 27 return;
27 xpad_entry.header.entry_count = 0;
28 xpad_entry.header.last_entry_index = 0;
29 return;
30 }
31 xpad_entry.header.entry_count = 16;
32
33 const auto& last_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index];
34 xpad_entry.header.last_entry_index = (xpad_entry.header.last_entry_index + 1) % 17;
35 auto& cur_entry = xpad_entry.pad_states[xpad_entry.header.last_entry_index];
36
37 cur_entry.sampling_number = last_entry.sampling_number + 1;
38 cur_entry.sampling_number2 = cur_entry.sampling_number;
39 } 28 }
29
30 const auto& last_entry = basic_xpad_lifo.ReadCurrentEntry().state;
31 next_state.sampling_number = last_entry.sampling_number + 1;
40 // TODO(ogniK): Update xpad states 32 // TODO(ogniK): Update xpad states
41 33
42 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 34 basic_xpad_lifo.WriteNextEntry(next_state);
35 std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
43} 36}
44 37
45void Controller_XPad::OnLoadInputDevices() {}
46} // namespace Service::HID 38} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index f9ab5facf..ba8db8d9d 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -8,12 +8,14 @@
8#include "common/common_funcs.h" 8#include "common/common_funcs.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/swap.h" 10#include "common/swap.h"
11#include "core/hid/hid_types.h"
11#include "core/hle/service/hid/controllers/controller_base.h" 12#include "core/hle/service/hid/controllers/controller_base.h"
13#include "core/hle/service/hid/ring_lifo.h"
12 14
13namespace Service::HID { 15namespace Service::HID {
14class Controller_XPad final : public ControllerBase { 16class Controller_XPad final : public ControllerBase {
15public: 17public:
16 explicit Controller_XPad(Core::System& system_); 18 explicit Controller_XPad(Core::HID::HIDCore& hid_core_);
17 ~Controller_XPad() override; 19 ~Controller_XPad() override;
18 20
19 // Called when the controller is initialized 21 // Called when the controller is initialized
@@ -25,13 +27,11 @@ public:
25 // When the controller is requesting an update for the shared memory 27 // When the controller is requesting an update for the shared memory
26 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 28 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
27 29
28 // Called when input devices should be loaded
29 void OnLoadInputDevices() override;
30
31private: 30private:
32 struct Attributes { 31 // This is nn::hid::BasicXpadAttributeSet
32 struct BasicXpadAttributeSet {
33 union { 33 union {
34 u32_le raw{}; 34 u32 raw{};
35 BitField<0, 1, u32> is_connected; 35 BitField<0, 1, u32> is_connected;
36 BitField<1, 1, u32> is_wired; 36 BitField<1, 1, u32> is_wired;
37 BitField<2, 1, u32> is_left_connected; 37 BitField<2, 1, u32> is_left_connected;
@@ -40,11 +40,12 @@ private:
40 BitField<5, 1, u32> is_right_wired; 40 BitField<5, 1, u32> is_right_wired;
41 }; 41 };
42 }; 42 };
43 static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size"); 43 static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size");
44 44
45 struct Buttons { 45 // This is nn::hid::BasicXpadButtonSet
46 struct BasicXpadButtonSet {
46 union { 47 union {
47 u32_le raw{}; 48 u32 raw{};
48 // Button states 49 // Button states
49 BitField<0, 1, u32> a; 50 BitField<0, 1, u32> a;
50 BitField<1, 1, u32> b; 51 BitField<1, 1, u32> b;
@@ -88,35 +89,21 @@ private:
88 BitField<30, 1, u32> handheld_left_b; 89 BitField<30, 1, u32> handheld_left_b;
89 }; 90 };
90 }; 91 };
91 static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size"); 92 static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size");
92 93
93 struct AnalogStick { 94 // This is nn::hid::detail::BasicXpadState
94 s32_le x; 95 struct BasicXpadState {
95 s32_le y; 96 s64 sampling_number;
96 }; 97 BasicXpadAttributeSet attributes;
97 static_assert(sizeof(AnalogStick) == 0x8, "AnalogStick is an invalid size"); 98 BasicXpadButtonSet pad_states;
98 99 Core::HID::AnalogStickState l_stick;
99 struct XPadState { 100 Core::HID::AnalogStickState r_stick;
100 s64_le sampling_number;
101 s64_le sampling_number2;
102 Attributes attributes;
103 Buttons pad_states;
104 AnalogStick l_stick;
105 AnalogStick r_stick;
106 }; 101 };
107 static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size"); 102 static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
108 103
109 struct XPadEntry { 104 // This is nn::hid::detail::BasicXpadLifo
110 CommonHeader header; 105 Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
111 std::array<XPadState, 17> pad_states{}; 106 static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
112 INSERT_PADDING_BYTES(0x138); 107 BasicXpadState next_state{};
113 };
114 static_assert(sizeof(XPadEntry) == 0x400, "XPadEntry is an invalid size");
115
116 struct SharedMemory {
117 std::array<XPadEntry, 4> shared_memory_entries{};
118 };
119 static_assert(sizeof(SharedMemory) == 0x1000, "SharedMemory is an invalid size");
120 SharedMemory shared_memory{};
121}; 108};
122} // namespace Service::HID 109} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 10c64d41a..95fc07325 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -8,7 +8,7 @@
8#include "common/settings.h" 8#include "common/settings.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/core_timing.h" 10#include "core/core_timing.h"
11#include "core/frontend/input.h" 11#include "core/hid/hid_core.h"
12#include "core/hle/ipc_helpers.h" 12#include "core/hle/ipc_helpers.h"
13#include "core/hle/kernel/k_readable_event.h" 13#include "core/hle/kernel/k_readable_event.h"
14#include "core/hle/kernel/k_shared_memory.h" 14#include "core/hle/kernel/k_shared_memory.h"
@@ -34,10 +34,10 @@
34namespace Service::HID { 34namespace Service::HID {
35 35
36// Updating period for each HID device. 36// Updating period for each HID device.
37// HID is polled every 15ms, this value was derived from 37// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
38// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet 38constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz)
39constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz) 39constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
40constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz) 40constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
41constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; 41constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
42 42
43IAppletResource::IAppletResource(Core::System& system_, 43IAppletResource::IAppletResource(Core::System& system_,
@@ -79,17 +79,24 @@ IAppletResource::IAppletResource(Core::System& system_,
79 const auto guard = LockService(); 79 const auto guard = LockService();
80 UpdateControllers(user_data, ns_late); 80 UpdateControllers(user_data, ns_late);
81 }); 81 });
82 mouse_keyboard_update_event = Core::Timing::CreateEvent(
83 "HID::UpdateMouseKeyboardCallback",
84 [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
85 const auto guard = LockService();
86 UpdateMouseKeyboard(user_data, ns_late);
87 });
82 motion_update_event = Core::Timing::CreateEvent( 88 motion_update_event = Core::Timing::CreateEvent(
83 "HID::MotionPadCallback", 89 "HID::UpdateMotionCallback",
84 [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 90 [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
85 const auto guard = LockService(); 91 const auto guard = LockService();
86 UpdateMotion(user_data, ns_late); 92 UpdateMotion(user_data, ns_late);
87 }); 93 });
88 94
89 system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); 95 system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
96 system.CoreTiming().ScheduleEvent(mouse_keyboard_update_ns, mouse_keyboard_update_event);
90 system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); 97 system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
91 98
92 ReloadInputDevices(); 99 system.HIDCore().ReloadInputDevices();
93} 100}
94 101
95void IAppletResource::ActivateController(HidController controller) { 102void IAppletResource::ActivateController(HidController controller) {
@@ -102,6 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) {
102 109
103IAppletResource::~IAppletResource() { 110IAppletResource::~IAppletResource() {
104 system.CoreTiming().UnscheduleEvent(pad_update_event, 0); 111 system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
112 system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
105 system.CoreTiming().UnscheduleEvent(motion_update_event, 0); 113 system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
106} 114}
107 115
@@ -117,23 +125,44 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
117 std::chrono::nanoseconds ns_late) { 125 std::chrono::nanoseconds ns_late) {
118 auto& core_timing = system.CoreTiming(); 126 auto& core_timing = system.CoreTiming();
119 127
120 const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
121 for (const auto& controller : controllers) { 128 for (const auto& controller : controllers) {
122 if (should_reload) { 129 // Keyboard has it's own update event
123 controller->OnLoadInputDevices(); 130 if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
131 continue;
132 }
133 // Mouse has it's own update event
134 if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
135 continue;
124 } 136 }
125 controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), 137 controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(),
126 SHARED_MEMORY_SIZE); 138 SHARED_MEMORY_SIZE);
127 } 139 }
128 140
129 // If ns_late is higher than the update rate ignore the delay 141 // If ns_late is higher than the update rate ignore the delay
130 if (ns_late > motion_update_ns) { 142 if (ns_late > pad_update_ns) {
131 ns_late = {}; 143 ns_late = {};
132 } 144 }
133 145
134 core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); 146 core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
135} 147}
136 148
149void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
150 std::chrono::nanoseconds ns_late) {
151 auto& core_timing = system.CoreTiming();
152
153 controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(
154 core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
155 controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(
156 core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
157
158 // If ns_late is higher than the update rate ignore the delay
159 if (ns_late > mouse_keyboard_update_ns) {
160 ns_late = {};
161 }
162
163 core_timing.ScheduleEvent(mouse_keyboard_update_ns - ns_late, mouse_keyboard_update_event);
164}
165
137void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 166void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
138 auto& core_timing = system.CoreTiming(); 167 auto& core_timing = system.CoreTiming();
139 168
@@ -166,7 +195,7 @@ public:
166private: 195private:
167 void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) { 196 void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) {
168 IPC::RequestParser rp{ctx}; 197 IPC::RequestParser rp{ctx};
169 const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; 198 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
170 199
171 if (applet_resource != nullptr) { 200 if (applet_resource != nullptr) {
172 applet_resource->GetController<Controller_NPad>(HidController::NPad) 201 applet_resource->GetController<Controller_NPad>(HidController::NPad)
@@ -422,6 +451,7 @@ void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) {
422 INSERT_PADDING_WORDS_NOINIT(1); 451 INSERT_PADDING_WORDS_NOINIT(1);
423 u64 applet_resource_user_id; 452 u64 applet_resource_user_id;
424 }; 453 };
454 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
425 455
426 const auto parameters{rp.PopRaw<Parameters>()}; 456 const auto parameters{rp.PopRaw<Parameters>()};
427 457
@@ -448,19 +478,18 @@ void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) {
448void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { 478void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
449 IPC::RequestParser rp{ctx}; 479 IPC::RequestParser rp{ctx};
450 struct Parameters { 480 struct Parameters {
451 Controller_NPad::DeviceHandle sixaxis_handle; 481 u32 basic_xpad_id;
452 INSERT_PADDING_WORDS_NOINIT(1); 482 INSERT_PADDING_WORDS_NOINIT(1);
453 u64 applet_resource_user_id; 483 u64 applet_resource_user_id;
454 }; 484 };
485 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
455 486
456 const auto parameters{rp.PopRaw<Parameters>()}; 487 const auto parameters{rp.PopRaw<Parameters>()};
457 488
458 applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); 489 // This function does nothing on 10.0.0+
459 490
460 LOG_DEBUG(Service_HID, 491 LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
461 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 492 parameters.basic_xpad_id, parameters.applet_resource_user_id);
462 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
463 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
464 493
465 IPC::ResponseBuilder rb{ctx, 2}; 494 IPC::ResponseBuilder rb{ctx, 2};
466 rb.Push(ResultSuccess); 495 rb.Push(ResultSuccess);
@@ -469,19 +498,18 @@ void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
469void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { 498void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
470 IPC::RequestParser rp{ctx}; 499 IPC::RequestParser rp{ctx};
471 struct Parameters { 500 struct Parameters {
472 Controller_NPad::DeviceHandle sixaxis_handle; 501 u32 basic_xpad_id;
473 INSERT_PADDING_WORDS_NOINIT(1); 502 INSERT_PADDING_WORDS_NOINIT(1);
474 u64 applet_resource_user_id; 503 u64 applet_resource_user_id;
475 }; 504 };
505 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
476 506
477 const auto parameters{rp.PopRaw<Parameters>()}; 507 const auto parameters{rp.PopRaw<Parameters>()};
478 508
479 applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); 509 // This function does nothing on 10.0.0+
480 510
481 LOG_DEBUG(Service_HID, 511 LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
482 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 512 parameters.basic_xpad_id, parameters.applet_resource_user_id);
483 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
484 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
485 513
486 IPC::ResponseBuilder rb{ctx, 2}; 514 IPC::ResponseBuilder rb{ctx, 2};
487 rb.Push(ResultSuccess); 515 rb.Push(ResultSuccess);
@@ -490,14 +518,16 @@ void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
490void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { 518void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
491 IPC::RequestParser rp{ctx}; 519 IPC::RequestParser rp{ctx};
492 struct Parameters { 520 struct Parameters {
493 Controller_NPad::DeviceHandle sixaxis_handle; 521 Core::HID::SixAxisSensorHandle sixaxis_handle;
494 INSERT_PADDING_WORDS_NOINIT(1); 522 INSERT_PADDING_WORDS_NOINIT(1);
495 u64 applet_resource_user_id; 523 u64 applet_resource_user_id;
496 }; 524 };
525 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
497 526
498 const auto parameters{rp.PopRaw<Parameters>()}; 527 const auto parameters{rp.PopRaw<Parameters>()};
499 528
500 applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); 529 applet_resource->GetController<Controller_NPad>(HidController::NPad)
530 .SetSixAxisEnabled(parameters.sixaxis_handle, true);
501 531
502 LOG_DEBUG(Service_HID, 532 LOG_DEBUG(Service_HID,
503 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 533 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -511,14 +541,16 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
511void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { 541void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
512 IPC::RequestParser rp{ctx}; 542 IPC::RequestParser rp{ctx};
513 struct Parameters { 543 struct Parameters {
514 Controller_NPad::DeviceHandle sixaxis_handle; 544 Core::HID::SixAxisSensorHandle sixaxis_handle;
515 INSERT_PADDING_WORDS_NOINIT(1); 545 INSERT_PADDING_WORDS_NOINIT(1);
516 u64 applet_resource_user_id; 546 u64 applet_resource_user_id;
517 }; 547 };
548 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
518 549
519 const auto parameters{rp.PopRaw<Parameters>()}; 550 const auto parameters{rp.PopRaw<Parameters>()};
520 551
521 applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); 552 applet_resource->GetController<Controller_NPad>(HidController::NPad)
553 .SetSixAxisEnabled(parameters.sixaxis_handle, false);
522 554
523 LOG_DEBUG(Service_HID, 555 LOG_DEBUG(Service_HID,
524 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 556 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -534,19 +566,23 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
534 struct Parameters { 566 struct Parameters {
535 bool enable_sixaxis_sensor_fusion; 567 bool enable_sixaxis_sensor_fusion;
536 INSERT_PADDING_BYTES_NOINIT(3); 568 INSERT_PADDING_BYTES_NOINIT(3);
537 Controller_NPad::DeviceHandle sixaxis_handle; 569 Core::HID::SixAxisSensorHandle sixaxis_handle;
538 u64 applet_resource_user_id; 570 u64 applet_resource_user_id;
539 }; 571 };
540 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); 572 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
541 573
542 const auto parameters{rp.PopRaw<Parameters>()}; 574 const auto parameters{rp.PopRaw<Parameters>()};
543 575
544 LOG_WARNING(Service_HID, 576 applet_resource->GetController<Controller_NPad>(HidController::NPad)
545 "(STUBBED) called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " 577 .SetSixAxisFusionEnabled(parameters.sixaxis_handle,
546 "device_index={}, applet_resource_user_id={}", 578 parameters.enable_sixaxis_sensor_fusion);
547 parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type, 579
548 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, 580 LOG_DEBUG(Service_HID,
549 parameters.applet_resource_user_id); 581 "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
582 "device_index={}, applet_resource_user_id={}",
583 parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
584 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
585 parameters.applet_resource_user_id);
550 586
551 IPC::ResponseBuilder rb{ctx, 2}; 587 IPC::ResponseBuilder rb{ctx, 2};
552 rb.Push(ResultSuccess); 588 rb.Push(ResultSuccess);
@@ -555,9 +591,9 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
555void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { 591void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
556 IPC::RequestParser rp{ctx}; 592 IPC::RequestParser rp{ctx};
557 struct Parameters { 593 struct Parameters {
558 Controller_NPad::DeviceHandle sixaxis_handle; 594 Core::HID::SixAxisSensorHandle sixaxis_handle;
559 f32 parameter1; 595 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion;
560 f32 parameter2; 596 INSERT_PADDING_WORDS_NOINIT(1);
561 u64 applet_resource_user_id; 597 u64 applet_resource_user_id;
562 }; 598 };
563 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 599 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
@@ -565,14 +601,14 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
565 const auto parameters{rp.PopRaw<Parameters>()}; 601 const auto parameters{rp.PopRaw<Parameters>()};
566 602
567 applet_resource->GetController<Controller_NPad>(HidController::NPad) 603 applet_resource->GetController<Controller_NPad>(HidController::NPad)
568 .SetSixAxisFusionParameters(parameters.parameter1, parameters.parameter2); 604 .SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
569 605
570 LOG_WARNING(Service_HID, 606 LOG_DEBUG(Service_HID,
571 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, parameter1={}, " 607 "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
572 "parameter2={}, applet_resource_user_id={}", 608 "parameter2={}, applet_resource_user_id={}",
573 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, 609 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
574 parameters.sixaxis_handle.device_index, parameters.parameter1, 610 parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1,
575 parameters.parameter2, parameters.applet_resource_user_id); 611 parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id);
576 612
577 IPC::ResponseBuilder rb{ctx, 2}; 613 IPC::ResponseBuilder rb{ctx, 2};
578 rb.Push(ResultSuccess); 614 rb.Push(ResultSuccess);
@@ -581,35 +617,33 @@ void Hid::SetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
581void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { 617void Hid::GetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
582 IPC::RequestParser rp{ctx}; 618 IPC::RequestParser rp{ctx};
583 struct Parameters { 619 struct Parameters {
584 Controller_NPad::DeviceHandle sixaxis_handle; 620 Core::HID::SixAxisSensorHandle sixaxis_handle;
621 INSERT_PADDING_WORDS_NOINIT(1);
585 u64 applet_resource_user_id; 622 u64 applet_resource_user_id;
586 }; 623 };
587 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); 624 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
588 625
589 f32 parameter1 = 0;
590 f32 parameter2 = 0;
591 const auto parameters{rp.PopRaw<Parameters>()}; 626 const auto parameters{rp.PopRaw<Parameters>()};
592 627
593 std::tie(parameter1, parameter2) = 628 const auto sixaxis_fusion_parameters =
594 applet_resource->GetController<Controller_NPad>(HidController::NPad) 629 applet_resource->GetController<Controller_NPad>(HidController::NPad)
595 .GetSixAxisFusionParameters(); 630 .GetSixAxisFusionParameters(parameters.sixaxis_handle);
596 631
597 LOG_WARNING( 632 LOG_DEBUG(Service_HID,
598 Service_HID, 633 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
599 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 634 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
600 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, 635 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
601 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
602 636
603 IPC::ResponseBuilder rb{ctx, 4}; 637 IPC::ResponseBuilder rb{ctx, 4};
604 rb.Push(ResultSuccess); 638 rb.Push(ResultSuccess);
605 rb.Push(parameter1); 639 rb.PushRaw(sixaxis_fusion_parameters);
606 rb.Push(parameter2);
607} 640}
608 641
609void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) { 642void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
610 IPC::RequestParser rp{ctx}; 643 IPC::RequestParser rp{ctx};
611 struct Parameters { 644 struct Parameters {
612 Controller_NPad::DeviceHandle sixaxis_handle; 645 Core::HID::SixAxisSensorHandle sixaxis_handle;
646 INSERT_PADDING_WORDS_NOINIT(1);
613 u64 applet_resource_user_id; 647 u64 applet_resource_user_id;
614 }; 648 };
615 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); 649 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@@ -617,13 +651,12 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
617 const auto parameters{rp.PopRaw<Parameters>()}; 651 const auto parameters{rp.PopRaw<Parameters>()};
618 652
619 applet_resource->GetController<Controller_NPad>(HidController::NPad) 653 applet_resource->GetController<Controller_NPad>(HidController::NPad)
620 .ResetSixAxisFusionParameters(); 654 .ResetSixAxisFusionParameters(parameters.sixaxis_handle);
621 655
622 LOG_WARNING( 656 LOG_DEBUG(Service_HID,
623 Service_HID, 657 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
624 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 658 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
625 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, 659 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
626 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
627 660
628 IPC::ResponseBuilder rb{ctx, 2}; 661 IPC::ResponseBuilder rb{ctx, 2};
629 rb.Push(ResultSuccess); 662 rb.Push(ResultSuccess);
@@ -631,12 +664,12 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
631 664
632void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { 665void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
633 IPC::RequestParser rp{ctx}; 666 IPC::RequestParser rp{ctx};
634 const auto sixaxis_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; 667 const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
635 const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()}; 668 const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()};
636 const auto applet_resource_user_id{rp.Pop<u64>()}; 669 const auto applet_resource_user_id{rp.Pop<u64>()};
637 670
638 applet_resource->GetController<Controller_NPad>(HidController::NPad) 671 applet_resource->GetController<Controller_NPad>(HidController::NPad)
639 .SetGyroscopeZeroDriftMode(drift_mode); 672 .SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
640 673
641 LOG_DEBUG(Service_HID, 674 LOG_DEBUG(Service_HID,
642 "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, " 675 "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
@@ -651,10 +684,11 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
651void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { 684void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
652 IPC::RequestParser rp{ctx}; 685 IPC::RequestParser rp{ctx};
653 struct Parameters { 686 struct Parameters {
654 Controller_NPad::DeviceHandle sixaxis_handle; 687 Core::HID::SixAxisSensorHandle sixaxis_handle;
655 INSERT_PADDING_WORDS_NOINIT(1); 688 INSERT_PADDING_WORDS_NOINIT(1);
656 u64 applet_resource_user_id; 689 u64 applet_resource_user_id;
657 }; 690 };
691 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
658 692
659 const auto parameters{rp.PopRaw<Parameters>()}; 693 const auto parameters{rp.PopRaw<Parameters>()};
660 694
@@ -666,21 +700,23 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
666 IPC::ResponseBuilder rb{ctx, 3}; 700 IPC::ResponseBuilder rb{ctx, 3};
667 rb.Push(ResultSuccess); 701 rb.Push(ResultSuccess);
668 rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) 702 rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
669 .GetGyroscopeZeroDriftMode()); 703 .GetGyroscopeZeroDriftMode(parameters.sixaxis_handle));
670} 704}
671 705
672void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { 706void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
673 IPC::RequestParser rp{ctx}; 707 IPC::RequestParser rp{ctx};
674 struct Parameters { 708 struct Parameters {
675 Controller_NPad::DeviceHandle sixaxis_handle; 709 Core::HID::SixAxisSensorHandle sixaxis_handle;
676 INSERT_PADDING_WORDS_NOINIT(1); 710 INSERT_PADDING_WORDS_NOINIT(1);
677 u64 applet_resource_user_id; 711 u64 applet_resource_user_id;
678 }; 712 };
713 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
679 714
680 const auto parameters{rp.PopRaw<Parameters>()}; 715 const auto parameters{rp.PopRaw<Parameters>()};
716 const auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard};
681 717
682 applet_resource->GetController<Controller_NPad>(HidController::NPad) 718 applet_resource->GetController<Controller_NPad>(HidController::NPad)
683 .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); 719 .SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
684 720
685 LOG_DEBUG(Service_HID, 721 LOG_DEBUG(Service_HID,
686 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 722 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
@@ -694,10 +730,11 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
694void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { 730void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
695 IPC::RequestParser rp{ctx}; 731 IPC::RequestParser rp{ctx};
696 struct Parameters { 732 struct Parameters {
697 Controller_NPad::DeviceHandle sixaxis_handle; 733 Core::HID::SixAxisSensorHandle sixaxis_handle;
698 INSERT_PADDING_WORDS_NOINIT(1); 734 INSERT_PADDING_WORDS_NOINIT(1);
699 u64 applet_resource_user_id; 735 u64 applet_resource_user_id;
700 }; 736 };
737 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
701 738
702 const auto parameters{rp.PopRaw<Parameters>()}; 739 const auto parameters{rp.PopRaw<Parameters>()};
703 740
@@ -709,16 +746,17 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
709 IPC::ResponseBuilder rb{ctx, 3}; 746 IPC::ResponseBuilder rb{ctx, 3};
710 rb.Push(ResultSuccess); 747 rb.Push(ResultSuccess);
711 rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) 748 rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
712 .IsSixAxisSensorAtRest()); 749 .IsSixAxisSensorAtRest(parameters.sixaxis_handle));
713} 750}
714 751
715void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) { 752void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) {
716 IPC::RequestParser rp{ctx}; 753 IPC::RequestParser rp{ctx};
717 struct Parameters { 754 struct Parameters {
718 Controller_NPad::DeviceHandle sixaxis_handle; 755 Core::HID::SixAxisSensorHandle sixaxis_handle;
719 INSERT_PADDING_WORDS_NOINIT(1); 756 INSERT_PADDING_WORDS_NOINIT(1);
720 u64 applet_resource_user_id; 757 u64 applet_resource_user_id;
721 }; 758 };
759 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
722 760
723 const auto parameters{rp.PopRaw<Parameters>()}; 761 const auto parameters{rp.PopRaw<Parameters>()};
724 762
@@ -740,13 +778,14 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
740 INSERT_PADDING_WORDS_NOINIT(1); 778 INSERT_PADDING_WORDS_NOINIT(1);
741 u64 applet_resource_user_id; 779 u64 applet_resource_user_id;
742 }; 780 };
781 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
743 782
744 const auto parameters{rp.PopRaw<Parameters>()}; 783 const auto parameters{rp.PopRaw<Parameters>()};
745 784
746 applet_resource->ActivateController(HidController::Gesture); 785 applet_resource->ActivateController(HidController::Gesture);
747 786
748 LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, 787 LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
749 parameters.applet_resource_user_id); 788 parameters.unknown, parameters.applet_resource_user_id);
750 789
751 IPC::ResponseBuilder rb{ctx, 2}; 790 IPC::ResponseBuilder rb{ctx, 2};
752 rb.Push(ResultSuccess); 791 rb.Push(ResultSuccess);
@@ -754,12 +793,20 @@ void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
754 793
755void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { 794void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
756 IPC::RequestParser rp{ctx}; 795 IPC::RequestParser rp{ctx};
757 const auto supported_styleset{rp.Pop<u32>()}; 796 struct Parameters {
797 Core::HID::NpadStyleSet supported_styleset;
798 INSERT_PADDING_WORDS_NOINIT(1);
799 u64 applet_resource_user_id;
800 };
801 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
802
803 const auto parameters{rp.PopRaw<Parameters>()};
758 804
759 applet_resource->GetController<Controller_NPad>(HidController::NPad) 805 applet_resource->GetController<Controller_NPad>(HidController::NPad)
760 .SetSupportedStyleSet({supported_styleset}); 806 .SetSupportedStyleSet({parameters.supported_styleset});
761 807
762 LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); 808 LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
809 parameters.supported_styleset, parameters.applet_resource_user_id);
763 810
764 IPC::ResponseBuilder rb{ctx, 2}; 811 IPC::ResponseBuilder rb{ctx, 2};
765 rb.Push(ResultSuccess); 812 rb.Push(ResultSuccess);
@@ -773,9 +820,9 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
773 820
774 IPC::ResponseBuilder rb{ctx, 3}; 821 IPC::ResponseBuilder rb{ctx, 3};
775 rb.Push(ResultSuccess); 822 rb.Push(ResultSuccess);
776 rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) 823 rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
777 .GetSupportedStyleSet() 824 .GetSupportedStyleSet()
778 .raw); 825 .raw);
779} 826}
780 827
781void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { 828void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
@@ -818,11 +865,12 @@ void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) {
818void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { 865void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
819 IPC::RequestParser rp{ctx}; 866 IPC::RequestParser rp{ctx};
820 struct Parameters { 867 struct Parameters {
821 u32 npad_id; 868 Core::HID::NpadIdType npad_id;
822 INSERT_PADDING_WORDS_NOINIT(1); 869 INSERT_PADDING_WORDS_NOINIT(1);
823 u64 applet_resource_user_id; 870 u64 applet_resource_user_id;
824 u64 unknown; 871 u64 unknown;
825 }; 872 };
873 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
826 874
827 const auto parameters{rp.PopRaw<Parameters>()}; 875 const auto parameters{rp.PopRaw<Parameters>()};
828 876
@@ -838,10 +886,11 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
838void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { 886void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
839 IPC::RequestParser rp{ctx}; 887 IPC::RequestParser rp{ctx};
840 struct Parameters { 888 struct Parameters {
841 u32 npad_id; 889 Core::HID::NpadIdType npad_id;
842 INSERT_PADDING_WORDS_NOINIT(1); 890 INSERT_PADDING_WORDS_NOINIT(1);
843 u64 applet_resource_user_id; 891 u64 applet_resource_user_id;
844 }; 892 };
893 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
845 894
846 const auto parameters{rp.PopRaw<Parameters>()}; 895 const auto parameters{rp.PopRaw<Parameters>()};
847 896
@@ -857,7 +906,7 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
857 906
858void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { 907void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
859 IPC::RequestParser rp{ctx}; 908 IPC::RequestParser rp{ctx};
860 const auto npad_id{rp.Pop<u32>()}; 909 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
861 910
862 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id); 911 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
863 912
@@ -872,16 +921,17 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
872 // Should have no effect with how our npad sets up the data 921 // Should have no effect with how our npad sets up the data
873 IPC::RequestParser rp{ctx}; 922 IPC::RequestParser rp{ctx};
874 struct Parameters { 923 struct Parameters {
875 u32 unknown; 924 s32 revision;
876 INSERT_PADDING_WORDS_NOINIT(1); 925 INSERT_PADDING_WORDS_NOINIT(1);
877 u64 applet_resource_user_id; 926 u64 applet_resource_user_id;
878 }; 927 };
928 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
879 929
880 const auto parameters{rp.PopRaw<Parameters>()}; 930 const auto parameters{rp.PopRaw<Parameters>()};
881 931
882 applet_resource->ActivateController(HidController::NPad); 932 applet_resource->ActivateController(HidController::NPad);
883 933
884 LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, 934 LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
885 parameters.applet_resource_user_id); 935 parameters.applet_resource_user_id);
886 936
887 IPC::ResponseBuilder rb{ctx, 2}; 937 IPC::ResponseBuilder rb{ctx, 2};
@@ -891,7 +941,7 @@ void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
891void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { 941void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
892 IPC::RequestParser rp{ctx}; 942 IPC::RequestParser rp{ctx};
893 const auto applet_resource_user_id{rp.Pop<u64>()}; 943 const auto applet_resource_user_id{rp.Pop<u64>()};
894 const auto hold_type{rp.PopEnum<Controller_NPad::NpadHoldType>()}; 944 const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()};
895 945
896 applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type); 946 applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type);
897 947
@@ -916,15 +966,16 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
916void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { 966void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
917 IPC::RequestParser rp{ctx}; 967 IPC::RequestParser rp{ctx};
918 struct Parameters { 968 struct Parameters {
919 u32 npad_id; 969 Core::HID::NpadIdType npad_id;
920 INSERT_PADDING_WORDS_NOINIT(1); 970 INSERT_PADDING_WORDS_NOINIT(1);
921 u64 applet_resource_user_id; 971 u64 applet_resource_user_id;
922 }; 972 };
973 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
923 974
924 const auto parameters{rp.PopRaw<Parameters>()}; 975 const auto parameters{rp.PopRaw<Parameters>()};
925 976
926 applet_resource->GetController<Controller_NPad>(HidController::NPad) 977 applet_resource->GetController<Controller_NPad>(HidController::NPad)
927 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); 978 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single);
928 979
929 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", 980 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
930 parameters.npad_id, parameters.applet_resource_user_id); 981 parameters.npad_id, parameters.applet_resource_user_id);
@@ -937,16 +988,17 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
937 // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault 988 // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
938 IPC::RequestParser rp{ctx}; 989 IPC::RequestParser rp{ctx};
939 struct Parameters { 990 struct Parameters {
940 u32 npad_id; 991 Core::HID::NpadIdType npad_id;
941 INSERT_PADDING_WORDS_NOINIT(1); 992 INSERT_PADDING_WORDS_NOINIT(1);
942 u64 applet_resource_user_id; 993 u64 applet_resource_user_id;
943 u64 npad_joy_device_type; 994 u64 npad_joy_device_type;
944 }; 995 };
996 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
945 997
946 const auto parameters{rp.PopRaw<Parameters>()}; 998 const auto parameters{rp.PopRaw<Parameters>()};
947 999
948 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1000 applet_resource->GetController<Controller_NPad>(HidController::NPad)
949 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); 1001 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single);
950 1002
951 LOG_WARNING(Service_HID, 1003 LOG_WARNING(Service_HID,
952 "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1004 "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
@@ -960,15 +1012,16 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
960void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { 1012void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
961 IPC::RequestParser rp{ctx}; 1013 IPC::RequestParser rp{ctx};
962 struct Parameters { 1014 struct Parameters {
963 u32 npad_id; 1015 Core::HID::NpadIdType npad_id;
964 INSERT_PADDING_WORDS_NOINIT(1); 1016 INSERT_PADDING_WORDS_NOINIT(1);
965 u64 applet_resource_user_id; 1017 u64 applet_resource_user_id;
966 }; 1018 };
1019 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
967 1020
968 const auto parameters{rp.PopRaw<Parameters>()}; 1021 const auto parameters{rp.PopRaw<Parameters>()};
969 1022
970 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1023 applet_resource->GetController<Controller_NPad>(HidController::NPad)
971 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Dual); 1024 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Dual);
972 1025
973 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", 1026 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
974 parameters.npad_id, parameters.applet_resource_user_id); 1027 parameters.npad_id, parameters.applet_resource_user_id);
@@ -979,8 +1032,8 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
979 1032
980void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { 1033void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
981 IPC::RequestParser rp{ctx}; 1034 IPC::RequestParser rp{ctx};
982 const auto npad_id_1{rp.Pop<u32>()}; 1035 const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
983 const auto npad_id_2{rp.Pop<u32>()}; 1036 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
984 const auto applet_resource_user_id{rp.Pop<u64>()}; 1037 const auto applet_resource_user_id{rp.Pop<u64>()};
985 1038
986 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1039 applet_resource->GetController<Controller_NPad>(HidController::NPad)
@@ -1046,8 +1099,8 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
1046 1099
1047void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { 1100void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
1048 IPC::RequestParser rp{ctx}; 1101 IPC::RequestParser rp{ctx};
1049 const auto npad_id_1{rp.Pop<u32>()}; 1102 const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
1050 const auto npad_id_2{rp.Pop<u32>()}; 1103 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1051 const auto applet_resource_user_id{rp.Pop<u64>()}; 1104 const auto applet_resource_user_id{rp.Pop<u64>()};
1052 1105
1053 const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad) 1106 const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad)
@@ -1068,10 +1121,11 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
1068void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { 1121void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
1069 IPC::RequestParser rp{ctx}; 1122 IPC::RequestParser rp{ctx};
1070 struct Parameters { 1123 struct Parameters {
1071 u32 npad_id; 1124 Core::HID::NpadIdType npad_id;
1072 INSERT_PADDING_WORDS_NOINIT(1); 1125 INSERT_PADDING_WORDS_NOINIT(1);
1073 u64 applet_resource_user_id; 1126 u64 applet_resource_user_id;
1074 }; 1127 };
1128 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1075 1129
1076 const auto parameters{rp.PopRaw<Parameters>()}; 1130 const auto parameters{rp.PopRaw<Parameters>()};
1077 1131
@@ -1089,9 +1143,10 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
1089 struct Parameters { 1143 struct Parameters {
1090 bool unintended_home_button_input_protection; 1144 bool unintended_home_button_input_protection;
1091 INSERT_PADDING_BYTES_NOINIT(3); 1145 INSERT_PADDING_BYTES_NOINIT(3);
1092 u32 npad_id; 1146 Core::HID::NpadIdType npad_id;
1093 u64 applet_resource_user_id; 1147 u64 applet_resource_user_id;
1094 }; 1148 };
1149 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1095 1150
1096 const auto parameters{rp.PopRaw<Parameters>()}; 1151 const auto parameters{rp.PopRaw<Parameters>()};
1097 1152
@@ -1113,6 +1168,7 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
1113 IPC::RequestParser rp{ctx}; 1168 IPC::RequestParser rp{ctx};
1114 struct Parameters { 1169 struct Parameters {
1115 bool analog_stick_use_center_clamp; 1170 bool analog_stick_use_center_clamp;
1171 INSERT_PADDING_BYTES_NOINIT(7);
1116 u64 applet_resource_user_id; 1172 u64 applet_resource_user_id;
1117 }; 1173 };
1118 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); 1174 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
@@ -1132,38 +1188,38 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
1132 1188
1133void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 1189void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1134 IPC::RequestParser rp{ctx}; 1190 IPC::RequestParser rp{ctx};
1135 const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; 1191 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
1136 1192
1137 VibrationDeviceInfo vibration_device_info; 1193 Core::HID::VibrationDeviceInfo vibration_device_info;
1138 1194
1139 switch (vibration_device_handle.npad_type) { 1195 switch (vibration_device_handle.npad_type) {
1140 case Controller_NPad::NpadType::ProController: 1196 case Core::HID::NpadStyleIndex::ProController:
1141 case Controller_NPad::NpadType::Handheld: 1197 case Core::HID::NpadStyleIndex::Handheld:
1142 case Controller_NPad::NpadType::JoyconDual: 1198 case Core::HID::NpadStyleIndex::JoyconDual:
1143 case Controller_NPad::NpadType::JoyconLeft: 1199 case Core::HID::NpadStyleIndex::JoyconLeft:
1144 case Controller_NPad::NpadType::JoyconRight: 1200 case Core::HID::NpadStyleIndex::JoyconRight:
1145 default: 1201 default:
1146 vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; 1202 vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
1147 break; 1203 break;
1148 case Controller_NPad::NpadType::GameCube: 1204 case Core::HID::NpadStyleIndex::GameCube:
1149 vibration_device_info.type = VibrationDeviceType::GcErm; 1205 vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
1150 break; 1206 break;
1151 case Controller_NPad::NpadType::Pokeball: 1207 case Core::HID::NpadStyleIndex::Pokeball:
1152 vibration_device_info.type = VibrationDeviceType::Unknown; 1208 vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
1153 break; 1209 break;
1154 } 1210 }
1155 1211
1156 switch (vibration_device_handle.device_index) { 1212 switch (vibration_device_handle.device_index) {
1157 case Controller_NPad::DeviceIndex::Left: 1213 case Core::HID::DeviceIndex::Left:
1158 vibration_device_info.position = VibrationDevicePosition::Left; 1214 vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
1159 break; 1215 break;
1160 case Controller_NPad::DeviceIndex::Right: 1216 case Core::HID::DeviceIndex::Right:
1161 vibration_device_info.position = VibrationDevicePosition::Right; 1217 vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
1162 break; 1218 break;
1163 case Controller_NPad::DeviceIndex::None: 1219 case Core::HID::DeviceIndex::None:
1164 default: 1220 default:
1165 UNREACHABLE_MSG("DeviceIndex should never be None!"); 1221 UNREACHABLE_MSG("DeviceIndex should never be None!");
1166 vibration_device_info.position = VibrationDevicePosition::None; 1222 vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
1167 break; 1223 break;
1168 } 1224 }
1169 1225
@@ -1178,11 +1234,12 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1178void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { 1234void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
1179 IPC::RequestParser rp{ctx}; 1235 IPC::RequestParser rp{ctx};
1180 struct Parameters { 1236 struct Parameters {
1181 Controller_NPad::DeviceHandle vibration_device_handle; 1237 Core::HID::VibrationDeviceHandle vibration_device_handle;
1182 Controller_NPad::VibrationValue vibration_value; 1238 Core::HID::VibrationValue vibration_value;
1183 INSERT_PADDING_WORDS_NOINIT(1); 1239 INSERT_PADDING_WORDS_NOINIT(1);
1184 u64 applet_resource_user_id; 1240 u64 applet_resource_user_id;
1185 }; 1241 };
1242 static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
1186 1243
1187 const auto parameters{rp.PopRaw<Parameters>()}; 1244 const auto parameters{rp.PopRaw<Parameters>()};
1188 1245
@@ -1202,10 +1259,11 @@ void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
1202void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { 1259void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
1203 IPC::RequestParser rp{ctx}; 1260 IPC::RequestParser rp{ctx};
1204 struct Parameters { 1261 struct Parameters {
1205 Controller_NPad::DeviceHandle vibration_device_handle; 1262 Core::HID::VibrationDeviceHandle vibration_device_handle;
1206 INSERT_PADDING_WORDS_NOINIT(1); 1263 INSERT_PADDING_WORDS_NOINIT(1);
1207 u64 applet_resource_user_id; 1264 u64 applet_resource_user_id;
1208 }; 1265 };
1266 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1209 1267
1210 const auto parameters{rp.PopRaw<Parameters>()}; 1268 const auto parameters{rp.PopRaw<Parameters>()};
1211 1269
@@ -1256,10 +1314,10 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
1256 const auto handles = ctx.ReadBuffer(0); 1314 const auto handles = ctx.ReadBuffer(0);
1257 const auto vibrations = ctx.ReadBuffer(1); 1315 const auto vibrations = ctx.ReadBuffer(1);
1258 1316
1259 std::vector<Controller_NPad::DeviceHandle> vibration_device_handles( 1317 std::vector<Core::HID::VibrationDeviceHandle> vibration_device_handles(
1260 handles.size() / sizeof(Controller_NPad::DeviceHandle)); 1318 handles.size() / sizeof(Core::HID::VibrationDeviceHandle));
1261 std::vector<Controller_NPad::VibrationValue> vibration_values( 1319 std::vector<Core::HID::VibrationValue> vibration_values(vibrations.size() /
1262 vibrations.size() / sizeof(Controller_NPad::VibrationValue)); 1320 sizeof(Core::HID::VibrationValue));
1263 1321
1264 std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); 1322 std::memcpy(vibration_device_handles.data(), handles.data(), handles.size());
1265 std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); 1323 std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size());
@@ -1276,9 +1334,10 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
1276void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { 1334void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1277 IPC::RequestParser rp{ctx}; 1335 IPC::RequestParser rp{ctx};
1278 struct Parameters { 1336 struct Parameters {
1279 Controller_NPad::DeviceHandle vibration_device_handle; 1337 Core::HID::VibrationDeviceHandle vibration_device_handle;
1338 INSERT_PADDING_WORDS_NOINIT(1);
1280 u64 applet_resource_user_id; 1339 u64 applet_resource_user_id;
1281 VibrationGcErmCommand gc_erm_command; 1340 Core::HID::VibrationGcErmCommand gc_erm_command;
1282 }; 1341 };
1283 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 1342 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1284 1343
@@ -1292,26 +1351,26 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1292 */ 1351 */
1293 const auto vibration_value = [parameters] { 1352 const auto vibration_value = [parameters] {
1294 switch (parameters.gc_erm_command) { 1353 switch (parameters.gc_erm_command) {
1295 case VibrationGcErmCommand::Stop: 1354 case Core::HID::VibrationGcErmCommand::Stop:
1296 return Controller_NPad::VibrationValue{ 1355 return Core::HID::VibrationValue{
1297 .amp_low = 0.0f, 1356 .low_amplitude = 0.0f,
1298 .freq_low = 160.0f, 1357 .low_frequency = 160.0f,
1299 .amp_high = 0.0f, 1358 .high_amplitude = 0.0f,
1300 .freq_high = 320.0f, 1359 .high_frequency = 320.0f,
1301 }; 1360 };
1302 case VibrationGcErmCommand::Start: 1361 case Core::HID::VibrationGcErmCommand::Start:
1303 return Controller_NPad::VibrationValue{ 1362 return Core::HID::VibrationValue{
1304 .amp_low = 1.0f, 1363 .low_amplitude = 1.0f,
1305 .freq_low = 160.0f, 1364 .low_frequency = 160.0f,
1306 .amp_high = 1.0f, 1365 .high_amplitude = 1.0f,
1307 .freq_high = 320.0f, 1366 .high_frequency = 320.0f,
1308 }; 1367 };
1309 case VibrationGcErmCommand::StopHard: 1368 case Core::HID::VibrationGcErmCommand::StopHard:
1310 return Controller_NPad::VibrationValue{ 1369 return Core::HID::VibrationValue{
1311 .amp_low = 0.0f, 1370 .low_amplitude = 0.0f,
1312 .freq_low = 0.0f, 1371 .low_frequency = 0.0f,
1313 .amp_high = 0.0f, 1372 .high_amplitude = 0.0f,
1314 .freq_high = 0.0f, 1373 .high_frequency = 0.0f,
1315 }; 1374 };
1316 default: 1375 default:
1317 return Controller_NPad::DEFAULT_VIBRATION_VALUE; 1376 return Controller_NPad::DEFAULT_VIBRATION_VALUE;
@@ -1336,7 +1395,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1336void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) { 1395void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1337 IPC::RequestParser rp{ctx}; 1396 IPC::RequestParser rp{ctx};
1338 struct Parameters { 1397 struct Parameters {
1339 Controller_NPad::DeviceHandle vibration_device_handle; 1398 Core::HID::VibrationDeviceHandle vibration_device_handle;
1340 INSERT_PADDING_WORDS_NOINIT(1); 1399 INSERT_PADDING_WORDS_NOINIT(1);
1341 u64 applet_resource_user_id; 1400 u64 applet_resource_user_id;
1342 }; 1401 };
@@ -1347,8 +1406,8 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1347 .GetLastVibration(parameters.vibration_device_handle); 1406 .GetLastVibration(parameters.vibration_device_handle);
1348 1407
1349 const auto gc_erm_command = [last_vibration] { 1408 const auto gc_erm_command = [last_vibration] {
1350 if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) { 1409 if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
1351 return VibrationGcErmCommand::Start; 1410 return Core::HID::VibrationGcErmCommand::Start;
1352 } 1411 }
1353 1412
1354 /** 1413 /**
@@ -1357,11 +1416,11 @@ void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1357 * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. 1416 * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
1358 * This is done to reuse the controller vibration functions made for regular controllers. 1417 * This is done to reuse the controller vibration functions made for regular controllers.
1359 */ 1418 */
1360 if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) { 1419 if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
1361 return VibrationGcErmCommand::StopHard; 1420 return Core::HID::VibrationGcErmCommand::StopHard;
1362 } 1421 }
1363 1422
1364 return VibrationGcErmCommand::Stop; 1423 return Core::HID::VibrationGcErmCommand::Stop;
1365 }(); 1424 }();
1366 1425
1367 LOG_DEBUG(Service_HID, 1426 LOG_DEBUG(Service_HID,
@@ -1401,10 +1460,11 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
1401void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { 1460void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) {
1402 IPC::RequestParser rp{ctx}; 1461 IPC::RequestParser rp{ctx};
1403 struct Parameters { 1462 struct Parameters {
1404 Controller_NPad::DeviceHandle vibration_device_handle; 1463 Core::HID::VibrationDeviceHandle vibration_device_handle;
1405 INSERT_PADDING_WORDS_NOINIT(1); 1464 INSERT_PADDING_WORDS_NOINIT(1);
1406 u64 applet_resource_user_id; 1465 u64 applet_resource_user_id;
1407 }; 1466 };
1467 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1408 1468
1409 const auto parameters{rp.PopRaw<Parameters>()}; 1469 const auto parameters{rp.PopRaw<Parameters>()};
1410 1470
@@ -1435,18 +1495,18 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
1435void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { 1495void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
1436 IPC::RequestParser rp{ctx}; 1496 IPC::RequestParser rp{ctx};
1437 struct Parameters { 1497 struct Parameters {
1438 Controller_NPad::DeviceHandle sixaxis_handle; 1498 Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
1439 INSERT_PADDING_WORDS_NOINIT(1); 1499 INSERT_PADDING_WORDS_NOINIT(1);
1440 u64 applet_resource_user_id; 1500 u64 applet_resource_user_id;
1441 }; 1501 };
1502 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1442 1503
1443 const auto parameters{rp.PopRaw<Parameters>()}; 1504 const auto parameters{rp.PopRaw<Parameters>()};
1444 1505
1445 LOG_WARNING( 1506 LOG_WARNING(Service_HID,
1446 Service_HID, 1507 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
1447 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 1508 parameters.console_sixaxis_handle.unknown_1,
1448 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, 1509 parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
1449 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
1450 1510
1451 IPC::ResponseBuilder rb{ctx, 2}; 1511 IPC::ResponseBuilder rb{ctx, 2};
1452 rb.Push(ResultSuccess); 1512 rb.Push(ResultSuccess);
@@ -1455,18 +1515,18 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
1455void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { 1515void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
1456 IPC::RequestParser rp{ctx}; 1516 IPC::RequestParser rp{ctx};
1457 struct Parameters { 1517 struct Parameters {
1458 Controller_NPad::DeviceHandle sixaxis_handle; 1518 Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
1459 INSERT_PADDING_WORDS_NOINIT(1); 1519 INSERT_PADDING_WORDS_NOINIT(1);
1460 u64 applet_resource_user_id; 1520 u64 applet_resource_user_id;
1461 }; 1521 };
1522 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1462 1523
1463 const auto parameters{rp.PopRaw<Parameters>()}; 1524 const auto parameters{rp.PopRaw<Parameters>()};
1464 1525
1465 LOG_WARNING( 1526 LOG_WARNING(Service_HID,
1466 Service_HID, 1527 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
1467 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 1528 parameters.console_sixaxis_handle.unknown_1,
1468 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, 1529 parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
1469 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
1470 1530
1471 IPC::ResponseBuilder rb{ctx, 2}; 1531 IPC::ResponseBuilder rb{ctx, 2};
1472 rb.Push(ResultSuccess); 1532 rb.Push(ResultSuccess);
@@ -1620,10 +1680,8 @@ void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
1620 1680
1621void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { 1681void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
1622 IPC::RequestParser rp{ctx}; 1682 IPC::RequestParser rp{ctx};
1623 const auto applet_resource_user_id{rp.Pop<u64>()};
1624 1683
1625 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", 1684 LOG_WARNING(Service_HID, "(STUBBED) called");
1626 applet_resource_user_id);
1627 1685
1628 IPC::ResponseBuilder rb{ctx, 4}; 1686 IPC::ResponseBuilder rb{ctx, 4};
1629 rb.Push(ResultSuccess); 1687 rb.Push(ResultSuccess);
@@ -2037,10 +2095,6 @@ public:
2037 } 2095 }
2038}; 2096};
2039 2097
2040void ReloadInputDevices() {
2041 Settings::values.is_device_reload_pending.store(true);
2042}
2043
2044void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { 2098void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
2045 std::make_shared<Hid>(system)->InstallAsService(service_manager); 2099 std::make_shared<Hid>(system)->InstallAsService(service_manager);
2046 std::make_shared<HidBus>(system)->InstallAsService(service_manager); 2100 std::make_shared<HidBus>(system)->InstallAsService(service_manager);
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index b1fe75e94..ab0084118 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -60,21 +60,23 @@ public:
60private: 60private:
61 template <typename T> 61 template <typename T>
62 void MakeController(HidController controller) { 62 void MakeController(HidController controller) {
63 controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system); 63 controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system.HIDCore());
64 } 64 }
65 template <typename T> 65 template <typename T>
66 void MakeControllerWithServiceContext(HidController controller) { 66 void MakeControllerWithServiceContext(HidController controller) {
67 controllers[static_cast<std::size_t>(controller)] = 67 controllers[static_cast<std::size_t>(controller)] =
68 std::make_unique<T>(system, service_context); 68 std::make_unique<T>(system.HIDCore(), service_context);
69 } 69 }
70 70
71 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); 71 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
72 void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); 72 void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
73 void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
73 void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); 74 void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
74 75
75 KernelHelpers::ServiceContext& service_context; 76 KernelHelpers::ServiceContext& service_context;
76 77
77 std::shared_ptr<Core::Timing::EventType> pad_update_event; 78 std::shared_ptr<Core::Timing::EventType> pad_update_event;
79 std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
78 std::shared_ptr<Core::Timing::EventType> motion_update_event; 80 std::shared_ptr<Core::Timing::EventType> motion_update_event;
79 81
80 std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)> 82 std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
@@ -161,38 +163,11 @@ private:
161 void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); 163 void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx);
162 void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx); 164 void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx);
163 165
164 enum class VibrationDeviceType : u32 {
165 Unknown = 0,
166 LinearResonantActuator = 1,
167 GcErm = 2,
168 };
169
170 enum class VibrationDevicePosition : u32 {
171 None = 0,
172 Left = 1,
173 Right = 2,
174 };
175
176 enum class VibrationGcErmCommand : u64 {
177 Stop = 0,
178 Start = 1,
179 StopHard = 2,
180 };
181
182 struct VibrationDeviceInfo {
183 VibrationDeviceType type{};
184 VibrationDevicePosition position{};
185 };
186 static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size.");
187
188 std::shared_ptr<IAppletResource> applet_resource; 166 std::shared_ptr<IAppletResource> applet_resource;
189 167
190 KernelHelpers::ServiceContext service_context; 168 KernelHelpers::ServiceContext service_context;
191}; 169};
192 170
193/// Reload input devices. Used when input configuration changed
194void ReloadInputDevices();
195
196/// Registers all HID services with the specified service manager. 171/// Registers all HID services with the specified service manager.
197void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); 172void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
198 173
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
new file mode 100644
index 000000000..44c20d967
--- /dev/null
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -0,0 +1,54 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included
4
5#pragma once
6
7#include <array>
8
9#include "common/common_types.h"
10
11namespace Service::HID {
12
13template <typename State>
14struct AtomicStorage {
15 s64 sampling_number;
16 State state;
17};
18
19template <typename State, std::size_t max_buffer_size>
20struct Lifo {
21 s64 timestamp{};
22 s64 total_buffer_count = static_cast<s64>(max_buffer_size);
23 s64 buffer_tail{};
24 s64 buffer_count{};
25 std::array<AtomicStorage<State>, max_buffer_size> entries{};
26
27 const AtomicStorage<State>& ReadCurrentEntry() const {
28 return entries[buffer_tail];
29 }
30
31 const AtomicStorage<State>& ReadPreviousEntry() const {
32 return entries[GetPreviousEntryIndex()];
33 }
34
35 std::size_t GetPreviousEntryIndex() const {
36 return static_cast<size_t>((buffer_tail + total_buffer_count - 1) % total_buffer_count);
37 }
38
39 std::size_t GetNextEntryIndex() const {
40 return static_cast<size_t>((buffer_tail + 1) % total_buffer_count);
41 }
42
43 void WriteNextEntry(const State& new_state) {
44 if (buffer_count < total_buffer_count - 1) {
45 buffer_count++;
46 }
47 buffer_tail = GetNextEntryIndex();
48 const auto& previous_entry = ReadPreviousEntry();
49 entries[buffer_tail].sampling_number = previous_entry.sampling_number + 1;
50 entries[buffer_tail].state = new_state;
51 }
52};
53
54} // namespace Service::HID