diff --git a/README.md b/README.md
index 8ec839d4d..900e72557 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 yuzu emulator early access
 =============
 
-This is the source code for early-access 3317.
+This is the source code for early-access 3319.
 
 ## Legal Notice
 
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 0122a815c..3d43145a1 100755
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -2,6 +2,7 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include <algorithm>
+#include <common/scope_exit.h>
 
 #include "common/polyfill_ranges.h"
 #include "common/thread.h"
@@ -834,17 +835,21 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
     if (index >= controller.stick_values.size()) {
         return;
     }
-    std::unique_lock lock{mutex};
+    auto trigger_guard =
+        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); });
+    std::scoped_lock lock{mutex};
     const auto stick_value = TransformToStick(callback);
 
     // Only read stick values that have the same uuid or are over the threshold to avoid flapping
     if (controller.stick_values[index].uuid != uuid) {
         const bool is_tas = uuid == TAS_UUID;
         if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) {
+            trigger_guard.Cancel();
             return;
         }
         if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left &&
             !stick_value.right) {
+            trigger_guard.Cancel();
             return;
         }
     }
@@ -855,8 +860,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
     if (is_configuring) {
         controller.analog_stick_state.left = {};
         controller.analog_stick_state.right = {};
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Stick, false);
         return;
     }
 
@@ -881,9 +884,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
         controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
         break;
     }
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Stick, true);
 }
 
 void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback,
@@ -891,7 +891,9 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
     if (index >= controller.trigger_values.size()) {
         return;
     }
-    std::unique_lock lock{mutex};
+    auto trigger_guard =
+        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); });
+    std::scoped_lock lock{mutex};
     const auto trigger_value = TransformToTrigger(callback);
 
     // Only read trigger values that have the same uuid or are pressed once
@@ -907,13 +909,12 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
     if (is_configuring) {
         controller.gc_trigger_state.left = 0;
         controller.gc_trigger_state.right = 0;
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Trigger, false);
         return;
     }
 
     // Only GC controllers have analog triggers
     if (npad_type != NpadStyleIndex::GameCube) {
+        trigger_guard.Cancel();
         return;
     }
 
@@ -930,9 +931,6 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
         controller.npad_button_state.zr.Assign(trigger.pressed.value);
         break;
     }
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Trigger, true);
 }
 
 void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback,
@@ -940,7 +938,8 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
     if (index >= controller.motion_values.size()) {
         return;
     }
-    std::unique_lock lock{mutex};
+    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); });
+    std::scoped_lock lock{mutex};
     auto& raw_status = controller.motion_values[index].raw_status;
     auto& emulated = controller.motion_values[index].emulated;
 
@@ -961,8 +960,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
     force_update_motion = raw_status.force_update;
 
     if (is_configuring) {
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Motion, false);
         return;
     }
 
@@ -972,9 +969,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
     motion.rotation = emulated.GetRotations();
     motion.orientation = emulated.GetOrientation();
     motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Motion, true);
 }
 
 void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback,
@@ -982,16 +976,17 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback
     if (index >= controller.color_values.size()) {
         return;
     }
-    std::unique_lock lock{mutex};
+    auto trigger_guard =
+        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); });
+    std::scoped_lock lock{mutex};
     controller.color_values[index] = TransformToColor(callback);
 
     if (is_configuring) {
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Color, false);
         return;
     }
 
     if (controller.color_values[index].body == 0) {
+        trigger_guard.Cancel();
         return;
     }
 
@@ -1024,9 +1019,6 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback
             break;
         }
     }
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Color, true);
 }
 
 void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
@@ -1034,12 +1026,11 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
     if (index >= controller.battery_values.size()) {
         return;
     }
-    std::unique_lock lock{mutex};
+    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); });
+    std::scoped_lock lock{mutex};
     controller.battery_values[index] = TransformToBattery(callback);
 
     if (is_configuring) {
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Battery, false);
         return;
     }
 
@@ -1095,18 +1086,14 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
         };
         break;
     }
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Battery, true);
 }
 
 void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
-    std::unique_lock lock{mutex};
+    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); });
+    std::scoped_lock lock{mutex};
     controller.camera_values = TransformToCamera(callback);
 
     if (is_configuring) {
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::IrSensor, false);
         return;
     }
 
@@ -1114,36 +1101,28 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback
     controller.camera_state.format =
         static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
     controller.camera_state.data = controller.camera_values.data;
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::IrSensor, true);
 }
 
 void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
-    std::unique_lock lock{mutex};
+    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); });
+    std::scoped_lock lock{mutex};
     const auto force_value = TransformToStick(callback);
 
     controller.ring_analog_value = force_value.x;
 
     if (is_configuring) {
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::RingController, false);
         return;
     }
 
     controller.ring_analog_state.force = force_value.x.value;
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::RingController, true);
 }
 
 void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
-    std::unique_lock lock{mutex};
+    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); });
+    std::scoped_lock lock{mutex};
     controller.nfc_values = TransformToNfc(callback);
 
     if (is_configuring) {
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Nfc, false);
         return;
     }
 
@@ -1151,9 +1130,6 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
         controller.nfc_values.state,
         controller.nfc_values.data,
     };
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Nfc, true);
 }
 
 bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
@@ -1412,39 +1388,35 @@ void EmulatedController::Connect(bool use_temporary_value) {
         return;
     }
 
-    std::unique_lock lock{mutex};
+    auto trigger_guard =
+        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); });
+    std::scoped_lock lock{mutex};
     if (is_configuring) {
         tmp_is_connected = true;
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Connected, false);
         return;
     }
 
     if (is_connected) {
+        trigger_guard.Cancel();
         return;
     }
     is_connected = true;
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Connected, true);
 }
 
 void EmulatedController::Disconnect() {
-    std::unique_lock lock{mutex};
+    auto trigger_guard =
+        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); });
+    std::scoped_lock lock{mutex};
     if (is_configuring) {
         tmp_is_connected = false;
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Disconnected, false);
         return;
     }
 
     if (!is_connected) {
+        trigger_guard.Cancel();
         return;
     }
     is_connected = false;
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Disconnected, true);
 }
 
 bool EmulatedController::IsConnected(bool get_temporary_value) const {
@@ -1469,19 +1441,21 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c
 }
 
 void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
-    std::unique_lock lock{mutex};
+    auto trigger_guard =
+        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); });
+    std::scoped_lock lock{mutex};
 
     if (is_configuring) {
         if (tmp_npad_type == npad_type_) {
+            trigger_guard.Cancel();
             return;
         }
         tmp_npad_type = npad_type_;
-        lock.unlock();
-        TriggerOnChange(ControllerTriggerType::Type, false);
         return;
     }
 
     if (npad_type == npad_type_) {
+        trigger_guard.Cancel();
         return;
     }
     if (is_connected) {
@@ -1489,9 +1463,6 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
                     NpadIdTypeToIndex(npad_id_type));
     }
     npad_type = npad_type_;
