From f30ef987615729f5a3b8eab524ce5680369057e9 Mon Sep 17 00:00:00 2001
From: german <german@thesoftwareartisans.com>
Date: Sun, 10 Jan 2021 11:37:19 -0600
Subject: Adds missing controller types and properties

---
 src/core/hle/service/hid/controllers/keyboard.cpp | 17 ++++--
 src/core/hle/service/hid/controllers/keyboard.h   | 21 ++++++-
 src/core/hle/service/hid/controllers/mouse.cpp    | 12 ++--
 src/core/hle/service/hid/controllers/mouse.h      | 26 ++++++++-
 src/core/hle/service/hid/controllers/npad.cpp     | 12 ++++
 src/core/hle/service/hid/controllers/npad.h       | 33 ++++++++++-
 src/core/hle/service/hid/controllers/xpad.h       | 70 +++++++++++++++++++++--
 src/core/hle/service/hid/hid.cpp                  | 20 ++++---
 src/core/hle/service/hid/hid.h                    | 10 ++--
 9 files changed, 191 insertions(+), 30 deletions(-)

(limited to 'src/core/hle/service/hid')

diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 59b694cd4..fd5d5e057 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -39,16 +39,25 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
     cur_entry.sampling_number2 = cur_entry.sampling_number;
 
     cur_entry.key.fill(0);
-    cur_entry.modifier = 0;
     if (Settings::values.keyboard_enabled) {
         for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
             auto& entry = cur_entry.key[i / KEYS_PER_BYTE];
             entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
         }
 
-        for (std::size_t i = 0; i < keyboard_mods.size(); ++i) {
-            cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i);
-        }
+        using namespace Settings::NativeKeyboard;
+
+        // TODO: Assign the correct key to all modifiers
+        cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus());
+        cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus());
+        cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus());
+        cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus());
+        cur_entry.modifier.gui.Assign(0);
+        cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus());
+        cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus());
+        cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus());
+        cur_entry.modifier.katana.Assign(0);
+        cur_entry.modifier.hiragana.Assign(0);
     }
     std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
 }
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index f3eef5936..8a89eb4bb 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <array>
+#include "common/bit_field.h"
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/swap.h"
@@ -31,12 +32,28 @@ public:
     void OnLoadInputDevices() override;
 
 private:
+    struct Modifiers {
+        union {
+            s32_le raw{};
+            BitField<0, 1, u32> control;
+            BitField<1, 1, u32> shift;
+            BitField<2, 1, u32> left_alt;
+            BitField<3, 1, u32> right_alt;
+            BitField<4, 1, u32> gui;
+            BitField<8, 1, u32> caps_lock;
+            BitField<9, 1, u32> scroll_lock;
+            BitField<10, 1, u32> num_lock;
+            BitField<11, 1, u32> katana;
+            BitField<12, 1, u32> hiragana;
+        };
+    };
+    static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size");
+
     struct KeyboardState {
         s64_le sampling_number;
         s64_le sampling_number2;
 
-        s32_le modifier;
-        s32_le attribute;
+        Modifiers modifier;
         std::array<u8, 32> key;
     };
     static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size");
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index ac40989c5..30924d9e2 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -35,7 +35,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
 
     cur_entry.sampling_number = last_entry.sampling_number + 1;
     cur_entry.sampling_number2 = cur_entry.sampling_number;
-
+    cur_entry.attribute.raw = 0;
     if (Settings::values.mouse_enabled) {
         const auto [px, py, sx, sy] = mouse_device->GetStatus();
         const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width);
@@ -46,10 +46,14 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
         cur_entry.delta_y = y - last_entry.y;
         cur_entry.mouse_wheel_x = sx;
         cur_entry.mouse_wheel_y = sy;
+        cur_entry.attribute.is_connected.Assign(1);
 
-        for (std::size_t i = 0; i < mouse_button_devices.size(); ++i) {
-            cur_entry.button |= (mouse_button_devices[i]->GetStatus() << i);
-        }
+        using namespace Settings::NativeMouseButton;
+        cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus());
+        cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus());
+        cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus());
+        cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus());
+        cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus());
     }
 
     std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 357ab7107..2c8ebe1d5 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <array>
+#include "common/bit_field.h"
 #include "common/common_types.h"
 #include "common/swap.h"
 #include "core/frontend/input.h"
@@ -30,6 +31,27 @@ public:
     void OnLoadInputDevices() override;
 
 private:
+    struct Buttons {
+        union {
+            s32_le raw{};
+            BitField<0, 1, u32> left;
+            BitField<1, 1, u32> right;
+            BitField<2, 1, u32> middle;
+            BitField<3, 1, u32> forward;
+            BitField<4, 1, u32> back;
+        };
+    };
+    static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size");
+
+    struct Attributes {
+        union {
+            s32_le raw{};
+            BitField<0, 1, u32> transferable;
+            BitField<1, 1, u32> is_connected;
+        };
+    };
+    static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
+
     struct MouseState {
         s64_le sampling_number;
         s64_le sampling_number2;
@@ -39,8 +61,8 @@ private:
         s32_le delta_y;
         s32_le mouse_wheel_x;
         s32_le mouse_wheel_y;
-        s32_le button;
-        s32_le attribute;
+        Buttons button;
+        Attributes attribute;
     };
     static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size");
 
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 0c227b135..251db1f84 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -609,7 +609,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             UNREACHABLE();
             break;
         case NPadControllerType::ProController:
+            full_sixaxis_entry.attribute.raw = 0;
             if (sixaxis_sensors_enabled && motions[i][0]) {
+                full_sixaxis_entry.attribute.IsConnected.Assign(1);
                 full_sixaxis_entry.accel = motion_devices[0].accel;
                 full_sixaxis_entry.gyro = motion_devices[0].gyro;
                 full_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -617,7 +619,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             }
             break;
         case NPadControllerType::Handheld:
+            handheld_sixaxis_entry.attribute.raw = 0;
             if (sixaxis_sensors_enabled && motions[i][0]) {
+                handheld_sixaxis_entry.attribute.IsConnected.Assign(1);
                 handheld_sixaxis_entry.accel = motion_devices[0].accel;
                 handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
                 handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -625,8 +629,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             }
             break;
         case NPadControllerType::JoyDual:
+            dual_left_sixaxis_entry.attribute.raw = 0;
+            dual_right_sixaxis_entry.attribute.raw = 0;
             if (sixaxis_sensors_enabled && motions[i][0]) {
                 // Set motion for the left joycon
+                dual_left_sixaxis_entry.attribute.IsConnected.Assign(1);
                 dual_left_sixaxis_entry.accel = motion_devices[0].accel;
                 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
                 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -634,6 +641,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             }
             if (sixaxis_sensors_enabled && motions[i][1]) {
                 // Set motion for the right joycon
+                dual_right_sixaxis_entry.attribute.IsConnected.Assign(1);
                 dual_right_sixaxis_entry.accel = motion_devices[1].accel;
                 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
                 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -641,7 +649,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             }
             break;
         case NPadControllerType::JoyLeft:
+            left_sixaxis_entry.attribute.raw = 0;
             if (sixaxis_sensors_enabled && motions[i][0]) {
+                left_sixaxis_entry.attribute.IsConnected.Assign(1);
                 left_sixaxis_entry.accel = motion_devices[0].accel;
                 left_sixaxis_entry.gyro = motion_devices[0].gyro;
                 left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -649,7 +659,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
             }
             break;
         case NPadControllerType::JoyRight:
+            right_sixaxis_entry.attribute.raw = 0;
             if (sixaxis_sensors_enabled && motions[i][1]) {
+                right_sixaxis_entry.attribute.IsConnected.Assign(1);
                 right_sixaxis_entry.accel = motion_devices[1].accel;
                 right_sixaxis_entry.gyro = motion_devices[1].gyro;
                 right_sixaxis_entry.rotation = motion_devices[1].rotation;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 2e13922b9..e5778921f 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -113,8 +113,13 @@ public:
             BitField<2, 1, u32> joycon_dual;
             BitField<3, 1, u32> joycon_left;
             BitField<4, 1, u32> joycon_right;
-
-            BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible
+            BitField<5, 1, u32> gamecube;
+            BitField<6, 1, u32> pokeball;
+            BitField<7, 1, u32> lark;
+            BitField<8, 1, u32> handheld_lark;
+            BitField<9, 1, u32> lucia;
+            BitField<29, 1, u32> system_ext;
+            BitField<30, 1, u32> system;
         };
     };
     static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
@@ -285,6 +290,9 @@ private:
 
             BitField<26, 1, u64> right_sl;
             BitField<27, 1, u64> right_sr;
+
+            BitField<28, 1, u64> palma;
+            BitField<30, 1, u64> handheld_left_b;
         };
     };
     static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
@@ -329,6 +337,15 @@ private:
     };
     static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
 
+    struct SixAxisAttributes {
+        union {
+            u32_le raw{};
+            BitField<0, 1, u32> IsConnected;
+            BitField<1, 1, u32> IsInterpolated;
+        };
+    };
+    static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size");
+
     struct SixAxisStates {
         s64_le timestamp{};
         INSERT_PADDING_WORDS(2);
@@ -337,7 +354,8 @@ private:
         Common::Vec3f gyro{};
         Common::Vec3f rotation{};
         std::array<Common::Vec3f, 3> orientation{};
-        s64_le always_one{1};
+        SixAxisAttributes attribute;
+        INSERT_PADDING_BYTES(4); // Reserved
     };
     static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
 
@@ -356,10 +374,19 @@ private:
     struct NPadProperties {
         union {
             s64_le raw{};
+            BitField<0, 1, s64> is_charging_joy_dual;
+            BitField<1, 1, s64> is_charging_joy_left;
+            BitField<2, 1, s64> is_charging_joy_right;
+            BitField<3, 1, s64> is_powered_joy_dual;
+            BitField<4, 1, s64> is_powered_joy_left;
+            BitField<5, 1, s64> is_powered_joy_right;
+            BitField<9, 1, s64> is_system_unsuported_button;
+            BitField<10, 1, s64> is_system_ext_unsuported_button;
             BitField<11, 1, s64> is_vertical;
             BitField<12, 1, s64> is_horizontal;
             BitField<13, 1, s64> use_plus;
             BitField<14, 1, s64> use_minus;
+            BitField<15, 1, s64> use_directional_buttons;
         };
     };
 
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index ad229787c..d91cf62a2 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include "common/bit_field.h"
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/swap.h"
@@ -28,6 +29,67 @@ public:
     void OnLoadInputDevices() override;
 
 private:
+    struct Attributes {
+        union {
+            s32_le raw{};
+            BitField<0, 1, u32> IsConnected;
+            BitField<1, 1, u32> IsWired;
+            BitField<2, 1, u32> IsLeftConnected;
+            BitField<3, 1, u32> IsLeftWired;
+            BitField<4, 1, u32> IsRightConnected;
+            BitField<5, 1, u32> IsRightWired;
+        };
+    };
+    static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size");
+
+    struct Buttons {
+        union {
+            u32_le raw{};
+            // Button states
+            BitField<0, 1, u32> a;
+            BitField<1, 1, u32> b;
+            BitField<2, 1, u32> x;
+            BitField<3, 1, u32> y;
+            BitField<4, 1, u32> l_stick;
+            BitField<5, 1, u32> r_stick;
+            BitField<6, 1, u32> l;
+            BitField<7, 1, u32> r;
+            BitField<8, 1, u32> zl;
+            BitField<9, 1, u32> zr;
+            BitField<10, 1, u32> plus;
+            BitField<11, 1, u32> minus;
+
+            // D-Pad
+            BitField<12, 1, u32> d_left;
+            BitField<13, 1, u32> d_up;
+            BitField<14, 1, u32> d_right;
+            BitField<15, 1, u32> d_down;
+
+            // Left JoyStick
+            BitField<16, 1, u32> l_stick_left;
+            BitField<17, 1, u32> l_stick_up;
+            BitField<18, 1, u32> l_stick_right;
+            BitField<19, 1, u32> l_stick_down;
+
+            // Right JoyStick
+            BitField<20, 1, u32> r_stick_left;
+            BitField<21, 1, u32> r_stick_up;
+            BitField<22, 1, u32> r_stick_right;
+            BitField<23, 1, u32> r_stick_down;
+
+            // Not always active?
+            BitField<24, 1, u32> left_sl;
+            BitField<25, 1, u32> left_sr;
+
+            BitField<26, 1, u32> right_sl;
+            BitField<27, 1, u32> right_sr;
+
+            BitField<28, 1, u32> palma;
+            BitField<30, 1, u32> handheld_left_b;
+        };
+    };
+    static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size");
+
     struct AnalogStick {
         s32_le x;
         s32_le y;
@@ -37,10 +99,10 @@ private:
     struct XPadState {
         s64_le sampling_number;
         s64_le sampling_number2;
-        s32_le attributes;
-        u32_le pad_states;
-        AnalogStick x_stick;
-        AnalogStick y_stick;
+        Attributes attributes;
+        Buttons pad_states;
+        AnalogStick l_stick;
+        AnalogStick r_stick;
     };
     static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size");
 
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 4cee4838c..370e266a8 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -59,20 +59,26 @@ IAppletResource::IAppletResource(Core::System& system_)
     MakeController<Controller_Mouse>(HidController::Mouse);
     MakeController<Controller_Keyboard>(HidController::Keyboard);
     MakeController<Controller_XPad>(HidController::XPad);
-    MakeController<Controller_Stubbed>(HidController::Unknown1);
-    MakeController<Controller_Stubbed>(HidController::Unknown2);
-    MakeController<Controller_Stubbed>(HidController::Unknown3);
-    MakeController<Controller_Stubbed>(HidController::SixAxisSensor);
+    MakeController<Controller_Stubbed>(HidController::HomeButton);
+    MakeController<Controller_Stubbed>(HidController::SleepButton);
+    MakeController<Controller_Stubbed>(HidController::CaptureButton);
+    MakeController<Controller_Stubbed>(HidController::InputDetector);
+    MakeController<Controller_Stubbed>(HidController::UniquePad);
     MakeController<Controller_NPad>(HidController::NPad);
     MakeController<Controller_Gesture>(HidController::Gesture);
+    MakeController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor);
 
     // Homebrew doesn't try to activate some controllers, so we activate them by default
     GetController<Controller_NPad>(HidController::NPad).ActivateController();
     GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController();
 
-    GetController<Controller_Stubbed>(HidController::Unknown1).SetCommonHeaderOffset(0x4c00);
-    GetController<Controller_Stubbed>(HidController::Unknown2).SetCommonHeaderOffset(0x4e00);
-    GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000);
+    GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
+    GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
+    GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
+    GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
+    GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
+    GetController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor)
+        .SetCommonHeaderOffset(0x3C200);
 
     // Register update callbacks
     pad_update_event = Core::Timing::CreateEvent(
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index d991bd721..7cc0433e2 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -29,12 +29,14 @@ enum class HidController : std::size_t {
     Mouse,
     Keyboard,
     XPad,
-    Unknown1,
-    Unknown2,
-    Unknown3,
-    SixAxisSensor,
+    HomeButton,
+    SleepButton,
+    CaptureButton,
+    InputDetector,
+    UniquePad,
     NPad,
     Gesture,
+    ConsoleSixAxisSensor,
 
     MaxControllers,
 };
-- 
cgit v1.2.3