Qt/Input: implement blacklist to Filter Noise in pad dialog

This commit is contained in:
Unknown 2017-11-30 00:43:52 +01:00 committed by Ivan
parent c04c23f33d
commit 853c3f9e39
12 changed files with 263 additions and 158 deletions

View File

@ -546,7 +546,7 @@ public:
bool has_deadzones() { return b_has_deadzones; }; bool has_deadzones() { return b_has_deadzones; };
pad_config* GetConfig() { return &m_pad_config; }; pad_config* GetConfig() { return &m_pad_config; };
//Sets window to config the controller(optional) //Sets window to config the controller(optional)
virtual void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) {}; virtual void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false) {};
virtual void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) {}; virtual void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) {};
//Return list of devices for that handler //Return list of devices for that handler
virtual std::vector<std::string> ListDevices() = 0; virtual std::vector<std::string> ListDevices() = 0;

View File

@ -147,45 +147,15 @@ ds4_pad_handler::ds4_pad_handler() : is_init(false)
m_thumb_threshold = thumb_max / 2; m_thumb_threshold = thumb_max / 2;
} }
void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist)
{ {
if (!Init()) if (get_blacklist)
{ blacklist.clear();
std::shared_ptr<DS4Device> device = GetDevice(padId);
if (CheckDeviceState(device) == false)
return; return;
}
// Get the DS4 Device or return if none found
size_t pos = padId.find("Ds4 Pad #");
if (pos == std::string::npos) return;
std::string pad_serial = padId.substr(pos + 9);
std::shared_ptr<DS4Device> device = nullptr;
for (auto& cur_control : controllers)
{
if (pad_serial == cur_control.first)
{
device = cur_control.second;
break;
}
}
if (device == nullptr || device->hidDevice == nullptr) return;
// Now that we have found a device, get its status
DS4DataStatus status = GetRawData(device);
if (status == DS4DataStatus::ReadError)
{
// this also can mean disconnected, either way deal with it on next loop and reconnect
hid_close(device->hidDevice);
device->hidDevice = nullptr;
return;
}
if (status != DS4DataStatus::NewData) return;
// Get the current button values // Get the current button values
auto data = GetButtonValues(device); auto data = GetButtonValues(device);
@ -199,19 +169,32 @@ void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::fu
u32 keycode = button.first; u32 keycode = button.first;
u16 value = data[keycode]; u16 value = data[keycode];
if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), keycode) != blacklist.end())
continue;
if (((keycode < DS4KeyCodes::L2) && (value > 0)) if (((keycode < DS4KeyCodes::L2) && (value > 0))
|| ((keycode == DS4KeyCodes::L2) && (value > m_trigger_threshold)) || ((keycode == DS4KeyCodes::L2) && (value > m_trigger_threshold))
|| ((keycode == DS4KeyCodes::R2) && (value > m_trigger_threshold)) || ((keycode == DS4KeyCodes::R2) && (value > m_trigger_threshold))
|| ((keycode >= DS4KeyCodes::LSXNeg && keycode <= DS4KeyCodes::LSYPos) && (value > m_thumb_threshold)) || ((keycode >= DS4KeyCodes::LSXNeg && keycode <= DS4KeyCodes::LSYPos) && (value > m_thumb_threshold))
|| ((keycode >= DS4KeyCodes::RSXNeg && keycode <= DS4KeyCodes::RSYPos) && (value > m_thumb_threshold))) || ((keycode >= DS4KeyCodes::RSXNeg && keycode <= DS4KeyCodes::RSYPos) && (value > m_thumb_threshold)))
{ {
if (value > pressed_button.first) if (get_blacklist)
{ {
pressed_button = { value, button.second}; blacklist.emplace_back(keycode);
LOG_ERROR(HLE, "DS4 Calibration: Added key [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
} }
else if (value > pressed_button.first)
pressed_button = { value, button.second };
} }
} }
if (get_blacklist)
{
if (blacklist.size() <= 0)
LOG_SUCCESS(HLE, "DS4 Calibration: Blacklist is clear. No input spam detected");
return;
}
int preview_values[6] = { data[L2], data[R2], data[LSXPos] - data[LSXNeg], data[LSYPos] - data[LSYNeg], data[RSXPos] - data[RSXNeg], data[RSYPos] - data[RSYNeg] }; int preview_values[6] = { data[L2], data[R2], data[LSXPos] - data[LSXNeg], data[LSYPos] - data[LSYNeg], data[RSXPos] - data[RSXNeg], data[RSYPos] - data[RSYNeg] };
if (pressed_button.first > 0) if (pressed_button.first > 0)
@ -222,17 +205,28 @@ void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::fu
void ds4_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) void ds4_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor)
{ {
if (!Init()) std::shared_ptr<DS4Device> device = GetDevice(padId);
{ if (device == nullptr || device->hidDevice == nullptr)
return; return;
}
// Set the device's motor speeds to our requested values 0-255
device->largeVibrate = largeMotor;
device->smallVibrate = smallMotor;
// Start/Stop the engines :)
SendVibrateData(device);
}
std::shared_ptr<ds4_pad_handler::DS4Device> ds4_pad_handler::GetDevice(const std::string& padId)
{
if (!Init())
return nullptr;
size_t pos = padId.find("Ds4 Pad #"); size_t pos = padId.find("Ds4 Pad #");
if (pos == std::string::npos)
if (pos == std::string::npos) return; return nullptr;
std::string pad_serial = padId.substr(pos + 9); std::string pad_serial = padId.substr(pos + 9);
std::shared_ptr<DS4Device> device = nullptr; std::shared_ptr<DS4Device> device = nullptr;
for (auto& cur_control : controllers) for (auto& cur_control : controllers)
@ -244,14 +238,29 @@ void ds4_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u3
} }
} }
if (device == nullptr || device->hidDevice == nullptr) return; return device;
}
// Set the device's motor speeds to our requested values 0-255 bool ds4_pad_handler::CheckDeviceState(std::shared_ptr<DS4Device> device)
device->largeVibrate = largeMotor; {
device->smallVibrate = smallMotor; if (device == nullptr || device->hidDevice == nullptr)
return false;
// Start/Stop the engines :) // Now that we have found a device, get its status
SendVibrateData(device); DS4DataStatus status = GetRawData(device);
if (status == DS4DataStatus::ReadError)
{
// this also can mean disconnected, either way deal with it on next loop and reconnect
hid_close(device->hidDevice);
device->hidDevice = nullptr;
return false;
}
if (status != DS4DataStatus::NewData)
return false;
return true;
} }
void ds4_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold) void ds4_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold)
@ -754,24 +763,9 @@ std::vector<std::string> ds4_pad_handler::ListDevices()
bool ds4_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) bool ds4_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device)
{ {
size_t pos = device.find("Ds4 Pad #"); std::shared_ptr<DS4Device> ds4device = GetDevice(device);
if (ds4device == nullptr || ds4device->hidDevice == nullptr)
if (pos == std::string::npos) return false; return false;
std::string pad_serial = device.substr(pos + 9);
std::shared_ptr<DS4Device> device_id = nullptr;
for (auto& cur_control : controllers)
{
if (pad_serial == cur_control.first)
{
device_id = cur_control.second;
break;
}
}
if (device_id == nullptr) return false;
m_pad_config.load(); m_pad_config.load();
@ -816,7 +810,7 @@ bool ds4_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::strin
pad->m_vibrateMotors.emplace_back(true, 0); pad->m_vibrateMotors.emplace_back(true, 0);
pad->m_vibrateMotors.emplace_back(false, 0); pad->m_vibrateMotors.emplace_back(false, 0);
bindings.emplace_back(device_id, pad); bindings.emplace_back(ds4device, pad);
return true; return true;
} }

