diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index e67a2a8bcf..6096aa678e 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -383,6 +383,24 @@ protected: return def_code; }; + // Search an unordered map for a string value and return found keycode + long FindKeyCodeByString(std::unordered_map map, const std::string& name, bool fallback = true) + { + for (auto it = map.begin(); it != map.end(); ++it) + { + if (it->second == name) + return it->first; + } + + if (fallback) + { + LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name); + return 0; + } + + return -1; + }; + // Get normalized trigger value based on the range defined by a threshold u16 NormalizeTriggerInput(u16 value, int threshold) { @@ -554,7 +572,7 @@ public: bool has_deadzones() { return b_has_deadzones; }; pad_config* GetConfig() { return &m_pad_config; }; //Sets window to config the controller(optional) - virtual void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false) {}; + virtual void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false, std::vector buttons = {}) {}; virtual void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) {}; //Return list of devices for that handler virtual std::vector ListDevices() = 0; diff --git a/rpcs3/ds4_pad_handler.cpp b/rpcs3/ds4_pad_handler.cpp index 23875daef3..916345b7c7 100644 --- a/rpcs3/ds4_pad_handler.cpp +++ b/rpcs3/ds4_pad_handler.cpp @@ -147,7 +147,7 @@ ds4_pad_handler::ds4_pad_handler() : is_init(false) m_thumb_threshold = thumb_max / 2; } -void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist) +void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); diff --git a/rpcs3/ds4_pad_handler.h b/rpcs3/ds4_pad_handler.h index ef8adda825..c149b8f100 100644 --- a/rpcs3/ds4_pad_handler.h +++ b/rpcs3/ds4_pad_handler.h @@ -141,7 +141,7 @@ public: std::vector ListDevices() override; bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; - void GetNextButtonPress(const std::string& padId, const std::function& buttonCallback, bool get_blacklist = false) override; + void GetNextButtonPress(const std::string& padId, const std::function& buttonCallback, bool get_blacklist = false, std::vector buttons = {}) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; private: diff --git a/rpcs3/evdev_joystick_handler.cpp b/rpcs3/evdev_joystick_handler.cpp index 8e2ef148f7..d6259497a9 100644 --- a/rpcs3/evdev_joystick_handler.cpp +++ b/rpcs3/evdev_joystick_handler.cpp @@ -206,7 +206,7 @@ std::unordered_map> evdev_joystick_handler::GetButtonV return button_values; } -void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist) +void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); diff --git a/rpcs3/evdev_joystick_handler.h b/rpcs3/evdev_joystick_handler.h index 2fd7aebf17..059c5d9723 100644 --- a/rpcs3/evdev_joystick_handler.h +++ b/rpcs3/evdev_joystick_handler.h @@ -247,7 +247,7 @@ public: bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; void Close(); - void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false) override; + void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false, std::vector buttons = {}) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; private: diff --git a/rpcs3/mm_joystick_handler.cpp b/rpcs3/mm_joystick_handler.cpp index c072b7ab01..c4cb62943e 100644 --- a/rpcs3/mm_joystick_handler.cpp +++ b/rpcs3/mm_joystick_handler.cpp @@ -21,27 +21,27 @@ mm_joystick_handler::mm_joystick_handler() : is_init(false) m_pad_config.ls_down.def = axis_list.at(mmjoy_axis::joy_y_neg); m_pad_config.ls_right.def = axis_list.at(mmjoy_axis::joy_x_pos); m_pad_config.ls_up.def = axis_list.at(mmjoy_axis::joy_y_pos); - m_pad_config.rs_left.def = axis_list.at(mmjoy_axis::joy_u_neg); + m_pad_config.rs_left.def = axis_list.at(mmjoy_axis::joy_z_neg); m_pad_config.rs_down.def = axis_list.at(mmjoy_axis::joy_r_neg); - m_pad_config.rs_right.def = axis_list.at(mmjoy_axis::joy_u_pos); + m_pad_config.rs_right.def = axis_list.at(mmjoy_axis::joy_z_pos); m_pad_config.rs_up.def = axis_list.at(mmjoy_axis::joy_r_pos); - m_pad_config.start.def = button_list.at(JOY_BUTTON8); - m_pad_config.select.def = button_list.at(JOY_BUTTON7); + m_pad_config.start.def = button_list.at(JOY_BUTTON9); + m_pad_config.select.def = button_list.at(JOY_BUTTON10); m_pad_config.ps.def = button_list.at(JOY_BUTTON17); - m_pad_config.square.def = button_list.at(JOY_BUTTON3); - m_pad_config.cross.def = button_list.at(JOY_BUTTON1); + m_pad_config.square.def = button_list.at(JOY_BUTTON4); + m_pad_config.cross.def = button_list.at(JOY_BUTTON3); m_pad_config.circle.def = button_list.at(JOY_BUTTON2); - m_pad_config.triangle.def = button_list.at(JOY_BUTTON4); + m_pad_config.triangle.def = button_list.at(JOY_BUTTON1); m_pad_config.left.def = pov_list.at(JOY_POVLEFT); m_pad_config.down.def = pov_list.at(JOY_POVBACKWARD); m_pad_config.right.def = pov_list.at(JOY_POVRIGHT); m_pad_config.up.def = pov_list.at(JOY_POVFORWARD); - m_pad_config.r1.def = button_list.at(JOY_BUTTON6); - m_pad_config.r2.def = axis_list.at(mmjoy_axis::joy_z_pos); - m_pad_config.r3.def = button_list.at(JOY_BUTTON10); - m_pad_config.l1.def = button_list.at(JOY_BUTTON5); - m_pad_config.l2.def = axis_list.at(mmjoy_axis::joy_z_neg); - m_pad_config.l3.def = button_list.at(JOY_BUTTON9); + m_pad_config.r1.def = button_list.at(JOY_BUTTON8); + m_pad_config.r2.def = button_list.at(JOY_BUTTON6); + m_pad_config.r3.def = button_list.at(JOY_BUTTON12); + m_pad_config.l1.def = button_list.at(JOY_BUTTON7); + m_pad_config.l2.def = button_list.at(JOY_BUTTON5); + m_pad_config.l3.def = button_list.at(JOY_BUTTON11); // Set default misc variables m_pad_config.lstickdeadzone.def = 0; // between 0 and 255 @@ -130,7 +130,7 @@ bool mm_joystick_handler::bindPadToDevice(std::shared_ptr pad, const std::s key = FindKeyCode(pov_list, name, false); if (key < 0) key = FindKeyCode(axis_list, name); - return key; + return static_cast(key); }; pad->Init @@ -141,12 +141,23 @@ bool mm_joystick_handler::bindPadToDevice(std::shared_ptr pad, const std::s CELL_PAD_DEV_TYPE_STANDARD ); + joy_device->trigger_left = find_key(m_pad_config.l2); + joy_device->trigger_right = find_key(m_pad_config.r2); + joy_device->axis_left[0] = find_key(m_pad_config.ls_left); + joy_device->axis_left[1] = find_key(m_pad_config.ls_right); + joy_device->axis_left[2] = find_key(m_pad_config.ls_down); + joy_device->axis_left[3] = find_key(m_pad_config.ls_up); + joy_device->axis_right[0] = find_key(m_pad_config.rs_left); + joy_device->axis_right[1] = find_key(m_pad_config.rs_right); + joy_device->axis_right[2] = find_key(m_pad_config.rs_down); + joy_device->axis_right[3] = find_key(m_pad_config.rs_up); + pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE); pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.circle), CELL_PAD_CTRL_CIRCLE); pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.cross), CELL_PAD_CTRL_CROSS); pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.square), CELL_PAD_CTRL_SQUARE); - pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l2), CELL_PAD_CTRL_L2); - pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r2), CELL_PAD_CTRL_R2); + pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_left, CELL_PAD_CTRL_L2); + pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_right, CELL_PAD_CTRL_R2); pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l1), CELL_PAD_CTRL_L1); pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r1), CELL_PAD_CTRL_R1); pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.start), CELL_PAD_CTRL_START); @@ -160,10 +171,10 @@ bool mm_joystick_handler::bindPadToDevice(std::shared_ptr pad, const std::s pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.right), CELL_PAD_CTRL_RIGHT); pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved - pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_key(m_pad_config.ls_left), find_key(m_pad_config.ls_right)); - pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_key(m_pad_config.ls_down), find_key(m_pad_config.ls_up)); - pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_key(m_pad_config.rs_left), find_key(m_pad_config.rs_right)); - pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, find_key(m_pad_config.rs_down), find_key(m_pad_config.rs_up)); + pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, joy_device->axis_left[0], joy_device->axis_left[1]); + pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, joy_device->axis_left[2], joy_device->axis_left[3]); + pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, joy_device->axis_right[0], joy_device->axis_right[1]); + pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, joy_device->axis_right[2], joy_device->axis_right[3]); pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512); pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399); @@ -185,15 +196,18 @@ void mm_joystick_handler::ThreadProc() for (u32 i = 0; i != bindings.size(); ++i) { - auto dev = bindings[i].first; + m_dev = bindings[i].first; auto pad = bindings[i].second; - status = joyGetPosEx(dev->device_id, &dev->device_info); + status = joyGetPosEx(m_dev->device_id, &m_dev->device_info); switch (status) { case JOYERR_UNPLUGGED: if (last_connection_status[i] == true) + { + LOG_ERROR(HLE, "MMJOY Device %d disconnected.", m_dev->device_id); pad->m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES; + } last_connection_status[i] = false; pad->m_port_status &= ~CELL_PAD_STATUS_CONNECTED; break; @@ -202,14 +216,15 @@ void mm_joystick_handler::ThreadProc() ++online; if (last_connection_status[i] == false) { - if (GetMMJOYDevice(dev->device_id, *dev) == false) + if (GetMMJOYDevice(m_dev->device_id, *m_dev) == false) continue; + LOG_SUCCESS(HLE, "MMJOY Device %d reconnected.", m_dev->device_id); pad->m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES; } last_connection_status[i] = true; pad->m_port_status |= CELL_PAD_STATUS_CONNECTED; - auto button_values = GetButtonValues(dev->device_info, dev->device_caps); + auto button_values = GetButtonValues(m_dev->device_info, m_dev->device_caps); // Translate any corresponding keycodes to our normal DS3 buttons and triggers for (auto& btn : pad->m_buttons) @@ -261,7 +276,7 @@ void mm_joystick_handler::ThreadProc() } } -void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist) +void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); @@ -312,10 +327,7 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), keycode) != blacklist.end()) continue; - if (((keycode == mmjoy_axis::joy_z_neg) && (value > m_trigger_threshold)) - || ((keycode == mmjoy_axis::joy_z_pos) && (value > m_trigger_threshold)) - || ((keycode <= mmjoy_axis::joy_y_neg) && (value > m_thumb_threshold)) - || ((keycode <= mmjoy_axis::joy_u_neg && keycode > mmjoy_axis::joy_z_neg) && (value > m_thumb_threshold))) + if (value > m_thumb_threshold) { if (get_blacklist) { @@ -374,14 +386,24 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std return; } + auto find_key = [=](const std::string& name) + { + long key = FindKeyCodeByString(axis_list, name, false); + if (key < 0) + key = FindKeyCodeByString(pov_list, name, false); + if (key < 0) + key = FindKeyCodeByString(button_list, name); + return static_cast(key); + }; + int preview_values[6] = { - data[mmjoy_axis::joy_z_neg], - data[mmjoy_axis::joy_z_pos], - data[mmjoy_axis::joy_x_pos] - data[mmjoy_axis::joy_x_neg], - data[mmjoy_axis::joy_y_pos] - data[mmjoy_axis::joy_y_neg], - data[mmjoy_axis::joy_u_pos] - data[mmjoy_axis::joy_u_neg], - data[mmjoy_axis::joy_r_pos] - data[mmjoy_axis::joy_r_neg] + data[find_key(buttons[0])], + data[find_key(buttons[1])], + data[find_key(buttons[3])] - data[find_key(buttons[2])], + data[find_key(buttons[5])] - data[find_key(buttons[4])], + data[find_key(buttons[7])] - data[find_key(buttons[6])], + data[find_key(buttons[9])] - data[find_key(buttons[8])], }; if (pressed_button.first > 0) @@ -397,34 +419,31 @@ void mm_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& { // Update the pad button values based on their type and thresholds. // With this you can use axis or triggers as buttons or vice versa - switch (keyCode) + + if (keyCode == m_dev->trigger_left) { - case mmjoy_axis::joy_z_neg: - pressed = val > m_pad_config.ltriggerthreshold; + pressed = val > (ignore_threshold ? 0 : m_pad_config.ltriggerthreshold); val = pressed ? NormalizeTriggerInput(val, m_pad_config.ltriggerthreshold) : 0; - break; - case mmjoy_axis::joy_z_pos: - pressed = val > m_pad_config.rtriggerthreshold; + } + else if (keyCode == m_dev->trigger_right) + { + pressed = val > (ignore_threshold ? 0 : m_pad_config.rtriggerthreshold); val = pressed ? NormalizeTriggerInput(val, m_pad_config.rtriggerthreshold) : 0; - break; - case mmjoy_axis::joy_x_pos: - case mmjoy_axis::joy_x_neg: - case mmjoy_axis::joy_y_pos: - case mmjoy_axis::joy_y_neg: + } + else if (std::find(m_dev->axis_left.begin(), m_dev->axis_left.end(), keyCode) != m_dev->axis_left.end()) + { pressed = val > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone); val = pressed ? NormalizeStickInput(val, m_pad_config.lstickdeadzone, ignore_threshold) : 0; - break; - case mmjoy_axis::joy_r_pos: - case mmjoy_axis::joy_r_neg: - case mmjoy_axis::joy_u_pos: - case mmjoy_axis::joy_u_neg: + } + else if (std::find(m_dev->axis_right.begin(), m_dev->axis_right.end(), keyCode) != m_dev->axis_right.end()) + { pressed = val > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone); val = pressed ? NormalizeStickInput(val, m_pad_config.rstickdeadzone, ignore_threshold) : 0; - break; - default: // normal button (should in theory also support sensitive buttons) + } + else // normal button (should in theory also support sensitive buttons) + { pressed = val > 0; val = pressed ? val : 0; - break; } } @@ -503,13 +522,13 @@ std::unordered_map mm_joystick_handler::GetButtonValues(const JOYINFOE }; add_axis_value(js_info.dwXpos, js_caps.wXmin, js_caps.wXmax, mmjoy_axis::joy_x_pos, mmjoy_axis::joy_x_neg); - add_axis_value(js_info.dwYpos, js_caps.wYmin, js_caps.wYmax, mmjoy_axis::joy_y_neg, mmjoy_axis::joy_y_pos); + add_axis_value(js_info.dwYpos, js_caps.wYmin, js_caps.wYmax, mmjoy_axis::joy_y_pos, mmjoy_axis::joy_y_neg); if (js_caps.wCaps & JOYCAPS_HASZ) - add_axis_value(js_info.dwZpos, js_caps.wZmin, js_caps.wZmax, mmjoy_axis::joy_z_neg, mmjoy_axis::joy_z_pos); + add_axis_value(js_info.dwZpos, js_caps.wZmin, js_caps.wZmax, mmjoy_axis::joy_z_pos, mmjoy_axis::joy_z_neg); if (js_caps.wCaps & JOYCAPS_HASR) - add_axis_value(js_info.dwRpos, js_caps.wRmin, js_caps.wRmax, mmjoy_axis::joy_r_neg, mmjoy_axis::joy_r_pos); + add_axis_value(js_info.dwRpos, js_caps.wRmin, js_caps.wRmax, mmjoy_axis::joy_r_pos, mmjoy_axis::joy_r_neg); if (js_caps.wCaps & JOYCAPS_HASU) add_axis_value(js_info.dwUpos, js_caps.wUmin, js_caps.wUmax, mmjoy_axis::joy_u_pos, mmjoy_axis::joy_u_neg); diff --git a/rpcs3/mm_joystick_handler.h b/rpcs3/mm_joystick_handler.h index 00f51ec537..f7922889f4 100644 --- a/rpcs3/mm_joystick_handler.h +++ b/rpcs3/mm_joystick_handler.h @@ -92,6 +92,10 @@ class mm_joystick_handler final : public PadHandlerBase std::string device_name{ "" }; JOYINFOEX device_info; JOYCAPS device_caps; + u64 trigger_left = 0; + u64 trigger_right = 0; + std::vector axis_left = { 0,0,0,0 }; + std::vector axis_right = { 0,0,0,0 }; }; public: @@ -103,7 +107,7 @@ public: std::vector ListDevices() override; bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; - void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false) override; + void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false, std::vector buttons = {}) override; private: void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override; @@ -118,4 +122,5 @@ private: std::unordered_map m_devices; std::vector, std::shared_ptr>> bindings; std::array last_connection_status = {}; + std::shared_ptr m_dev; }; diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp index 468430a1c4..e4afa5559c 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp @@ -96,7 +96,20 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_ connect(&m_timer_input, &QTimer::timeout, [=]() { - m_handler->GetNextButtonPress(m_device_name, callback); + std::vector buttons = + { + m_cfg_entries[button_ids::id_pad_l2].key, + m_cfg_entries[button_ids::id_pad_r2].key, + m_cfg_entries[button_ids::id_pad_lstick_left].key, + m_cfg_entries[button_ids::id_pad_lstick_right].key, + m_cfg_entries[button_ids::id_pad_lstick_down].key, + m_cfg_entries[button_ids::id_pad_lstick_up].key, + m_cfg_entries[button_ids::id_pad_rstick_left].key, + m_cfg_entries[button_ids::id_pad_rstick_right].key, + m_cfg_entries[button_ids::id_pad_rstick_down].key, + m_cfg_entries[button_ids::id_pad_rstick_up].key + }; + m_handler->GetNextButtonPress(m_device_name, callback, false, buttons); }); m_timer_input.start(1); diff --git a/rpcs3/xinput_pad_handler.cpp b/rpcs3/xinput_pad_handler.cpp index ff1b70928f..23676dccbe 100644 --- a/rpcs3/xinput_pad_handler.cpp +++ b/rpcs3/xinput_pad_handler.cpp @@ -70,7 +70,7 @@ xinput_pad_handler::~xinput_pad_handler() Close(); } -void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist) +void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist, std::vector buttons) { if (get_blacklist) blacklist.clear(); diff --git a/rpcs3/xinput_pad_handler.h b/rpcs3/xinput_pad_handler.h index 131c155a62..58598294e7 100644 --- a/rpcs3/xinput_pad_handler.h +++ b/rpcs3/xinput_pad_handler.h @@ -107,7 +107,7 @@ public: std::vector ListDevices() override; bool bindPadToDevice(std::shared_ptr pad, const std::string& device) override; void ThreadProc() override; - void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false) override; + void GetNextButtonPress(const std::string& padId, const std::function& callback, bool get_blacklist = false, std::vector buttons = {}) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; private: