diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp
index 70a494097a..874780ec28 100644
--- a/src/core/hid/emulated_devices.cpp
+++ b/src/core/hid/emulated_devices.cpp
@@ -376,9 +376,9 @@ void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std
 
 void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
     std::lock_guard lock{mutex};
-    const auto stick_value = TransformToStick(callback);
+    const auto touch_value = TransformToTouch(callback);
 
-    device_status.mouse_stick_value = stick_value;
+    device_status.mouse_stick_value = touch_value;
 
     if (is_configuring) {
         device_status.mouse_position_state = {};
@@ -386,8 +386,8 @@ void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
         return;
     }
 
-    device_status.mouse_position_state.x = stick_value.x.value;
-    device_status.mouse_position_state.y = stick_value.y.value;
+    device_status.mouse_position_state.x = touch_value.x.value;
+    device_status.mouse_position_state.y = touch_value.y.value;
 
     TriggerOnChange(DeviceTriggerType::Mouse);
 }
@@ -420,7 +420,7 @@ MousePosition EmulatedDevices::GetMousePosition() const {
     return device_status.mouse_position_state;
 }
 
-AnalogStickState EmulatedDevices::GetMouseDeltaWheel() const {
+AnalogStickState EmulatedDevices::GetMouseWheel() const {
     return device_status.mouse_wheel_state;
 }
 
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h
index 49edfd255b..05a945d083 100644
--- a/src/core/hid/emulated_devices.h
+++ b/src/core/hid/emulated_devices.h
@@ -38,7 +38,7 @@ using MouseButtonValues =
     std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
 using MouseAnalogValues =
     std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>;
-using MouseStickValue = Common::Input::StickStatus;
+using MouseStickValue = Common::Input::TouchStatus;
 
 struct MousePosition {
     f32 x;
@@ -130,7 +130,7 @@ public:
     MousePosition GetMousePosition() const;
 
     /// Returns the latest mouse wheel change
-    AnalogStickState GetMouseDeltaWheel() const;
+    AnalogStickState GetMouseWheel() const;
 
     /**
      * Adds a callback to the list of events
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index af95f3aff9..8b12f63ad9 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -502,21 +502,30 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor
 // This is nn::hid::KeyboardModifier
 struct KeyboardModifier {
     union {
-        u64 raw{};
-        BitField<0, 1, u64> control;
-        BitField<1, 1, u64> shift;
-        BitField<2, 1, u64> left_alt;
-        BitField<3, 1, u64> right_alt;
-        BitField<4, 1, u64> gui;
-        BitField<8, 1, u64> caps_lock;
-        BitField<9, 1, u64> scroll_lock;
-        BitField<10, 1, u64> num_lock;
-        BitField<11, 1, u64> katakana;
-        BitField<12, 1, u64> hiragana;
-        BitField<32, 1, u64> unknown;
+        u32 raw{};
+        BitField<0, 1, u32> control;
+        BitField<1, 1, u32> shift;
+        BitField<2, 1, u32> left_alt;
+        BitField<3, 1, u32> right_alt;
+        BitField<4, 1, u32> gui;
+        BitField<8, 1, u32> caps_lock;
+        BitField<9, 1, u32> scroll_lock;
+        BitField<10, 1, u32> num_lock;
+        BitField<11, 1, u32> katakana;
+        BitField<12, 1, u32> hiragana;
     };
 };
-static_assert(sizeof(KeyboardModifier) == 0x8, "KeyboardModifier is an invalid size");
+
+static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size");
+
+// This is nn::hid::KeyboardAttribute
+struct KeyboardAttribute {
+    union {
+        u32 raw{};
+        BitField<0, 1, u32> is_connected;
+    };
+};
+static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid size");
 
 // This is nn::hid::KeyboardKey
 struct KeyboardKey {
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index c4e6539568..f5acff6e0f 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -175,6 +175,10 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
     case Common::Input::InputType::Touch:
         status = callback.touch_status;
         break;
+    case Common::Input::InputType::Stick:
+        status.x = callback.stick_status.x;
+        status.y = callback.stick_status.y;
+        break;
     default:
         LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type);
         break;
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 0ef8af0e69..9588a69101 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -42,8 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
 
         next_state.key = keyboard_state;
         next_state.modifier = keyboard_modifier_state;
-        // This is always enabled on HW. Check what it actually does
-        next_state.modifier.unknown.Assign(1);
+        next_state.attribute.is_connected.Assign(1);
     }
 
     keyboard_lifo.WriteNextEntry(next_state);
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index ec5dd607cb..0d61cb4709 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -38,6 +38,7 @@ private:
     struct KeyboardState {
         s64 sampling_number;
         Core::HID::KeyboardModifier modifier;
+        Core::HID::KeyboardAttribute attribute;
         Core::HID::KeyboardKey key;
     };
     static_assert(sizeof(KeyboardState) == 0x30, "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 9c408e7f40..ba79888ae0 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -38,15 +38,16 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
     if (Settings::values.mouse_enabled) {
         const auto& mouse_button_state = emulated_devices->GetMouseButtons();
         const auto& mouse_position_state = emulated_devices->GetMousePosition();
-        const auto& mouse_wheel_state = emulated_devices->GetMouseDeltaWheel();
+        const auto& mouse_wheel_state = emulated_devices->GetMouseWheel();
         next_state.attribute.is_connected.Assign(1);
         next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width);
         next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height);
         next_state.delta_x = next_state.x - last_entry.x;
         next_state.delta_y = next_state.y - last_entry.y;
-        next_state.delta_wheel_x = mouse_wheel_state.x;
-        next_state.delta_wheel_y = mouse_wheel_state.y;
+        next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x;
+        next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y;
 
+        last_mouse_wheel_state = mouse_wheel_state;
         next_state.button = mouse_button_state;
     }
 
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 25017f1173..1ac69aa6ff 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -14,6 +14,7 @@
 namespace Core::HID {
 class EmulatedDevices;
 struct MouseState;
+struct AnalogStickState;
 } // namespace Core::HID
 
 namespace Service::HID {
@@ -37,6 +38,7 @@ private:
     static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
     Core::HID::MouseState next_state{};
 
+    Core::HID::AnalogStickState last_mouse_wheel_state;
     Core::HID::EmulatedDevices* emulated_devices;
 };
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index e740b43314..95fc07325b 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -35,9 +35,9 @@ namespace Service::HID {
 
 // Updating period for each HID device.
 // Period time is obtained by measuring the number of samples in a second on HW using a homebrew
-constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};      // (4ms, 250Hz)
-constexpr auto keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
-constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000};   // (5ms, 200Hz)
+constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};            // (4ms, 250Hz)
+constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
+constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000};         // (5ms, 200Hz)
 constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
 
 IAppletResource::IAppletResource(Core::System& system_,
@@ -79,11 +79,11 @@ IAppletResource::IAppletResource(Core::System& system_,
             const auto guard = LockService();
             UpdateControllers(user_data, ns_late);
         });
-    keyboard_update_event = Core::Timing::CreateEvent(
-        "HID::UpdatekeyboardCallback",
+    mouse_keyboard_update_event = Core::Timing::CreateEvent(
+        "HID::UpdateMouseKeyboardCallback",
         [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
             const auto guard = LockService();
-            UpdateKeyboard(user_data, ns_late);
+            UpdateMouseKeyboard(user_data, ns_late);
         });
     motion_update_event = Core::Timing::CreateEvent(
         "HID::UpdateMotionCallback",
@@ -93,7 +93,7 @@ IAppletResource::IAppletResource(Core::System& system_,
         });
 
     system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
-    system.CoreTiming().ScheduleEvent(keyboard_update_ns, keyboard_update_event);
+    system.CoreTiming().ScheduleEvent(mouse_keyboard_update_ns, mouse_keyboard_update_event);
     system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
 
     system.HIDCore().ReloadInputDevices();
@@ -109,7 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) {
 
 IAppletResource::~IAppletResource() {
     system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
-    system.CoreTiming().UnscheduleEvent(keyboard_update_event, 0);
+    system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
     system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
 }
 
@@ -130,6 +130,10 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
         if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
             continue;
         }
+        // Mouse has it's own update event
+        if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
+            continue;
+        }
         controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(),
                              SHARED_MEMORY_SIZE);
     }
@@ -142,18 +146,21 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
     core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
 }
 
-void IAppletResource::UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
+                                          std::chrono::nanoseconds ns_late) {
     auto& core_timing = system.CoreTiming();
 
+    controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(
+        core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
     controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(
         core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
 
     // If ns_late is higher than the update rate ignore the delay
-    if (ns_late > keyboard_update_ns) {
+    if (ns_late > mouse_keyboard_update_ns) {
         ns_late = {};
     }
 
-    core_timing.ScheduleEvent(keyboard_update_ns - ns_late, keyboard_update_event);
+    core_timing.ScheduleEvent(mouse_keyboard_update_ns - ns_late, mouse_keyboard_update_event);
 }
 
 void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index bbad165f89..ab00841180 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -70,13 +70,13 @@ private:
 
     void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
     void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
-    void UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+    void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
     void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 
     KernelHelpers::ServiceContext& service_context;
 
     std::shared_ptr<Core::Timing::EventType> pad_update_event;
-    std::shared_ptr<Core::Timing::EventType> keyboard_update_event;
+    std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
     std::shared_ptr<Core::Timing::EventType> motion_update_event;
 
     std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 478737db22..05fd7f9c0d 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -39,7 +39,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
     Common::SetCurrentThreadName("yuzu:input:Mouse");
     constexpr int update_time = 10;
     while (!stop_token.stop_requested()) {
-        if (Settings::values.mouse_panning) {
+        if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
             // Slow movement by 4%
             last_mouse_change *= 0.96f;
             const float sensitivity =
@@ -52,14 +52,17 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
             StopPanning();
         }
         std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
-
-        // Reset wheel position
-        SetAxis(identifier, wheel_axis_x, 0);
-        SetAxis(identifier, wheel_axis_y, 0);
     }
 }
 
 void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) {
+    // If native mouse is enabled just set the screen coordinates
+    if (Settings::values.mouse_enabled) {
+        SetAxis(identifier, mouse_axis_x, touch_x);
+        SetAxis(identifier, mouse_axis_y, touch_y);
+        return;
+    }
+
     SetAxis(identifier, touch_axis_x, touch_x);
     SetAxis(identifier, touch_axis_y, touch_y);
 
@@ -121,7 +124,7 @@ void Mouse::PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton butt
 void Mouse::ReleaseButton(MouseButton button) {
     SetButton(identifier, static_cast<int>(button), false);
 
-    if (!Settings::values.mouse_panning) {
+    if (!Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
         SetAxis(identifier, mouse_axis_x, 0);
         SetAxis(identifier, mouse_axis_y, 0);
     }
@@ -129,8 +132,10 @@ void Mouse::ReleaseButton(MouseButton button) {
 }
 
 void Mouse::MouseWheelChange(int x, int y) {
-    SetAxis(identifier, wheel_axis_x, static_cast<f32>(x));
-    SetAxis(identifier, wheel_axis_y, static_cast<f32>(y));
+    wheel_position.x += x;
+    wheel_position.y += y;
+    SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
+    SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
 }
 
 void Mouse::ReleaseAllButtons() {
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index 429502af9f..f7e6db0b5f 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -72,6 +72,7 @@ private:
     Common::Vec2<int> mouse_origin;
     Common::Vec2<int> last_mouse_position;
     Common::Vec2<float> last_mouse_change;
+    Common::Vec2<int> wheel_position;
     bool button_pressed;
     int mouse_panning_timout{};
     std::jthread update_thread;
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 1015e51b56..2313a41894 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -729,7 +729,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
     const int center_y = height() / 2;
     input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y);
 
-    if (Settings::values.mouse_panning) {
+    if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
         QCursor::setPos(mapToGlobal({center_x, center_y}));
     }
 
@@ -1044,7 +1044,7 @@ void GRenderWindow::showEvent(QShowEvent* event) {
 
 bool GRenderWindow::eventFilter(QObject* object, QEvent* event) {
     if (event->type() == QEvent::HoverMove) {
-        if (Settings::values.mouse_panning) {
+        if (Settings::values.mouse_panning || Settings::values.mouse_enabled) {
             auto* hover_event = static_cast<QMouseEvent*>(event);
             mouseMoveEvent(hover_event);
             return false;
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index cf8aad4abf..e6127f9e67 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -179,4 +179,6 @@ void ConfigureInputAdvanced::RetranslateUI() {
 void ConfigureInputAdvanced::UpdateUIEnabled() {
     ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
     ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
+    ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked());
+    ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked());
 }