View File

@ -141,7 +141,7 @@ public:
std::vector<std::string> ListDevices() override; std::vector<std::string> ListDevices() override;
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override; bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
void ThreadProc() override; void ThreadProc() override;
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& buttonCallback) override; void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& buttonCallback, bool get_blacklist = false) override;
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
private: private:
@ -149,10 +149,12 @@ private:
// holds internal controller state change // holds internal controller state change
std::array<bool, MAX_GAMEPADS> last_connection_status = {}; std::array<bool, MAX_GAMEPADS> last_connection_status = {};
std::vector<u32> blacklist;
std::vector<std::pair<std::shared_ptr<DS4Device>, std::shared_ptr<Pad>>> bindings; std::vector<std::pair<std::shared_ptr<DS4Device>, std::shared_ptr<Pad>>> bindings;
private: private:
std::shared_ptr<DS4Device> GetDevice(const std::string& padId);
bool CheckDeviceState(std::shared_ptr<DS4Device> device);
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override; void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
void ProcessDataToPad(const std::shared_ptr<DS4Device>& ds4Device, const std::shared_ptr<Pad>& pad); void ProcessDataToPad(const std::shared_ptr<DS4Device>& ds4Device, const std::shared_ptr<Pad>& pad);
// Copies data into padData if status is NewData, otherwise buffer is untouched // Copies data into padData if status is NewData, otherwise buffer is untouched

