diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 4239c17f57251a2436ee75c0e423d4fc1771c6fd..4104928d1194ba51a165c6e9101b55e1a1394e2f 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -257,7 +257,7 @@ void QtControllerSelectorDialog::LoadConfiguration() {
 }
 
 void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
-    ConfigureVibration dialog(this);
+    ConfigureVibration dialog(this, system.HIDCore());
 
     dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
                           Qt::WindowSystemMenuHint);
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index d53179dbbb25e149f7d48adf7005592af7f98375..7c57761899699ebde944e93865087f5f8e700347 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -164,7 +164,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
             });
 
     connect(ui->vibrationButton, &QPushButton::clicked,
-            [this] { CallConfigureDialog<ConfigureVibration>(*this); });
+            [this, &hid_core] { CallConfigureDialog<ConfigureVibration>(*this, hid_core); });
 
     connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] {
         CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index adce04b2786706b930529d652269203905b133d0..779b6401c9843e4f25deb64d5101e23c44031719 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -9,11 +9,14 @@
 
 #include "common/param_package.h"
 #include "common/settings.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
+#include "core/hid/hid_types.h"
 #include "ui_configure_vibration.h"
 #include "yuzu/configuration/configure_vibration.h"
 
-ConfigureVibration::ConfigureVibration(QWidget* parent)
-    : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) {
+ConfigureVibration::ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_)
+    : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()), hid_core{hid_core_} {
     ui->setupUi(this);
 
     vibration_groupboxes = {
@@ -31,6 +34,13 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)
     const auto& players = Settings::values.players.GetValue();
 
     for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
+        auto controller = hid_core.GetEmulatedControllerByIndex(i);
+        Core::HID::ControllerUpdateCallback engine_callback{
+            .on_change = [this,
+                          i](Core::HID::ControllerTriggerType type) { VibrateController(type, i); },
+            .is_npad_service = false,
+        };
+        controller_callback_key[i] = controller->SetCallback(engine_callback);
         vibration_groupboxes[i]->setChecked(players[i].vibration_enabled);
         vibration_spinboxes[i]->setValue(players[i].vibration_strength);
     }
@@ -45,7 +55,14 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)
     RetranslateUI();
 }
 
-ConfigureVibration::~ConfigureVibration() = default;
+ConfigureVibration::~ConfigureVibration() {
+    StopVibrations();
+
+    for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
+        auto controller = hid_core.GetEmulatedControllerByIndex(i);
+        controller->DeleteCallback(controller_callback_key[i]);
+    }
+};
 
 void ConfigureVibration::ApplyConfiguration() {
     auto& players = Settings::values.players.GetValue();
@@ -70,3 +87,54 @@ void ConfigureVibration::changeEvent(QEvent* event) {
 void ConfigureVibration::RetranslateUI() {
     ui->retranslateUi(this);
 }
+
+void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type,
+                                           std::size_t player_index) {
+    if (type != Core::HID::ControllerTriggerType::Button) {
+        return;
+    }
+
+    auto& player = Settings::values.players.GetValue()[player_index];
+    auto controller = hid_core.GetEmulatedControllerByIndex(player_index);
+    const int vibration_strenght = vibration_spinboxes[player_index]->value();
+    const auto& buttons = controller->GetButtonsValues();
+
+    bool button_is_pressed = false;
+    for (std::size_t i = 0; i < buttons.size(); ++i) {
+        if (buttons[i].value) {
+            button_is_pressed = true;
+            break;
+        }
+    }
+
+    if (!button_is_pressed) {
+        StopVibrations();
+        return;
+    }
+
+    const int old_vibration_enabled = player.vibration_enabled;
+    const bool old_vibration_strenght = player.vibration_strength;
+    player.vibration_enabled = true;
+    player.vibration_strength = vibration_strenght;
+
+    const Core::HID::VibrationValue vibration{
+        .low_amplitude = 1.0f,
+        .low_frequency = 160.0f,
+        .high_amplitude = 1.0f,
+        .high_frequency = 320.0f,
+    };
+    controller->SetVibration(0, vibration);
+    controller->SetVibration(1, vibration);
+
+    // Restore previous values
+    player.vibration_enabled = old_vibration_enabled;
+    player.vibration_strength = old_vibration_strenght;
+}
+
+void ConfigureVibration::StopVibrations() {
+    for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
+        auto controller = hid_core.GetEmulatedControllerByIndex(i);
+        controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE);
+        controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE);
+    }
+}
diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h
index 37bbc26536c33a6dc114db30a8f529ce1c659d04..50b8195fae8070cfd7e944c9553ad17a1170cbfc 100644
--- a/src/yuzu/configuration/configure_vibration.h
+++ b/src/yuzu/configuration/configure_vibration.h
@@ -15,11 +15,16 @@ namespace Ui {
 class ConfigureVibration;
 }
 
+namespace Core::HID {
+enum class ControllerTriggerType;
+class HIDCore;
+} // namespace Core::HID
+
 class ConfigureVibration : public QDialog {
     Q_OBJECT
 
 public:
-    explicit ConfigureVibration(QWidget* parent);
+    explicit ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_);
     ~ConfigureVibration() override;
 
     void ApplyConfiguration();
@@ -27,14 +32,21 @@ public:
 private:
     void changeEvent(QEvent* event) override;
     void RetranslateUI();
+    void VibrateController(Core::HID::ControllerTriggerType type, std::size_t player_index);
+    void StopVibrations();
 
     std::unique_ptr<Ui::ConfigureVibration> ui;
 
     static constexpr std::size_t NUM_PLAYERS = 8;
 
-    // Groupboxes encapsulating the vibration strength spinbox.
+    /// Groupboxes encapsulating the vibration strength spinbox.
     std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes;
 
-    // Spinboxes representing the vibration strength percentage.
+    /// Spinboxes representing the vibration strength percentage.
     std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes;
+
+    /// Callback index to stop the controllers events
+    std::array<int, NUM_PLAYERS> controller_callback_key;
+
+    Core::HID::HIDCore& hid_core;
 };
diff --git a/src/yuzu/configuration/configure_vibration.ui b/src/yuzu/configuration/configure_vibration.ui
index efdf317a95a21406f8458d6184682bc8e712f644..447a18eb120e23354ae1e1dae5b068a1aecefda3 100644
--- a/src/yuzu/configuration/configure_vibration.ui
+++ b/src/yuzu/configuration/configure_vibration.ui
@@ -17,6 +17,13 @@
    <string notr="true"/>
   </property>
   <layout class="QVBoxLayout">
+   <item row="0" column="0" colspan="4">
+    <widget class="QLabel" name="label_1">
+     <property name="text">
+      <string>Press any controller button to vibrate the controller.</string>
+     </property>
+    </widget>
+   </item>
    <item>
     <widget class="QGroupBox" name="vibrationStrengthGroup">
      <property name="title">