-
-    lock.unlock();
-    TriggerOnChange(ControllerTriggerType::Type, true);
 }
 
 LedPattern EmulatedController::GetLedPattern() const {
@@ -1589,7 +1560,7 @@ DebugPadButton EmulatedController::GetDebugPadButtons() const {
 }
 
 AnalogSticks EmulatedController::GetSticks() const {
-    std::unique_lock lock{mutex};
+    std::scoped_lock lock{mutex};
 
     if (is_configuring) {
         return {};
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index e1f98f9e5..e9a25539a 100755
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -40,25 +40,26 @@ public:
     }
 
     void EnableMotion() {
-        if (sdl_controller) {
-            SDL_GameController* controller = sdl_controller.get();
-            has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE;
-            has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE;
-            if (has_accel) {
-                SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
-            }
-            if (has_gyro) {
-                SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
-            }
+        if (!sdl_controller) {
+            return;
+        }
+        SDL_GameController* controller = sdl_controller.get();
+        if (HasMotion()) {
+            SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_FALSE);
+            SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_FALSE);
+        }
+        has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE;
+        has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE;
+        if (has_accel) {
+            SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
+        }
+        if (has_gyro) {
+            SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
         }
     }
 
-    bool HasGyro() const {
-        return has_gyro;
-    }
-
-    bool HasAccel() const {
-        return has_accel;
+    bool HasMotion() const {
+        return has_gyro || has_accel;
     }
 
     bool UpdateMotion(SDL_ControllerSensorEvent event) {
@@ -85,6 +86,20 @@ public:
         if (time_difference == 0) {
             return false;
         }
+
+        // Motion data is invalid
+        if (motion.accel_x == 0 && motion.gyro_x == 0 && motion.accel_y == 0 &&
+            motion.gyro_y == 0 && motion.accel_z == 0 && motion.gyro_z == 0) {
+            if (motion_error_count++ < 200) {
+                return false;
+            }
+            // Try restarting the sensor
+            motion_error_count = 0;
+            EnableMotion();
+            return false;
+        }
+
+        motion_error_count = 0;
         motion.delta_timestamp = time_difference * 1000;
         return true;
     }
@@ -250,6 +265,7 @@ private:
     mutable std::mutex mutex;
 
     u64 last_motion_update{};
+    std::size_t motion_error_count{};
     bool has_gyro{false};
     bool has_accel{false};
     bool has_vibration{false};
@@ -955,18 +971,18 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p
     MotionMapping mapping = {};
     joystick->EnableMotion();
 
-    if (joystick->HasGyro() || joystick->HasAccel()) {
+    if (joystick->HasMotion()) {
         mapping.insert_or_assign(Settings::NativeMotion::MotionRight,
                                  BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
     }
     if (params.Has("guid2")) {
         joystick2->EnableMotion();
-        if (joystick2->HasGyro() || joystick2->HasAccel()) {
+        if (joystick2->HasMotion()) {
             mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
                                      BuildMotionParam(joystick2->GetPort(), joystick2->GetGUID()));
         }
     } else {
-        if (joystick->HasGyro() || joystick->HasAccel()) {
+        if (joystick->HasMotion()) {
             mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
                                      BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
         }
diff --git a/src/input_common/helpers/joycon_protocol/calibration.cpp b/src/input_common/helpers/joycon_protocol/calibration.cpp
index cd30ab869..f6e7e97d5 100755
--- a/src/input_common/helpers/joycon_protocol/calibration.cpp
+++ b/src/input_common/helpers/joycon_protocol/calibration.cpp
@@ -12,10 +12,10 @@ CalibrationProtocol::CalibrationProtocol(std::shared_ptr<JoyconHandle> handle)
     : JoyconCommonProtocol(std::move(handle)) {}
 
 DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) {
+    ScopedSetBlocking sb(this);
     std::vector<u8> buffer;
     DriverResult result{DriverResult::Success};
     calibration = {};
-    SetBlocking();
 
     result = ReadSPI(CalAddr::USER_LEFT_MAGIC, sizeof(u16), buffer);
 
@@ -44,15 +44,14 @@ DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration
     // Set a valid default calibration if data is missing
     ValidateCalibration(calibration);
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibration& calibration) {
+    ScopedSetBlocking sb(this);
     std::vector<u8> buffer;
     DriverResult result{DriverResult::Success};
     calibration = {};
-    SetBlocking();
 
     result = ReadSPI(CalAddr::USER_RIGHT_MAGIC, sizeof(u16), buffer);
 
@@ -81,15 +80,14 @@ DriverResult CalibrationProtocol::GetRightJoyStickCalibration(JoyStickCalibratio
     // Set a valid default calibration if data is missing
     ValidateCalibration(calibration);
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibration) {
+    ScopedSetBlocking sb(this);
     std::vector<u8> buffer;
     DriverResult result{DriverResult::Success};
     calibration = {};
-    SetBlocking();
 
     result = ReadSPI(CalAddr::USER_IMU_MAGIC, sizeof(u16), buffer);
 
@@ -124,7 +122,6 @@ DriverResult CalibrationProtocol::GetImuCalibration(MotionCalibration& calibrati
 
     ValidateCalibration(calibration);
 
-    SetNonBlocking();
     return result;
 }
 
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
index e8c4a7d0e..417d0dcc5 100755
--- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
@@ -58,9 +58,8 @@ DriverResult JoyconCommonProtocol::CheckDeviceAccess(SDL_hid_device_info* device
 }
 
 DriverResult JoyconCommonProtocol::SetReportMode(ReportMode report_mode) {
-    const std::vector<u8> buffer{static_cast<u8>(report_mode)};
-    std::vector<u8> output;
-    return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer, output);
+    const std::array<u8, 1> buffer{static_cast<u8>(report_mode)};
+    return SendSubCommand(SubCommand::SET_REPORT_MODE, buffer);
 }
 
 DriverResult JoyconCommonProtocol::SendData(std::span<const u8> buffer) {
@@ -120,6 +119,11 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const
     return DriverResult::Success;
 }
 
+DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span<const u8> buffer) {
+    std::vector<u8> output;
+    return SendSubCommand(sc, buffer, output);
+}
+
 DriverResult JoyconCommonProtocol::SendMCUCommand(SubCommand sc, std::span<const u8> buffer) {
     std::vector<u8> local_buffer(MaxResponseSize);
 
@@ -147,7 +151,7 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span<const u8> buffe
 DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8>& output) {
     constexpr std::size_t MaxTries = 10;
     std::size_t tries = 0;
-    std::vector<u8> buffer = {0x00, 0x00, 0x00, 0x00, size};
+    std::array<u8, 5> buffer = {0x00, 0x00, 0x00, 0x00, size};
     std::vector<u8> local_buffer(size + 20);
 
     buffer[0] = static_cast<u8>(static_cast<u16>(addr) & 0x00FF);
@@ -169,10 +173,8 @@ DriverResult JoyconCommonProtocol::ReadSPI(CalAddr addr, u8 size, std::vector<u8
 }
 
 DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
-    std::vector<u8> output;
-
-    const std::vector<u8> mcu_state{static_cast<u8>(enable ? 1 : 0)};
-    const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state, output);
+    const std::array<u8, 1> mcu_state{static_cast<u8>(enable ? 1 : 0)};
+    const auto result = SendSubCommand(SubCommand::SET_MCU_STATE, mcu_state);
 
     if (result != DriverResult::Success) {
         LOG_ERROR(Input, "SendMCUData failed with error {}", result);
@@ -183,13 +185,11 @@ DriverResult JoyconCommonProtocol::EnableMCU(bool enable) {
 
 DriverResult JoyconCommonProtocol::ConfigureMCU(const MCUConfig& config) {
     LOG_DEBUG(Input, "ConfigureMCU");
-    std::vector<u8> output;
-
     std::array<u8, sizeof(MCUConfig)> config_buffer;
     memcpy(config_buffer.data(), &config, sizeof(MCUConfig));
     config_buffer[37] = CalculateMCU_CRC8(config_buffer.data() + 1, 36);
 
-    const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer, output);
+    const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, config_buffer);
 
     if (result != DriverResult::Success) {
         LOG_ERROR(Input, "Set MCU config failed with error {}", result);
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.h b/src/input_common/helpers/joycon_protocol/common_protocol.h
index d693f2165..903bcf402 100755
--- a/src/input_common/helpers/joycon_protocol/common_protocol.h
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.h
@@ -74,6 +74,13 @@ public:
      */
     DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer, std::vector<u8>& output);
 
+    /**
+     * Sends a sub command to the device and waits for it's reply and ignores the output
+     * @param sc sub command to be send
+     * @param buffer data to be send
+     */
+    DriverResult SendSubCommand(SubCommand sc, std::span<const u8> buffer);
+
     /**
      * Sends a mcu command to the device
      * @param sc sub command to be send
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp
index cbd9ff4f8..52bb8b61a 100755
--- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp
+++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp
@@ -10,22 +10,18 @@ GenericProtocol::GenericProtocol(std::shared_ptr<JoyconHandle> handle)
     : JoyconCommonProtocol(std::move(handle)) {}
 
 DriverResult GenericProtocol::EnablePassiveMode() {
-    SetBlocking();
-    const auto result = SetReportMode(ReportMode::SIMPLE_HID_MODE);
-    SetNonBlocking();
-    return result;
+    ScopedSetBlocking sb(this);
+    return SetReportMode(ReportMode::SIMPLE_HID_MODE);
 }
 
 DriverResult GenericProtocol::EnableActiveMode() {
-    SetBlocking();
-    const auto result = SetReportMode(ReportMode::STANDARD_FULL_60HZ);
-    SetNonBlocking();
-    return result;
+    ScopedSetBlocking sb(this);
+    return SetReportMode(ReportMode::STANDARD_FULL_60HZ);
 }
 
 DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) {
+    ScopedSetBlocking sb(this);
     std::vector<u8> output;
-    SetBlocking();
 
     const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output);
 
@@ -34,7 +30,6 @@ DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) {
         memcpy(&device_info, output.data(), sizeof(DeviceInfo));
     }
 
-    SetNonBlocking();
     return result;
 }
 
@@ -43,36 +38,30 @@ DriverResult GenericProtocol::GetControllerType(ControllerType& controller_type)
 }
 
 DriverResult GenericProtocol::EnableImu(bool enable) {
+    ScopedSetBlocking sb(this);
     const std::array<u8, 1> buffer{static_cast<u8>(enable ? 1 : 0)};
-    std::vector<u8> output;
-    SetBlocking();
-    const auto result = SendSubCommand(SubCommand::ENABLE_IMU, buffer, output);
-    SetNonBlocking();
-    return result;
+    return SendSubCommand(SubCommand::ENABLE_IMU, buffer);
 }
 
 DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec,
                                            AccelerometerSensitivity asen,
                                            AccelerometerPerformance afrec) {
+    ScopedSetBlocking sb(this);
     const std::array<u8, 4> buffer{static_cast<u8>(gsen), static_cast<u8>(asen),
                                    static_cast<u8>(gfrec), static_cast<u8>(afrec)};
-    std::vector<u8> output;
-    SetBlocking();
-    const auto result = SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer, output);
-    SetNonBlocking();
-    return result;
+    return SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer);
 }
 
 DriverResult GenericProtocol::GetBattery(u32& battery_level) {
+    // This function is meant to request the high resolution battery status
     battery_level = 0;
     return DriverResult::NotSupported;
 }
 
 DriverResult GenericProtocol::GetColor(Color& color) {
+    ScopedSetBlocking sb(this);
     std::vector<u8> buffer;
-    SetBlocking();
     const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer);
-    SetNonBlocking();
 
     color = {};
     if (result == DriverResult::Success) {
@@ -86,10 +75,9 @@ DriverResult GenericProtocol::GetColor(Color& color) {
 }
 
 DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) {
+    ScopedSetBlocking sb(this);
     std::vector<u8> buffer;
-    SetBlocking();
     const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer);
-    SetNonBlocking();
 
     serial_number = {};
     if (result == DriverResult::Success) {
@@ -115,14 +103,9 @@ DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) {
 }
 
 DriverResult GenericProtocol::SetHomeLight() {
+    ScopedSetBlocking sb(this);
     static constexpr std::array<u8, 3> buffer{0x0f, 0xf0, 0x00};
-    std::vector<u8> output;
-    SetBlocking();
-
-    const auto result = SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer, output);
-
-    SetNonBlocking();
-    return result;
+    return SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer);
 }
 
 DriverResult GenericProtocol::SetLedBusy() {
@@ -130,14 +113,9 @@ DriverResult GenericProtocol::SetLedBusy() {
 }
 
 DriverResult GenericProtocol::SetLedPattern(u8 leds) {
+    ScopedSetBlocking sb(this);
     const std::array<u8, 1> buffer{leds};
-    std::vector<u8> output;
-    SetBlocking();
-
-    const auto result = SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer, output);
-
-    SetNonBlocking();
-    return result;
+    return SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer);
 }
 
 DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) {
diff --git a/src/input_common/helpers/joycon_protocol/irs.cpp b/src/input_common/helpers/joycon_protocol/irs.cpp
index 077b5b79a..09e17bc5b 100755
--- a/src/input_common/helpers/joycon_protocol/irs.cpp
+++ b/src/input_common/helpers/joycon_protocol/irs.cpp
@@ -12,8 +12,8 @@ IrsProtocol::IrsProtocol(std::shared_ptr<JoyconHandle> handle)
 
 DriverResult IrsProtocol::EnableIrs() {
     LOG_INFO(Input, "Enable IRS");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ);
@@ -49,14 +49,13 @@ DriverResult IrsProtocol::EnableIrs() {
 
     is_enabled = true;
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult IrsProtocol::DisableIrs() {
     LOG_DEBUG(Input, "Disable IRS");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = EnableMCU(false);
@@ -64,7 +63,6 @@ DriverResult IrsProtocol::DisableIrs() {
 
     is_enabled = false;
 
-    SetNonBlocking();
     return result;
 }
 
@@ -148,7 +146,7 @@ DriverResult IrsProtocol::ConfigureIrs() {
     };
     buf_image.resize((static_cast<u8>(fragments) + 1) * 300);
 
-    std::vector<u8> request_data(sizeof(IrsConfigure));
+    std::array<u8, sizeof(IrsConfigure)> request_data{};
     memcpy(request_data.data(), &irs_configuration, sizeof(IrsConfigure));
     request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
     do {
@@ -191,7 +189,7 @@ DriverResult IrsProtocol::WriteRegistersStep1() {
         .crc = {},
     };
 
-    std::vector<u8> request_data(sizeof(IrsWriteRegisters));
+    std::array<u8, sizeof(IrsWriteRegisters)> request_data{};
     memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters));
     request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
 
@@ -250,7 +248,7 @@ DriverResult IrsProtocol::WriteRegistersStep2() {
         .crc = {},
     };
 
-    std::vector<u8> request_data(sizeof(IrsWriteRegisters));
+    std::array<u8, sizeof(IrsWriteRegisters)> request_data{};
     memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters));
     request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
     do {
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h
index 273c8d07d..817a43730 100755
--- a/src/input_common/helpers/joycon_protocol/joycon_types.h
+++ b/src/input_common/helpers/joycon_protocol/joycon_types.h
@@ -347,6 +347,13 @@ enum class IrRegistersAddress : u16 {
     DenoiseColor = 0x6901,
 };
 
+enum class NFCBlock {
+    Block0 = 0,
+    Block45 = 45,
+    Block135 = 135,
+    Block231 = 231,
+};
+
 enum class DriverResult {
     Success,
     WrongReply,
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp
index 27147591e..3e3868888 100755
--- a/src/input_common/helpers/joycon_protocol/nfc.cpp
+++ b/src/input_common/helpers/joycon_protocol/nfc.cpp
@@ -12,8 +12,8 @@ NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle)
 
 DriverResult NfcProtocol::EnableNfc() {
     LOG_INFO(Input, "Enable NFC");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ);
@@ -35,14 +35,13 @@ DriverResult NfcProtocol::EnableNfc() {
         result = ConfigureMCU(config);
     }
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult NfcProtocol::DisableNfc() {
     LOG_DEBUG(Input, "Disable NFC");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = EnableMCU(false);
@@ -50,15 +49,14 @@ DriverResult NfcProtocol::DisableNfc() {
 
     is_enabled = false;
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult NfcProtocol::StartNFCPollingMode() {
     LOG_DEBUG(Input, "Start NFC pooling Mode");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
     TagFoundData tag_data{};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC);
@@ -70,15 +68,14 @@ DriverResult NfcProtocol::StartNFCPollingMode() {
         is_enabled = true;
     }
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
     LOG_DEBUG(Input, "Start NFC pooling Mode");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
     TagFoundData tag_data{};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = StartPolling(tag_data);
@@ -96,20 +93,18 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
         result = GetAmiiboData(data);
     }
 
-    SetNonBlocking();
     return result;
 }
 
 bool NfcProtocol::HasAmiibo() {
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
     TagFoundData tag_data{};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = StartPolling(tag_data);
     }
 
-    SetNonBlocking();
     return result == DriverResult::Success;
 }
 
@@ -298,7 +293,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) {
         .crc = {},
     };
 
-    std::vector<u8> request_data(sizeof(NFCRequestState));
+    std::array<u8, sizeof(NFCRequestState)> request_data{};
     memcpy(request_data.data(), &request, sizeof(NFCRequestState));
     request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
     return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@@ -315,7 +310,7 @@ DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) {
         .crc = {},
     };
 
-    std::vector<u8> request_data(sizeof(NFCRequestState));
+    std::array<u8, sizeof(NFCRequestState)> request_data{};
     memcpy(request_data.data(), &request, sizeof(NFCRequestState));
     request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
     return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@@ -357,60 +352,50 @@ DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::si
         .crc = {},
     };
 
-    std::vector<u8> request_data(sizeof(NFCRequestState));
+    std::array<u8, sizeof(NFCRequestState)> request_data{};
     memcpy(request_data.data(), &request, sizeof(NFCRequestState));
     request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
     return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
 }
 
 NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
-    constexpr NFCReadBlockCommand block0{
-        .block_count = 1,
+    switch (static_cast<NFCBlock>(pages)) {
+    case NFCBlock::Block0:
+        return {
+            .block_count = 1,
+        };
+    case NFCBlock::Block45:
+        return {
+            .block_count = 1,
+            .blocks =
+                {
+                    NFCReadBlock{0x00, 0x2C},
+                },
+        };
+    case NFCBlock::Block135:
+        return {
+            .block_count = 3,
+            .blocks =
+                {
+                    NFCReadBlock{0x00, 0x3b},
+                    {0x3c, 0x77},
+                    {0x78, 0x86},
+                },
+        };
+    case NFCBlock::Block231:
+        return {
+            .block_count = 4,
+            .blocks =
+                {
+                    NFCReadBlock{0x00, 0x3b},
+                    {0x3c, 0x77},
+                    {0x78, 0x83},
+                    {0xb4, 0xe6},
+                },
+        };
+    default:
+        return {};
     };
-    constexpr NFCReadBlockCommand block45{
-        .block_count = 1,
-        .blocks =
-            {
-                NFCReadBlock{0x00, 0x2C},
-            },
-    };
-    constexpr NFCReadBlockCommand block135{
-        .block_count = 3,
-        .blocks =
-            {
-                NFCReadBlock{0x00, 0x3b},
-                {0x3c, 0x77},
-                {0x78, 0x86},
-            },
-    };
-    constexpr NFCReadBlockCommand block231{
-        .block_count = 4,
-        .blocks =
-            {
-                NFCReadBlock{0x00, 0x3b},
-                {0x3c, 0x77},
-                {0x78, 0x83},
-                {0xb4, 0xe6},
-            },
-    };
-
-    if (pages == 0) {
-        return block0;
-    }
-
-    if (pages == 45) {
-        return block45;
-    }
-
-    if (pages == 135) {
-        return block135;
-    }
-
-    if (pages == 231) {
-        return block231;
-    }
-
-    return {};
 }
 
 bool NfcProtocol::IsEnabled() const {
diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp
index 8adad57dd..12f81309e 100755
--- a/src/input_common/helpers/joycon_protocol/ringcon.cpp
+++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp
@@ -11,8 +11,8 @@ RingConProtocol::RingConProtocol(std::shared_ptr<JoyconHandle> handle)
 
 DriverResult RingConProtocol::EnableRingCon() {
     LOG_DEBUG(Input, "Enable Ringcon");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = SetReportMode(ReportMode::STANDARD_FULL_60HZ);
@@ -30,14 +30,13 @@ DriverResult RingConProtocol::EnableRingCon() {
         result = ConfigureMCU(config);
     }
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult RingConProtocol::DisableRingCon() {
     LOG_DEBUG(Input, "Disable RingCon");
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
-    SetBlocking();
 
     if (result == DriverResult::Success) {
         result = EnableMCU(false);
@@ -45,15 +44,14 @@ DriverResult RingConProtocol::DisableRingCon() {
 
     is_enabled = false;
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult RingConProtocol::StartRingconPolling() {
     LOG_DEBUG(Input, "Enable Ringcon");
-    bool is_connected = false;
+    ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
-    SetBlocking();
+    bool is_connected = false;
 
     if (result == DriverResult::Success) {
         result = IsRingConnected(is_connected);
@@ -66,13 +64,13 @@ DriverResult RingConProtocol::StartRingconPolling() {
         is_enabled = true;
     }
 
-    SetNonBlocking();
     return result;
 }
 
 DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
     LOG_DEBUG(Input, "IsRingConnected");
     constexpr std::size_t max_tries = 28;
+    constexpr u8 ring_controller_id = 0x20;
     std::vector<u8> output;
     std::size_t tries = 0;
     is_connected = false;
@@ -88,7 +86,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
         if (tries++ >= max_tries) {
             return DriverResult::NoDeviceDetected;
         }
-    } while (output[14] != 0x59 || output[16] != 0x20);
+    } while (output[16] != ring_controller_id);
 
     is_connected = true;
     return DriverResult::Success;
@@ -96,30 +94,20 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
 
 DriverResult RingConProtocol::ConfigureRing() {
     LOG_DEBUG(Input, "ConfigureRing");
-    constexpr std::size_t max_tries = 28;
-    DriverResult result{DriverResult::Success};
-    std::vector<u8> output;
-    std::size_t tries = 0;
 
     static constexpr std::array<u8, 37> ring_config{
         0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16, 0xED, 0x34, 0x36,
         0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36};
-    do {
-        result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config, output);
 
-        if (result != DriverResult::Success) {
-            return result;
-        }
-        if (tries++ >= max_tries) {
-            return DriverResult::NoDeviceDetected;
-        }
-    } while (output[14] != 0x5C);
+    const DriverResult result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config);
+
+    if (result != DriverResult::Success) {
+        return result;
+    }
 
     static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02};
-    result = SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data, output);
-
-    return result;
+    return SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data);
 }
 
 bool RingConProtocol::IsEnabled() const {
diff --git a/src/input_common/helpers/joycon_protocol/rumble.cpp b/src/input_common/helpers/joycon_protocol/rumble.cpp
index a83e86828..63b60c946 100755
--- a/src/input_common/helpers/joycon_protocol/rumble.cpp
+++ b/src/input_common/helpers/joycon_protocol/rumble.cpp
@@ -14,12 +14,9 @@ RumbleProtocol::RumbleProtocol(std::shared_ptr<JoyconHandle> handle)
 
 DriverResult RumbleProtocol::EnableRumble(bool is_enabled) {
     LOG_DEBUG(Input, "Enable Rumble");
+    ScopedSetBlocking sb(this);
     const std::array<u8, 1> buffer{static_cast<u8>(is_enabled ? 1 : 0)};
-    std::vector<u8> output;
-    SetBlocking();
-    const auto result = SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer, output);
-    SetNonBlocking();
-    return result;
+    return SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer);
 }
 
 DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) {