View File

@ -213,8 +213,11 @@ std::unordered_map<u64, std::pair<u16, bool>> evdev_joystick_handler::GetButtonV
return button_values; return button_values;
} }
void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist)
{ {
if (get_blacklist)
blacklist.clear();
// Add device if not yet present // Add device if not yet present
m_pad_index = add_device(padId, true); m_pad_index = add_device(padId, true);
@ -243,22 +246,41 @@ void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const
std::pair<u16, std::string> pressed_button = { 0, "" }; std::pair<u16, std::string> pressed_button = { 0, "" };
for (const auto& button : button_list) for (const auto& button : button_list)
{ {
if (padId.find("Xbox 360") != std::string::npos && button.first >= BTN_TRIGGER_HAPPY) int code = button.first;
std::string name = button.second;
if (padId.find("Xbox 360") != std::string::npos && code >= BTN_TRIGGER_HAPPY)
continue; continue;
if (padId.find("Sony") != std::string::npos && (button.first == BTN_TL2 || button.first == BTN_TR2)) if (padId.find("Sony") != std::string::npos && (code == BTN_TL2 || code == BTN_TR2))
continue; continue;
u16 value = data[button.first].first; if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end())
if (value > 0 && value > pressed_button.first) continue;
pressed_button = { value, button.second };
u16 value = data[code].first;
if (value > 0)
{
if (get_blacklist)
{
blacklist.emplace_back(name);
LOG_ERROR(HLE, "Evdev Calibration: Added button [ %d = %s ] to blacklist. Value = %d", code, name, value);
}
else if (value > pressed_button.first)
pressed_button = { value, name };
}
} }
for (const auto& button : axis_list) for (const auto& button : axis_list)
{ {
int code = button.first; int code = button.first;
std::string name = button.second;
if (data[code].second) if (data[code].second)
continue; continue;
if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end())
continue;
u16 value = data[code].first; u16 value = data[code].first;
if (((code == ABS_X || code == ABS_Y) && value < m_thumb_threshold) if (((code == ABS_X || code == ABS_Y) && value < m_thumb_threshold)
@ -267,16 +289,29 @@ void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const
|| (code == ABS_RZ && value < m_trigger_threshold)) || (code == ABS_RZ && value < m_trigger_threshold))
continue; continue;
if (value > 0 && value > pressed_button.first) if (value > 0)
pressed_button = { value, button.second }; {
if (get_blacklist)
{
blacklist.emplace_back(name);
LOG_ERROR(HLE, "Evdev Calibration: Added axis [ %d = %s ] to blacklist. Value = %d", code, name, value);
}
else if (value > pressed_button.first)
pressed_button = { value, name };
}
} }
for (const auto& button : rev_axis_list) for (const auto& button : rev_axis_list)
{ {
int code = button.first; int code = button.first;
std::string name = button.second;
if (!data[code].second) if (!data[code].second)
continue; continue;
if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end())
continue;
u16 value = data[code].first; u16 value = data[code].first;
if (((code == ABS_X || code == ABS_Y) && value < m_thumb_threshold) if (((code == ABS_X || code == ABS_Y) && value < m_thumb_threshold)
@ -285,8 +320,23 @@ void evdev_joystick_handler::GetNextButtonPress(const std::string& padId, const
|| (code == ABS_RZ && value < m_trigger_threshold)) || (code == ABS_RZ && value < m_trigger_threshold))
continue; continue;
if (value > 0 && value > pressed_button.first) if (value > 0)
pressed_button = { value, button.second }; {
if (get_blacklist)
{
blacklist.emplace_back(name);
LOG_ERROR(HLE, "Evdev Calibration: Added rev axis [ %d = %s ] to blacklist. Value = %d", code, name, value);
}
else if (value > pressed_button.first)
pressed_button = { value, name };
}
}
if (get_blacklist)
{
if (blacklist.size() <= 0)
LOG_SUCCESS(HLE, "Evdev Calibration: Blacklist is clear. No input spam detected");
return;
} }
// get stick values // get stick values

View File

@ -247,7 +247,7 @@ public:
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override; bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
void ThreadProc() override; void ThreadProc() override;
void Close(); void Close();
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) override; void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false) override;
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
private: private:
@ -261,6 +261,7 @@ private:
// Search axis_orientations map for the direction by index, returns -1 if not found, 0 for positive and 1 for negative // Search axis_orientations map for the direction by index, returns -1 if not found, 0 for positive and 1 for negative
int FindAxisDirection(const std::unordered_map<int, bool>& map, int index); int FindAxisDirection(const std::unordered_map<int, bool>& map, int index);
std::vector<std::string> blacklist;
std::vector<EvdevDevice> devices; std::vector<EvdevDevice> devices;
int m_pad_index = -1; int m_pad_index = -1;
}; };

View File

@ -284,12 +284,13 @@ void mm_joystick_handler::ThreadProc()
} }
} }
void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist)
{ {
if (get_blacklist)
blacklist.clear();
if (!Init()) if (!Init())
{
return; return;
}
static std::string cur_pad = ""; static std::string cur_pad = "";
static int id = -1; static int id = -1;
@ -328,33 +329,72 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std
for (const auto& button : axis_list) for (const auto& button : axis_list)
{ {
u32 keycode = button.first; u64 keycode = button.first;
u16 value = data[keycode]; u16 value = data[keycode];
if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), keycode) != blacklist.end())
continue;
if (((keycode == mmjoy_axis::joy_z_neg) && (value > m_trigger_threshold)) 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_z_pos) && (value > m_trigger_threshold))
|| ((keycode <= mmjoy_axis::joy_y_neg) && (value > m_thumb_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))) || ((keycode <= mmjoy_axis::joy_u_neg && keycode > mmjoy_axis::joy_z_neg) && (value > m_thumb_threshold)))
{ {
if (value > pressed_button.first) if (get_blacklist)
{ {
pressed_button = { value, button.second }; blacklist.emplace_back(keycode);
LOG_ERROR(HLE, "MMJOY Calibration: Added axis [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
} }
else if (value > pressed_button.first)
pressed_button = { value, button.second };
} }
} }
for (const auto& button : pov_list) for (const auto& button : pov_list)
{ {
u16 value = data[button.first]; u64 keycode = button.first;
if (value > 0 && value > pressed_button.first) u16 value = data[keycode];
pressed_button = { value, button.second };
if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), keycode) != blacklist.end())
continue;
if (value > 0)
{
if (get_blacklist)
{
blacklist.emplace_back(keycode);
LOG_ERROR(HLE, "MMJOY Calibration: Added pov [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
}
else if (value > pressed_button.first)
pressed_button = { value, button.second };
}
} }
for (const auto& button : button_list) for (const auto& button : button_list)
{ {
u16 value = data[button.first]; u64 keycode = button.first;
if (value > 0 && value > pressed_button.first) u16 value = data[keycode];
pressed_button = { value, button.second };
if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), keycode) != blacklist.end())
continue;
if (value > 0)
{
if (get_blacklist)
{
blacklist.emplace_back(keycode);
LOG_ERROR(HLE, "MMJOY Calibration: Added button [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
}
else if (value > pressed_button.first)
pressed_button = { value, button.second };
}
}
if (get_blacklist)
{
if (blacklist.size() <= 0)
LOG_SUCCESS(HLE, "MMJOY Calibration: Blacklist is clear. No input spam detected");
return;
} }
int preview_values[6] = int preview_values[6] =

View File

@ -103,7 +103,7 @@ public:
std::vector<std::string> ListDevices() override; std::vector<std::string> ListDevices() override;
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override; bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
void ThreadProc() override; void ThreadProc() override;
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) override; void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false) override;
private: private:
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override; void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
@ -113,6 +113,7 @@ private:
bool is_init = false; bool is_init = false;
u32 supportedJoysticks = 0; u32 supportedJoysticks = 0;
std::vector<u64> blacklist;
std::unordered_map<int, MMJOYDevice> m_devices; std::unordered_map<int, MMJOYDevice> m_devices;
std::vector<std::pair<std::shared_ptr<MMJOYDevice>, std::shared_ptr<Pad>>> bindings; std::vector<std::pair<std::shared_ptr<MMJOYDevice>, std::shared_ptr<Pad>>> bindings;
std::array<bool, 7> last_connection_status = {}; std::array<bool, 7> last_connection_status = {};

View File

@ -37,6 +37,7 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
{ {
setWindowTitle(tr("Configure Keyboard")); setWindowTitle(tr("Configure Keyboard"));
m_handler_type = handler_type::handler_type_keyboard; m_handler_type = handler_type::handler_type_keyboard;
ui->b_blacklist->setEnabled(false);
} }
else if (m_handler_cfg->cfg_type == "xinput") else if (m_handler_cfg->cfg_type == "xinput")
{ {
@ -241,9 +242,10 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg->rs_right); insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg->rs_right);
insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg->rs_up); insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg->rs_up);
m_padButtons->addButton(ui->b_reset, button_ids::id_reset_parameters); m_padButtons->addButton(ui->b_reset, button_ids::id_reset_parameters);
m_padButtons->addButton(ui->b_ok, button_ids::id_ok); m_padButtons->addButton(ui->b_blacklist, button_ids::id_blacklist);
m_padButtons->addButton(ui->b_cancel, button_ids::id_cancel); m_padButtons->addButton(ui->b_ok, button_ids::id_ok);
m_padButtons->addButton(ui->b_cancel, button_ids::id_cancel);
connect(m_padButtons, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &pad_settings_dialog::OnPadButtonClicked); connect(m_padButtons, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &pad_settings_dialog::OnPadButtonClicked);
@ -415,6 +417,9 @@ void pad_settings_dialog::OnPadButtonClicked(int id)
m_handler_cfg->from_default(); m_handler_cfg->from_default();
UpdateLabel(true); UpdateLabel(true);
return; return;
case button_ids::id_blacklist:
m_handler->GetNextButtonPress(m_device_name, nullptr, true);
return;
case button_ids::id_ok: case button_ids::id_ok:
SaveConfig(); SaveConfig();
QDialog::accept(); QDialog::accept();

View File

@ -67,6 +67,7 @@ class pad_settings_dialog : public QDialog
id_pad_end, // end id_pad_end, // end
id_reset_parameters, id_reset_parameters,
id_blacklist,
id_ok, id_ok,
id_cancel id_cancel
}; };

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>892</width> <width>1044</width>
<height>568</height> <height>640</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -1729,14 +1729,25 @@
</spacer> </spacer>
</item> </item>
<item> <item>
<widget class="QPushButton" name="b_reset"> <layout class="QHBoxLayout" name="horizontalLayout_20" stretch="1,1">
<property name="text"> <item>
<string>Restore Defaults</string> <widget class="QPushButton" name="b_blacklist">
</property> <property name="text">
<property name="autoDefault"> <string>Filter Noise</string>
<bool>false</bool> </property>
</property> </widget>
</widget> </item>
<item>
<widget class="QPushButton" name="b_reset">
<property name="text">
<string>Restore Defaults</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</item> </item>

View File

@ -70,37 +70,23 @@ xinput_pad_handler::~xinput_pad_handler()
Close(); Close();
} }
void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist)
{ {
if (!Init()) if (get_blacklist)
{ blacklist.clear();
int device_number = GetDeviceNumber(padId);
if (device_number < 0)
return; return;
}
size_t pos = padId.find("Xinput Pad #");
int device_number;
if (pos != std::string::npos)
{
device_number = std::stoul(padId.substr(pos + 12));
}
if (pos == std::string::npos || device_number >= XUSER_MAX_COUNT)
{
return;
}
DWORD dwResult; DWORD dwResult;
XINPUT_STATE state; XINPUT_STATE state;
ZeroMemory(&state, sizeof(XINPUT_STATE)); ZeroMemory(&state, sizeof(XINPUT_STATE));
// Simply get the state of the controller from XInput. // Simply get the state of the controller from XInput.
dwResult = (*xinputGetState)(device_number, &state); dwResult = (*xinputGetState)(static_cast<u32>(device_number), &state);
if (dwResult != ERROR_SUCCESS) if (dwResult != ERROR_SUCCESS)
{
return; return;
}
// Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed. // Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed.
// Return the new value if the button was pressed (aka. its value was bigger than 0 or the defined threshold) // Return the new value if the button was pressed (aka. its value was bigger than 0 or the defined threshold)
@ -112,19 +98,32 @@ void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std:
u32 keycode = button.first; u32 keycode = button.first;
u16 value = data[keycode]; u16 value = data[keycode];
if (!get_blacklist && std::find(blacklist.begin(), blacklist.end(), keycode) != blacklist.end())
continue;
if (((keycode < XInputKeyCodes::LT) && (value > 0)) if (((keycode < XInputKeyCodes::LT) && (value > 0))
|| ((keycode == XInputKeyCodes::LT) && (value > m_trigger_threshold)) || ((keycode == XInputKeyCodes::LT) && (value > m_trigger_threshold))
|| ((keycode == XInputKeyCodes::RT) && (value > m_trigger_threshold)) || ((keycode == XInputKeyCodes::RT) && (value > m_trigger_threshold))
|| ((keycode >= XInputKeyCodes::LSXNeg && keycode <= XInputKeyCodes::LSYPos) && (value > m_thumb_threshold)) || ((keycode >= XInputKeyCodes::LSXNeg && keycode <= XInputKeyCodes::LSYPos) && (value > m_thumb_threshold))
|| ((keycode >= XInputKeyCodes::RSXNeg && keycode <= XInputKeyCodes::RSYPos) && (value > m_thumb_threshold))) || ((keycode >= XInputKeyCodes::RSXNeg && keycode <= XInputKeyCodes::RSYPos) && (value > m_thumb_threshold)))
{ {
if (value > pressed_button.first) if (get_blacklist)
{ {
pressed_button = { value, button.second }; blacklist.emplace_back(keycode);
LOG_ERROR(HLE, "XInput Calibration: Added key [ %d = %s ] to blacklist. Value = %d", keycode, button.second, value);
} }
else if (value > pressed_button.first)
pressed_button = { value, button.second };
} }
} }
if (get_blacklist)
{
if (blacklist.size() <= 0)
LOG_SUCCESS(HLE, "XInput Calibration: Blacklist is clear. No input spam detected");
return;
}
int preview_values[6] = { data[LT], data[RT], data[LSXPos] - data[LSXNeg], data[LSYPos] - data[LSYNeg], data[RSXPos] - data[RSXNeg], data[RSYPos] - data[RSYNeg] }; int preview_values[6] = { data[LT], data[RT], data[LSXPos] - data[LSXNeg], data[LSYPos] - data[LSYNeg], data[RSXPos] - data[RSXNeg], data[RSYPos] - data[RSYNeg] };
if (pressed_button.first > 0) if (pressed_button.first > 0)
@ -135,23 +134,9 @@ void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std:
void xinput_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) void xinput_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor)
{ {
if (!Init()) int device_number = GetDeviceNumber(padId);
{ if (device_number < 0)
return; return;
}
u32 device_number = 0;
size_t pos = padId.find("Xinput Pad #");
if (pos != std::string::npos)
{
device_number = std::stoul(padId.substr(pos + 12));
}
if (pos == std::string::npos || device_number >= XUSER_MAX_COUNT)
{
return;
}
// The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor. // The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor.
// The two motors are not the same, and they create different vibration effects. // The two motors are not the same, and they create different vibration effects.
@ -160,7 +145,7 @@ void xinput_pad_handler::TestVibration(const std::string& padId, u32 largeMotor,
vibrate.wLeftMotorSpeed = largeMotor; // between 0 to 65535 vibrate.wLeftMotorSpeed = largeMotor; // between 0 to 65535
vibrate.wRightMotorSpeed = smallMotor; // between 0 to 65535 vibrate.wRightMotorSpeed = smallMotor; // between 0 to 65535
(*xinputSetState)(device_number, &vibrate); (*xinputSetState)(static_cast<u32>(device_number), &vibrate);
} }
void xinput_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold) void xinput_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold)
@ -198,6 +183,22 @@ void xinput_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& v
} }
} }
int xinput_pad_handler::GetDeviceNumber(const std::string& padId)
{
if (!Init())
return -1;
size_t pos = padId.find("Xinput Pad #");
if (pos == std::string::npos)
return -1;
int device_number = std::stoul(padId.substr(pos + 12));
if (device_number >= XUSER_MAX_COUNT)
return -1;
return device_number;
}
std::array<u16, xinput_pad_handler::XInputKeyCodes::KeyCodeCount> xinput_pad_handler::GetButtonValues(const XINPUT_STATE& state) std::array<u16, xinput_pad_handler::XInputKeyCodes::KeyCodeCount> xinput_pad_handler::GetButtonValues(const XINPUT_STATE& state)
{ {
std::array<u16, xinput_pad_handler::XInputKeyCodes::KeyCodeCount> values; std::array<u16, xinput_pad_handler::XInputKeyCodes::KeyCodeCount> values;
@ -451,15 +452,12 @@ std::vector<std::string> xinput_pad_handler::ListDevices()
bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device)
{ {
//Convert device string to u32 representing xinput device number //Convert device string to u32 representing xinput device number
u32 device_number = 0; int device_number = GetDeviceNumber(device);
size_t pos = device.find("Xinput Pad #"); if (device_number < 0)
return false;
if (pos != std::string::npos) device_number = std::stoul(device.substr(pos + 12));
if (pos == std::string::npos || device_number >= XUSER_MAX_COUNT) return false;
std::shared_ptr<XInputDevice> device_id = std::make_shared<XInputDevice>(); std::shared_ptr<XInputDevice> device_id = std::make_shared<XInputDevice>();
device_id->deviceNumber = device_number; device_id->deviceNumber = static_cast<u32>(device_number);
m_pad_config.load(); m_pad_config.load();

View File

@ -107,7 +107,7 @@ public:
std::vector<std::string> ListDevices() override; std::vector<std::string> ListDevices() override;
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override; bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
void ThreadProc() override; void ThreadProc() override;
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback) override; void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false) override;
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override; void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
private: private:
@ -117,6 +117,7 @@ private:
typedef DWORD (WINAPI * PFN_XINPUTGETBATTERYINFORMATION)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION *); typedef DWORD (WINAPI * PFN_XINPUTGETBATTERYINFORMATION)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION *);
private: private:
int GetDeviceNumber(const std::string& padId);
std::array<u16, XInputKeyCodes::KeyCodeCount> GetButtonValues(const XINPUT_STATE& state); std::array<u16, XInputKeyCodes::KeyCodeCount> GetButtonValues(const XINPUT_STATE& state);
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override; void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
@ -127,6 +128,7 @@ private:
PFN_XINPUTENABLE xinputEnable; PFN_XINPUTENABLE xinputEnable;
PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation; PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation;
std::vector<u32> blacklist;
std::vector<std::pair<std::shared_ptr<XInputDevice>, std::shared_ptr<Pad>>> bindings; std::vector<std::pair<std::shared_ptr<XInputDevice>, std::shared_ptr<Pad>>> bindings;
std::array<bool, 7> last_connection_status = {}; std::array<bool, 7> last_connection_status = {};