Input: Abbreviate some variable names and add min output interval

The abbreviation allows for easier diff between handlers.
This commit is contained in:
Megamouse 2024-08-17 11:21:11 +02:00
parent 9a071746ed
commit 08f81160cc
14 changed files with 246 additions and 221 deletions

View file

@ -23,6 +23,8 @@ public:
u8 player_id{0}; u8 player_id{0};
u8 large_motor{0}; u8 large_motor{0};
u8 small_motor{0}; u8 small_motor{0};
bool new_output_data{true};
steady_clock::time_point last_output;
std::set<u64> trigger_code_left{}; std::set<u64> trigger_code_left{};
std::set<u64> trigger_code_right{}; std::set<u64> trigger_code_right{};
std::array<std::set<u64>, 4> axis_code_left{}; std::array<std::set<u64>, 4> axis_code_left{};
@ -114,6 +116,7 @@ protected:
static constexpr u32 MAX_GAMEPADS = 7; static constexpr u32 MAX_GAMEPADS = 7;
static constexpr u16 button_press_threshold = 50; static constexpr u16 button_press_threshold = 50;
static constexpr u16 touch_threshold = static_cast<u16>(255 * 0.9f); static constexpr u16 touch_threshold = static_cast<u16>(255 * 0.9f);
static constexpr auto min_output_interval = 300ms;
std::array<bool, MAX_GAMEPADS> last_connection_status{{ false, false, false, false, false, false, false }}; std::array<bool, MAX_GAMEPADS> last_connection_status{{ false, false, false, false, false, false, false }};

View file

@ -421,14 +421,14 @@ void ds3_pad_handler::get_extended_info(const pad_ensemble& binding)
const auto& device = binding.device; const auto& device = binding.device;
const auto& pad = binding.pad; const auto& pad = binding.pad;
ds3_device* ds3dev = static_cast<ds3_device*>(device.get()); ds3_device* dev = static_cast<ds3_device*>(device.get());
if (!ds3dev || !pad) if (!dev || !pad)
return; return;
const ds3_input_report& report = ds3dev->report; const ds3_input_report& report = dev->report;
pad->m_battery_level = ds3dev->battery_level; pad->m_battery_level = dev->battery_level;
pad->m_cable_state = ds3dev->cable_state; pad->m_cable_state = dev->cable_state;
// For unknown reasons the sixaxis values seem to be in little endian on linux // For unknown reasons the sixaxis values seem to be in little endian on linux
@ -510,14 +510,13 @@ PadHandlerBase::connection ds3_pad_handler::update_connection(const std::shared_
if (dev->hidDevice == nullptr) if (dev->hidDevice == nullptr)
{ {
hid_device* devhandle = hid_open_path(dev->path.c_str()); if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
if (devhandle)
{ {
if (hid_set_nonblocking(devhandle, 1) == -1) if (hid_set_nonblocking(hid_dev, 1) == -1)
{ {
ds3_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(devhandle)); ds3_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev));
} }
dev->hidDevice = devhandle; dev->hidDevice = hid_dev;
} }
else else
{ {
@ -598,11 +597,15 @@ void ds3_pad_handler::apply_pad_data(const pad_ensemble& binding)
dev->large_motor = speed_large; dev->large_motor = speed_large;
dev->small_motor = speed_small; dev->small_motor = speed_small;
if (dev->new_output_data) const auto now = steady_clock::now();
const auto elapsed = now - dev->last_output;
if (dev->new_output_data || elapsed > min_output_interval)
{ {
if (const int res = send_output_report(dev); res >= 0) if (const int res = send_output_report(dev); res >= 0)
{ {
dev->new_output_data = false; dev->new_output_data = false;
dev->last_output = now;
} }
else if (res == -1) else if (res == -1)
{ {

View file

@ -253,11 +253,11 @@ void ds4_pad_handler::SetPadData(const std::string& padId, u8 player_id, u8 larg
std::unordered_map<u64, u16> ds4_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device) std::unordered_map<u64, u16> ds4_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device)
{ {
std::unordered_map<u64, u16> keyBuffer; std::unordered_map<u64, u16> keyBuffer;
DS4Device* ds4_dev = static_cast<DS4Device*>(device.get()); DS4Device* dev = static_cast<DS4Device*>(device.get());
if (!ds4_dev) if (!dev)
return keyBuffer; return keyBuffer;
const ds4_input_report_common& input = ds4_dev->bt_controller ? ds4_dev->report_bt.common : ds4_dev->report_usb.common; const ds4_input_report_common& input = dev->bt_controller ? dev->report_bt.common : dev->report_usb.common;
// Left Stick X Axis // Left Stick X Axis
keyBuffer[DS4KeyCodes::LSXNeg] = Clamp0To255((127.5f - input.x) * 2.0f); keyBuffer[DS4KeyCodes::LSXNeg] = Clamp0To255((127.5f - input.x) * 2.0f);
@ -383,9 +383,9 @@ std::unordered_map<u64, u16> ds4_pad_handler::get_button_values(const std::share
} }
}; };
if (ds4_dev->bt_controller) if (dev->bt_controller)
{ {
const ds4_input_report_bt& report = ds4_dev->report_bt; const ds4_input_report_bt& report = dev->report_bt;
for (u32 i = 0; i < std::min<u32>(report.num_touch_reports, ::size32(report.touch_reports)); i++) for (u32 i = 0; i < std::min<u32>(report.num_touch_reports, ::size32(report.touch_reports)); i++)
{ {
@ -394,7 +394,7 @@ std::unordered_map<u64, u16> ds4_pad_handler::get_button_values(const std::share
} }
else else
{ {
const ds4_input_report_usb& report = ds4_dev->report_usb; const ds4_input_report_usb& report = dev->report_usb;
for (u32 i = 0; i < std::min<u32>(report.num_touch_reports, ::size32(report.touch_reports)); i++) for (u32 i = 0; i < std::min<u32>(report.num_touch_reports, ::size32(report.touch_reports)); i++)
{ {
@ -828,23 +828,26 @@ bool ds4_pad_handler::get_is_touch_pad_motion(const std::shared_ptr<PadDevice>&
PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device) PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{ {
DS4Device* ds4_dev = static_cast<DS4Device*>(device.get()); DS4Device* dev = static_cast<DS4Device*>(device.get());
if (!ds4_dev || ds4_dev->path.empty()) if (!dev || dev->path.empty())
return connection::disconnected; return connection::disconnected;
if (ds4_dev->hidDevice == nullptr) if (dev->hidDevice == nullptr)
{ {
// try to reconnect // try to reconnect
hid_device* dev = hid_open_path(ds4_dev->path.c_str()); if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
if (dev)
{ {
if (hid_set_nonblocking(dev, 1) == -1) if (hid_set_nonblocking(hid_dev, 1) == -1)
{ {
ds4_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", ds4_dev->path, hid_error(dev)); ds4_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev));
}
dev->hidDevice = hid_dev;
if (!dev->has_calib_data)
{
dev->has_calib_data = GetCalibrationData(dev);
} }
ds4_dev->hidDevice = dev;
if (!ds4_dev->has_calib_data)
ds4_dev->has_calib_data = GetCalibrationData(ds4_dev);
} }
else else
{ {
@ -853,10 +856,10 @@ PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_
} }
} }
if (get_data(ds4_dev) == DataStatus::ReadError) if (get_data(dev) == DataStatus::ReadError)
{ {
// this also can mean disconnected, either way deal with it on next loop and reconnect // this also can mean disconnected, either way deal with it on next loop and reconnect
ds4_dev->close(); dev->close();
return connection::no_data; return connection::no_data;
} }
@ -869,14 +872,14 @@ void ds4_pad_handler::get_extended_info(const pad_ensemble& binding)
const auto& device = binding.device; const auto& device = binding.device;
const auto& pad = binding.pad; const auto& pad = binding.pad;
DS4Device* ds4_device = static_cast<DS4Device*>(device.get()); DS4Device* dev = static_cast<DS4Device*>(device.get());
if (!ds4_device || !pad) if (!dev || !pad)
return; return;
const ds4_input_report_common& input = ds4_device->bt_controller ? ds4_device->report_bt.common : ds4_device->report_usb.common; const ds4_input_report_common& input = dev->bt_controller ? dev->report_bt.common : dev->report_usb.common;
pad->m_battery_level = ds4_device->battery_level; pad->m_battery_level = dev->battery_level;
pad->m_cable_state = ds4_device->cable_state; pad->m_cable_state = dev->cable_state;
// these values come already calibrated, all we need to do is convert to ds3 range // these values come already calibrated, all we need to do is convert to ds3 range
@ -910,11 +913,11 @@ void ds4_pad_handler::apply_pad_data(const pad_ensemble& binding)
const auto& device = binding.device; const auto& device = binding.device;
const auto& pad = binding.pad; const auto& pad = binding.pad;
DS4Device* ds4_dev = static_cast<DS4Device*>(device.get()); DS4Device* dev = static_cast<DS4Device*>(device.get());
if (!ds4_dev || !ds4_dev->hidDevice || !ds4_dev->config || !pad) if (!dev || !dev->hidDevice || !dev->config || !pad)
return; return;
cfg_pad* config = ds4_dev->config; cfg_pad* config = dev->config;
// Attempt to send rumble no matter what // Attempt to send rumble no matter what
const int idx_l = config->switch_vibration_motors ? 1 : 0; const int idx_l = config->switch_vibration_motors ? 1 : 0;
@ -923,9 +926,9 @@ void ds4_pad_handler::apply_pad_data(const pad_ensemble& binding)
const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0; const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0; const u8 speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
const bool wireless = ds4_dev->cable_state == 0; const bool wireless = dev->cable_state == 0;
const bool low_battery = ds4_dev->battery_level < 2; const bool low_battery = dev->battery_level < 2;
const bool is_blinking = ds4_dev->led_delay_on > 0 || ds4_dev->led_delay_off > 0; const bool is_blinking = dev->led_delay_on > 0 || dev->led_delay_off > 0;
// Blink LED when battery is low // Blink LED when battery is low
if (config->led_low_battery_blink) if (config->led_low_battery_blink)
@ -933,16 +936,16 @@ void ds4_pad_handler::apply_pad_data(const pad_ensemble& binding)
// we are now wired or have okay battery level -> stop blinking // we are now wired or have okay battery level -> stop blinking
if (is_blinking && !(wireless && low_battery)) if (is_blinking && !(wireless && low_battery))
{ {
ds4_dev->led_delay_on = 0; dev->led_delay_on = 0;
ds4_dev->led_delay_off = 0; dev->led_delay_off = 0;
ds4_dev->new_output_data = true; dev->new_output_data = true;
} }
// we are now wireless and low on battery -> blink // we are now wireless and low on battery -> blink
else if (!is_blinking && wireless && low_battery) else if (!is_blinking && wireless && low_battery)
{ {
ds4_dev->led_delay_on = 100; dev->led_delay_on = 100;
ds4_dev->led_delay_off = 100; dev->led_delay_off = 100;
ds4_dev->new_output_data = true; dev->new_output_data = true;
} }
} }
@ -950,31 +953,35 @@ void ds4_pad_handler::apply_pad_data(const pad_ensemble& binding)
if (config->led_battery_indicator) if (config->led_battery_indicator)
{ {
// This makes sure that the LED color doesn't update every 1ms. DS4 only reports battery level in 10% increments // This makes sure that the LED color doesn't update every 1ms. DS4 only reports battery level in 10% increments
if (ds4_dev->last_battery_level != ds4_dev->battery_level) if (dev->last_battery_level != dev->battery_level)
{ {
const u32 combined_color = get_battery_color(ds4_dev->battery_level, config->led_battery_indicator_brightness); const u32 combined_color = get_battery_color(dev->battery_level, config->led_battery_indicator_brightness);
config->colorR.set(combined_color >> 8); config->colorR.set(combined_color >> 8);
config->colorG.set(combined_color & 0xff); config->colorG.set(combined_color & 0xff);
config->colorB.set(0); config->colorB.set(0);
ds4_dev->new_output_data = true; dev->new_output_data = true;
ds4_dev->last_battery_level = ds4_dev->battery_level; dev->last_battery_level = dev->battery_level;
} }
} }
ds4_dev->new_output_data |= ds4_dev->large_motor != speed_large || ds4_dev->small_motor != speed_small; dev->new_output_data |= dev->large_motor != speed_large || dev->small_motor != speed_small;
ds4_dev->large_motor = speed_large; dev->large_motor = speed_large;
ds4_dev->small_motor = speed_small; dev->small_motor = speed_small;
if (ds4_dev->new_output_data) const auto now = steady_clock::now();
const auto elapsed = now - dev->last_output;
if (dev->new_output_data || elapsed > min_output_interval)
{ {
if (const int res = send_output_report(ds4_dev); res >= 0) if (const int res = send_output_report(dev); res >= 0)
{ {
ds4_dev->new_output_data = false; dev->new_output_data = false;
dev->last_output = now;
} }
else if (res == -1) else if (res == -1)
{ {
ds4_log.error("apply_pad_data: send_output_report failed! error=%s", hid_error(ds4_dev->hidDevice)); ds4_log.error("apply_pad_data: send_output_report failed! error=%s", hid_error(dev->hidDevice));
} }
} }
} }

View file

@ -383,9 +383,9 @@ dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevic
return DataStatus::NewData; return DataStatus::NewData;
} }
bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_device) const bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dev) const
{ {
if (!dualsense_device || !dualsense_device->hidDevice) if (!dev || !dev->hidDevice)
{ {
dualsense_log.error("get_calibration_data called with null device"); dualsense_log.error("get_calibration_data called with null device");
return false; return false;
@ -393,16 +393,16 @@ bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_devi
std::array<u8, 64> buf{}; std::array<u8, 64> buf{};
if (dualsense_device->bt_controller) if (dev->bt_controller)
{ {
for (int tries = 0; tries < 3; ++tries) for (int tries = 0; tries < 3; ++tries)
{ {
buf = {}; buf = {};
buf[0] = 0x05; buf[0] = 0x05;
if (int res = hid_get_feature_report(dualsense_device->hidDevice, buf.data(), DUALSENSE_CALIBRATION_REPORT_SIZE); res != DUALSENSE_CALIBRATION_REPORT_SIZE || buf[0] != 0x05) if (int res = hid_get_feature_report(dev->hidDevice, buf.data(), DUALSENSE_CALIBRATION_REPORT_SIZE); res != DUALSENSE_CALIBRATION_REPORT_SIZE || buf[0] != 0x05)
{ {
dualsense_log.error("get_calibration_data: hid_get_feature_report 0x05 for bluetooth controller failed! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(dualsense_device->hidDevice)); dualsense_log.error("get_calibration_data: hid_get_feature_report 0x05 for bluetooth controller failed! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(dev->hidDevice));
return false; return false;
} }
@ -427,16 +427,16 @@ bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_devi
{ {
buf[0] = 0x05; buf[0] = 0x05;
if (int res = hid_get_feature_report(dualsense_device->hidDevice, buf.data(), DUALSENSE_CALIBRATION_REPORT_SIZE); res != DUALSENSE_CALIBRATION_REPORT_SIZE || buf[0] != 0x05) if (int res = hid_get_feature_report(dev->hidDevice, buf.data(), DUALSENSE_CALIBRATION_REPORT_SIZE); res != DUALSENSE_CALIBRATION_REPORT_SIZE || buf[0] != 0x05)
{ {
dualsense_log.error("get_calibration_data: hid_get_feature_report 0x05 for wired controller failed! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(dualsense_device->hidDevice)); dualsense_log.error("get_calibration_data: hid_get_feature_report 0x05 for wired controller failed! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(dev->hidDevice));
return false; return false;
} }
} }
dualsense_device->calib_data[CalibIndex::PITCH].bias = read_s16(&buf[1]); dev->calib_data[CalibIndex::PITCH].bias = read_s16(&buf[1]);
dualsense_device->calib_data[CalibIndex::YAW].bias = read_s16(&buf[3]); dev->calib_data[CalibIndex::YAW].bias = read_s16(&buf[3]);
dualsense_device->calib_data[CalibIndex::ROLL].bias = read_s16(&buf[5]); dev->calib_data[CalibIndex::ROLL].bias = read_s16(&buf[5]);
const s16 pitch_plus = read_s16(&buf[7]); const s16 pitch_plus = read_s16(&buf[7]);
const s16 pitch_minus = read_s16(&buf[9]); const s16 pitch_minus = read_s16(&buf[9]);
@ -455,14 +455,14 @@ bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_devi
const s32 gyro_speed_scale = read_s16(&buf[19]) + read_s16(&buf[21]); const s32 gyro_speed_scale = read_s16(&buf[19]) + read_s16(&buf[21]);
dualsense_device->calib_data[CalibIndex::PITCH].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S; dev->calib_data[CalibIndex::PITCH].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
dualsense_device->calib_data[CalibIndex::PITCH].sens_denom = pitch_plus - pitch_minus; dev->calib_data[CalibIndex::PITCH].sens_denom = pitch_plus - pitch_minus;
dualsense_device->calib_data[CalibIndex::YAW].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S; dev->calib_data[CalibIndex::YAW].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
dualsense_device->calib_data[CalibIndex::YAW].sens_denom = yaw_plus - yaw_minus; dev->calib_data[CalibIndex::YAW].sens_denom = yaw_plus - yaw_minus;
dualsense_device->calib_data[CalibIndex::ROLL].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S; dev->calib_data[CalibIndex::ROLL].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
dualsense_device->calib_data[CalibIndex::ROLL].sens_denom = roll_plus - roll_minus; dev->calib_data[CalibIndex::ROLL].sens_denom = roll_plus - roll_minus;
const s16 accel_x_plus = read_s16(&buf[23]); const s16 accel_x_plus = read_s16(&buf[23]);
const s16 accel_x_minus = read_s16(&buf[25]); const s16 accel_x_minus = read_s16(&buf[25]);
@ -475,23 +475,23 @@ bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_devi
const s32 accel_y_range = accel_y_plus - accel_y_minus; const s32 accel_y_range = accel_y_plus - accel_y_minus;
const s32 accel_z_range = accel_z_plus - accel_z_minus; const s32 accel_z_range = accel_z_plus - accel_z_minus;
dualsense_device->calib_data[CalibIndex::X].bias = accel_x_plus - accel_x_range / 2; dev->calib_data[CalibIndex::X].bias = accel_x_plus - accel_x_range / 2;
dualsense_device->calib_data[CalibIndex::X].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G; dev->calib_data[CalibIndex::X].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
dualsense_device->calib_data[CalibIndex::X].sens_denom = accel_x_range; dev->calib_data[CalibIndex::X].sens_denom = accel_x_range;
dualsense_device->calib_data[CalibIndex::Y].bias = accel_y_plus - accel_y_range / 2; dev->calib_data[CalibIndex::Y].bias = accel_y_plus - accel_y_range / 2;
dualsense_device->calib_data[CalibIndex::Y].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G; dev->calib_data[CalibIndex::Y].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
dualsense_device->calib_data[CalibIndex::Y].sens_denom = accel_y_range; dev->calib_data[CalibIndex::Y].sens_denom = accel_y_range;
dualsense_device->calib_data[CalibIndex::Z].bias = accel_z_plus - accel_z_range / 2; dev->calib_data[CalibIndex::Z].bias = accel_z_plus - accel_z_range / 2;
dualsense_device->calib_data[CalibIndex::Z].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G; dev->calib_data[CalibIndex::Z].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
dualsense_device->calib_data[CalibIndex::Z].sens_denom = accel_z_range; dev->calib_data[CalibIndex::Z].sens_denom = accel_z_range;
// Make sure data 'looks' valid, dongle will report invalid calibration data with no controller connected // Make sure data 'looks' valid, dongle will report invalid calibration data with no controller connected
for (size_t i = 0; i < dualsense_device->calib_data.size(); i++) for (size_t i = 0; i < dev->calib_data.size(); i++)
{ {
CalibData& data = dualsense_device->calib_data[i]; CalibData& data = dev->calib_data[i];
if (data.sens_denom == 0) if (data.sens_denom == 0)
{ {
@ -559,23 +559,26 @@ bool dualsense_pad_handler::get_is_touch_pad_motion(const std::shared_ptr<PadDev
PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device) PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{ {
DualSenseDevice* dualsense_dev = static_cast<DualSenseDevice*>(device.get()); DualSenseDevice* dev = static_cast<DualSenseDevice*>(device.get());
if (!dualsense_dev || dualsense_dev->path.empty()) if (!dev || dev->path.empty())
return connection::disconnected; return connection::disconnected;
if (dualsense_dev->hidDevice == nullptr) if (dev->hidDevice == nullptr)
{ {
// try to reconnect // try to reconnect
hid_device* dev = hid_open_path(dualsense_dev->path.c_str()); if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
if (dev)
{ {
if (hid_set_nonblocking(dev, 1) == -1) if (hid_set_nonblocking(hid_dev, 1) == -1)
{ {
dualsense_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dualsense_dev->path, hid_error(dev)); dualsense_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev));
}
dev->hidDevice = hid_dev;
if (!dev->has_calib_data)
{
dev->has_calib_data = get_calibration_data(dev);
} }
dualsense_dev->hidDevice = dev;
if (!dualsense_dev->has_calib_data)
dualsense_dev->has_calib_data = get_calibration_data(dualsense_dev);
} }
else else
{ {
@ -584,10 +587,10 @@ PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::s
} }
} }
if (get_data(dualsense_dev) == DataStatus::ReadError) if (get_data(dev) == DataStatus::ReadError)
{ {
// this also can mean disconnected, either way deal with it on next loop and reconnect // this also can mean disconnected, either way deal with it on next loop and reconnect
dualsense_dev->close(); dev->close();
return connection::no_data; return connection::no_data;
} }
@ -600,14 +603,14 @@ void dualsense_pad_handler::get_extended_info(const pad_ensemble& binding)
const auto& device = binding.device; const auto& device = binding.device;
const auto& pad = binding.pad; const auto& pad = binding.pad;
DualSenseDevice* dualsense_device = static_cast<DualSenseDevice*>(device.get()); DualSenseDevice* dev = static_cast<DualSenseDevice*>(device.get());
if (!dualsense_device || !pad) if (!dev || !pad)
return; return;
pad->m_battery_level = dualsense_device->battery_level; pad->m_battery_level = dev->battery_level;
pad->m_cable_state = dualsense_device->cable_state; pad->m_cable_state = dev->cable_state;
const dualsense_input_report_common& input = dualsense_device->report; const dualsense_input_report_common& input = dev->report;
// these values come already calibrated, all we need to do is convert to ds3 range // these values come already calibrated, all we need to do is convert to ds3 range
@ -638,13 +641,13 @@ void dualsense_pad_handler::get_extended_info(const pad_ensemble& binding)
std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device) std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device)
{ {
std::unordered_map<u64, u16> keyBuffer; std::unordered_map<u64, u16> keyBuffer;
DualSenseDevice* dualsense_dev = static_cast<DualSenseDevice*>(device.get()); DualSenseDevice* dev = static_cast<DualSenseDevice*>(device.get());
if (!dualsense_dev) if (!dev)
return keyBuffer; return keyBuffer;
const dualsense_input_report_common& input = dualsense_dev->report; const dualsense_input_report_common& input = dev->report;
const bool is_simple_mode = dualsense_dev->data_mode == DualSenseDevice::DualSenseDataMode::Simple; const bool is_simple_mode = dev->data_mode == DualSenseDevice::DualSenseDataMode::Simple;
// Left Stick X Axis // Left Stick X Axis
keyBuffer[DualSenseKeyCodes::LSXNeg] = Clamp0To255((127.5f - input.x) * 2.0f); keyBuffer[DualSenseKeyCodes::LSXNeg] = Clamp0To255((127.5f - input.x) * 2.0f);
@ -766,7 +769,7 @@ std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std:
} }
} }
if (dualsense_dev->feature_set == DualSenseDevice::DualSenseFeatureSet::Edge) if (dev->feature_set == DualSenseDevice::DualSenseFeatureSet::Edge)
{ {
keyBuffer[DualSenseKeyCodes::EdgeFnL] = ((data & 0x10) != 0) ? 255 : 0; keyBuffer[DualSenseKeyCodes::EdgeFnL] = ((data & 0x10) != 0) ? 255 : 0;
keyBuffer[DualSenseKeyCodes::EdgeFnR] = ((data & 0x20) != 0) ? 255 : 0; keyBuffer[DualSenseKeyCodes::EdgeFnR] = ((data & 0x20) != 0) ? 255 : 0;
@ -930,11 +933,11 @@ void dualsense_pad_handler::apply_pad_data(const pad_ensemble& binding)
const auto& device = binding.device; const auto& device = binding.device;
const auto& pad = binding.pad; const auto& pad = binding.pad;
DualSenseDevice* dualsense_dev = static_cast<DualSenseDevice*>(device.get()); DualSenseDevice* dev = static_cast<DualSenseDevice*>(device.get());
if (!dualsense_dev || !dualsense_dev->hidDevice || !dualsense_dev->config || !pad) if (!dev || !dev->hidDevice || !dev->config || !pad)
return; return;
cfg_pad* config = dualsense_dev->config; cfg_pad* config = dev->config;
// Attempt to send rumble no matter what // Attempt to send rumble no matter what
const int idx_l = config->switch_vibration_motors ? 1 : 0; const int idx_l = config->switch_vibration_motors ? 1 : 0;
@ -943,9 +946,9 @@ void dualsense_pad_handler::apply_pad_data(const pad_ensemble& binding)
const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0; const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0; const u8 speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
const bool wireless = dualsense_dev->cable_state == 0; const bool wireless = dev->cable_state == 0;
const bool low_battery = dualsense_dev->battery_level <= 1; const bool low_battery = dev->battery_level <= 1;
const bool is_blinking = dualsense_dev->led_delay_on > 0 || dualsense_dev->led_delay_off > 0; const bool is_blinking = dev->led_delay_on > 0 || dev->led_delay_off > 0;
// Blink LED when battery is low // Blink LED when battery is low
if (config->led_low_battery_blink) if (config->led_low_battery_blink)
@ -953,71 +956,75 @@ void dualsense_pad_handler::apply_pad_data(const pad_ensemble& binding)
// we are now wired or have okay battery level -> stop blinking // we are now wired or have okay battery level -> stop blinking
if (is_blinking && !(wireless && low_battery)) if (is_blinking && !(wireless && low_battery))
{ {
dualsense_dev->lightbar_on = true; dev->lightbar_on = true;
dualsense_dev->led_delay_on = 0; dev->led_delay_on = 0;
dualsense_dev->led_delay_off = 0; dev->led_delay_off = 0;
dualsense_dev->update_lightbar = true; dev->update_lightbar = true;
} }
// we are now wireless and low on battery -> blink // we are now wireless and low on battery -> blink
else if (!is_blinking && wireless && low_battery) else if (!is_blinking && wireless && low_battery)
{ {
dualsense_dev->led_delay_on = 100; dev->led_delay_on = 100;
dualsense_dev->led_delay_off = 100; dev->led_delay_off = 100;
dualsense_dev->update_lightbar = true; dev->update_lightbar = true;
} }
// Turn lightbar on and off in an interval. I wanted to do an automatic pulse, but I haven't found out how to do that yet. // Turn lightbar on and off in an interval. I wanted to do an automatic pulse, but I haven't found out how to do that yet.
if (dualsense_dev->led_delay_on > 0) if (dev->led_delay_on > 0)
{ {
if (const steady_clock::time_point now = steady_clock::now(); (now - dualsense_dev->last_lightbar_time) > 500ms) if (const steady_clock::time_point now = steady_clock::now(); (now - dev->last_lightbar_time) > 500ms)
{ {
dualsense_dev->lightbar_on = !dualsense_dev->lightbar_on; dev->lightbar_on = !dev->lightbar_on;
dualsense_dev->last_lightbar_time = now; dev->last_lightbar_time = now;
dualsense_dev->update_lightbar = true; dev->update_lightbar = true;
} }
} }
} }
else if (!dualsense_dev->lightbar_on) else if (!dev->lightbar_on)
{ {
dualsense_dev->lightbar_on = true; dev->lightbar_on = true;
dualsense_dev->update_lightbar = true; dev->update_lightbar = true;
} }
// Use LEDs to indicate battery level // Use LEDs to indicate battery level
if (config->led_battery_indicator) if (config->led_battery_indicator)
{ {
// This makes sure that the LED color doesn't update every 1ms. DS4 only reports battery level in 10% increments // This makes sure that the LED color doesn't update every 1ms. DS4 only reports battery level in 10% increments
if (dualsense_dev->last_battery_level != dualsense_dev->battery_level) if (dev->last_battery_level != dev->battery_level)
{ {
const u32 combined_color = get_battery_color(dualsense_dev->battery_level, config->led_battery_indicator_brightness); const u32 combined_color = get_battery_color(dev->battery_level, config->led_battery_indicator_brightness);
config->colorR.set(combined_color >> 8); config->colorR.set(combined_color >> 8);
config->colorG.set(combined_color & 0xff); config->colorG.set(combined_color & 0xff);
config->colorB.set(0); config->colorB.set(0);
dualsense_dev->update_lightbar = true; dev->update_lightbar = true;
dualsense_dev->last_battery_level = dualsense_dev->battery_level; dev->last_battery_level = dev->battery_level;
} }
} }
if (dualsense_dev->enable_player_leds != config->player_led_enabled.get()) if (dev->enable_player_leds != config->player_led_enabled.get())
{ {
dualsense_dev->enable_player_leds = config->player_led_enabled.get(); dev->enable_player_leds = config->player_led_enabled.get();
dualsense_dev->update_player_leds = true; dev->update_player_leds = true;
} }
dualsense_dev->new_output_data |= dualsense_dev->release_leds || dualsense_dev->update_player_leds || dualsense_dev->update_lightbar || dualsense_dev->large_motor != speed_large || dualsense_dev->small_motor != speed_small; dev->new_output_data |= dev->release_leds || dev->update_player_leds || dev->update_lightbar || dev->large_motor != speed_large || dev->small_motor != speed_small;
dualsense_dev->large_motor = speed_large; dev->large_motor = speed_large;
dualsense_dev->small_motor = speed_small; dev->small_motor = speed_small;
if (dualsense_dev->new_output_data) const auto now = steady_clock::now();
const auto elapsed = now - dev->last_output;
if (dev->new_output_data || elapsed > min_output_interval)
{ {
if (const int res = send_output_report(dualsense_dev); res >= 0) if (const int res = send_output_report(dev); res >= 0)
{ {
dualsense_dev->new_output_data = false; dev->new_output_data = false;
dev->last_output = now;
} }
else if (res == -1) else if (res == -1)
{ {
dualsense_log.error("apply_pad_data: send_output_report failed! error=%s", hid_error(dualsense_dev->hidDevice)); dualsense_log.error("apply_pad_data: send_output_report failed! error=%s", hid_error(dev->hidDevice));
} }
} }
} }

View file

@ -243,7 +243,7 @@ public:
void init_config(cfg_pad* cfg) override; void init_config(cfg_pad* cfg) override;
private: private:
bool get_calibration_data(DualSenseDevice* dualsense_device) const; bool get_calibration_data(DualSenseDevice* dev) const;
DataStatus get_data(DualSenseDevice* device) override; DataStatus get_data(DualSenseDevice* device) override;
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial) override; void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial) override;

View file

@ -587,15 +587,18 @@ void evdev_joystick_handler::SetRumble(EvdevDevice* device, u8 large, u8 small)
if (fd < 0) if (fd < 0)
return; return;
if (large == device->large_motor && small == device->small_motor) device->new_output_data = large != device->large_motor || small != device->small_motor;
return;
const auto now = steady_clock::now();
const auto elapsed = now - device->last_output;
// XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. // XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse.
// So I'll use 20ms to be on the safe side. No lag was noticable. // So I'll use 20ms to be on the safe side. No lag was noticable.
if (clock() - device->last_vibration < 20) if ((!device->new_output_data || elapsed <= 20ms) && elapsed <= min_output_interval)
return; return;
device->last_vibration = clock(); device->new_output_data = false;
device->last_output = now;
// delete the previous effect (which also stops it) // delete the previous effect (which also stops it)
if (device->effect_id != -1) if (device->effect_id != -1)

View file

@ -396,7 +396,6 @@ class evdev_joystick_handler final : public PadHandlerBase
int effect_id = -1; int effect_id = -1;
bool has_rumble = false; bool has_rumble = false;
bool has_motion = false; bool has_motion = false;
clock_t last_vibration = 0;
}; };
public: public:

View file

@ -34,7 +34,6 @@ public:
hid_device* hidDevice{nullptr}; hid_device* hidDevice{nullptr};
std::string path; std::string path;
bool new_output_data{true};
bool enable_player_leds{false}; bool enable_player_leds{false};
u8 led_delay_on{0}; u8 led_delay_on{0};
u8 led_delay_off{0}; u8 led_delay_off{0};

View file

@ -169,20 +169,20 @@ std::array<std::set<u32>, PadHandlerBase::button::button_count> mm_joystick_hand
{ {
std::array<std::set<u32>, button::button_count> mapping{}; std::array<std::set<u32>, button::button_count> mapping{};
MMJOYDevice* joy_device = static_cast<MMJOYDevice*>(device.get()); MMJOYDevice* dev = static_cast<MMJOYDevice*>(device.get());
if (!joy_device || !cfg) if (!dev || !cfg)
return mapping; return mapping;
joy_device->trigger_code_left = find_keys<u64>(cfg->l2); dev->trigger_code_left = find_keys<u64>(cfg->l2);
joy_device->trigger_code_right = find_keys<u64>(cfg->r2); dev->trigger_code_right = find_keys<u64>(cfg->r2);
joy_device->axis_code_left[0] = find_keys<u64>(cfg->ls_left); dev->axis_code_left[0] = find_keys<u64>(cfg->ls_left);
joy_device->axis_code_left[1] = find_keys<u64>(cfg->ls_right); dev->axis_code_left[1] = find_keys<u64>(cfg->ls_right);
joy_device->axis_code_left[2] = find_keys<u64>(cfg->ls_down); dev->axis_code_left[2] = find_keys<u64>(cfg->ls_down);
joy_device->axis_code_left[3] = find_keys<u64>(cfg->ls_up); dev->axis_code_left[3] = find_keys<u64>(cfg->ls_up);
joy_device->axis_code_right[0] = find_keys<u64>(cfg->rs_left); dev->axis_code_right[0] = find_keys<u64>(cfg->rs_left);
joy_device->axis_code_right[1] = find_keys<u64>(cfg->rs_right); dev->axis_code_right[1] = find_keys<u64>(cfg->rs_right);
joy_device->axis_code_right[2] = find_keys<u64>(cfg->rs_down); dev->axis_code_right[2] = find_keys<u64>(cfg->rs_down);
joy_device->axis_code_right[3] = find_keys<u64>(cfg->rs_up); dev->axis_code_right[3] = find_keys<u64>(cfg->rs_up);
mapping[button::up] = find_keys<u32>(cfg->up); mapping[button::up] = find_keys<u32>(cfg->up);
mapping[button::down] = find_keys<u32>(cfg->down); mapping[button::down] = find_keys<u32>(cfg->down);
@ -193,22 +193,22 @@ std::array<std::set<u32>, PadHandlerBase::button::button_count> mm_joystick_hand
mapping[button::circle] = find_keys<u32>(cfg->circle); mapping[button::circle] = find_keys<u32>(cfg->circle);
mapping[button::triangle] = find_keys<u32>(cfg->triangle); mapping[button::triangle] = find_keys<u32>(cfg->triangle);
mapping[button::l1] = find_keys<u32>(cfg->l1); mapping[button::l1] = find_keys<u32>(cfg->l1);
mapping[button::l2] = narrow_set(joy_device->trigger_code_left); mapping[button::l2] = narrow_set(dev->trigger_code_left);
mapping[button::l3] = find_keys<u32>(cfg->l3); mapping[button::l3] = find_keys<u32>(cfg->l3);
mapping[button::r1] = find_keys<u32>(cfg->r1); mapping[button::r1] = find_keys<u32>(cfg->r1);
mapping[button::r2] = narrow_set(joy_device->trigger_code_right); mapping[button::r2] = narrow_set(dev->trigger_code_right);
mapping[button::r3] = find_keys<u32>(cfg->r3); mapping[button::r3] = find_keys<u32>(cfg->r3);
mapping[button::start] = find_keys<u32>(cfg->start); mapping[button::start] = find_keys<u32>(cfg->start);
mapping[button::select] = find_keys<u32>(cfg->select); mapping[button::select] = find_keys<u32>(cfg->select);
mapping[button::ps] = find_keys<u32>(cfg->ps); mapping[button::ps] = find_keys<u32>(cfg->ps);
mapping[button::ls_left] = narrow_set(joy_device->axis_code_left[0]); mapping[button::ls_left] = narrow_set(dev->axis_code_left[0]);
mapping[button::ls_right] = narrow_set(joy_device->axis_code_left[1]); mapping[button::ls_right] = narrow_set(dev->axis_code_left[1]);
mapping[button::ls_down] = narrow_set(joy_device->axis_code_left[2]); mapping[button::ls_down] = narrow_set(dev->axis_code_left[2]);
mapping[button::ls_up] = narrow_set(joy_device->axis_code_left[3]); mapping[button::ls_up] = narrow_set(dev->axis_code_left[3]);
mapping[button::rs_left] = narrow_set(joy_device->axis_code_right[0]); mapping[button::rs_left] = narrow_set(dev->axis_code_right[0]);
mapping[button::rs_right] = narrow_set(joy_device->axis_code_right[1]); mapping[button::rs_right] = narrow_set(dev->axis_code_right[1]);
mapping[button::rs_down] = narrow_set(joy_device->axis_code_right[2]); mapping[button::rs_down] = narrow_set(dev->axis_code_right[2]);
mapping[button::rs_up] = narrow_set(joy_device->axis_code_right[3]); mapping[button::rs_up] = narrow_set(dev->axis_code_right[3]);
mapping[button::skateboard_ir_nose] = find_keys<u32>(cfg->ir_nose); mapping[button::skateboard_ir_nose] = find_keys<u32>(cfg->ir_nose);
mapping[button::skateboard_ir_tail] = find_keys<u32>(cfg->ir_tail); mapping[button::skateboard_ir_tail] = find_keys<u32>(cfg->ir_tail);

View file

@ -114,9 +114,6 @@ private:
bool m_initialized = false; bool m_initialized = false;
}; };
constexpr u32 rumble_duration_ms = 500; // Some high number to keep rumble updates at a minimum.
constexpr u32 rumble_refresh_ms = rumble_duration_ms - 100; // We need to keep updating the rumble. Choose a refresh timeout that is unlikely to run into missed rumble updates.
sdl_pad_handler::sdl_pad_handler() : PadHandlerBase(pad_handler::sdl) sdl_pad_handler::sdl_pad_handler() : PadHandlerBase(pad_handler::sdl)
{ {
button_list = button_list =
@ -792,21 +789,21 @@ void sdl_pad_handler::apply_pad_data(const pad_ensemble& binding)
const u8 speed_large = cfg->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0; const u8 speed_large = cfg->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = cfg->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0; const u8 speed_small = cfg->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
dev->has_new_rumble_data |= dev->large_motor != speed_large || dev->small_motor != speed_small; dev->new_output_data |= dev->large_motor != speed_large || dev->small_motor != speed_small;
dev->large_motor = speed_large; dev->large_motor = speed_large;
dev->small_motor = speed_small; dev->small_motor = speed_small;
const steady_clock::time_point now = steady_clock::now(); const auto now = steady_clock::now();
const s64 elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - dev->last_vibration).count(); const auto elapsed = now - dev->last_output;
// XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. So I'll use 20ms to be on the safe side. No lag was noticable. // XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. So I'll use 20ms to be on the safe side. No lag was noticable.
if ((dev->has_new_rumble_data && elapsed_ms > 20) || (elapsed_ms > rumble_refresh_ms)) if ((dev->new_output_data && elapsed > 20ms) || elapsed > min_output_interval)
{ {
set_rumble(dev, speed_large, speed_small); set_rumble(dev, speed_large, speed_small);
dev->has_new_rumble_data = false; dev->new_output_data = false;
dev->last_vibration = steady_clock::now(); dev->last_output = now;
} }
} }
@ -880,6 +877,8 @@ void sdl_pad_handler::set_rumble(SDLDevice* dev, u8 speed_large, u8 speed_small)
{ {
if (!dev || !dev->sdl.game_controller) return; if (!dev || !dev->sdl.game_controller) return;
constexpr u32 rumble_duration_ms = static_cast<u32>((min_output_interval + 100ms).count()); // Some number higher than the min_output_interval.
if (dev->sdl.has_rumble) if (dev->sdl.has_rumble)
{ {
if (SDL_GameControllerRumble(dev->sdl.game_controller, speed_large * 257, speed_small * 257, rumble_duration_ms) != 0) if (SDL_GameControllerRumble(dev->sdl.game_controller, speed_large * 257, speed_small * 257, rumble_duration_ms) != 0)

View file

@ -64,9 +64,6 @@ public:
bool led_is_on = true; bool led_is_on = true;
bool led_is_blinking = false; bool led_is_blinking = false;
steady_clock::time_point led_timestamp{}; steady_clock::time_point led_timestamp{};
bool has_new_rumble_data = true;
steady_clock::time_point last_vibration{};
}; };
class sdl_pad_handler : public PadHandlerBase class sdl_pad_handler : public PadHandlerBase

View file

@ -228,39 +228,38 @@ skateboard_pad_handler::DataStatus skateboard_pad_handler::get_data(skateboard_d
PadHandlerBase::connection skateboard_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device) PadHandlerBase::connection skateboard_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
{ {
skateboard_device* skateboard_dev = static_cast<skateboard_device*>(device.get()); skateboard_device* dev = static_cast<skateboard_device*>(device.get());
if (!skateboard_dev || skateboard_dev->path.empty()) if (!dev || dev->path.empty())
return connection::disconnected; return connection::disconnected;
if (skateboard_dev->hidDevice == nullptr) if (dev->hidDevice == nullptr)
{ {
// try to reconnect // try to reconnect
hid_device* dev = hid_open_path(skateboard_dev->path.c_str()); if (hid_device* hid_dev = hid_open_path(dev->path.c_str()))
if (dev)
{ {
if (hid_set_nonblocking(dev, 1) == -1) if (hid_set_nonblocking(hid_dev, 1) == -1)
{ {
skateboard_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", skateboard_dev->path, hid_error(dev)); skateboard_log.error("Reconnecting Device %s: hid_set_nonblocking failed with error %s", dev->path, hid_error(hid_dev));
} }
skateboard_dev->hidDevice = dev; dev->hidDevice = hid_dev;
} }
else else
{ {
// nope, not there // nope, not there
skateboard_log.error("Device %s: disconnected", skateboard_dev->path); skateboard_log.error("Device %s: disconnected", dev->path);
return connection::disconnected; return connection::disconnected;
} }
} }
if (get_data(skateboard_dev) == DataStatus::ReadError) if (get_data(dev) == DataStatus::ReadError)
{ {
// this also can mean disconnected, either way deal with it on next loop and reconnect // this also can mean disconnected, either way deal with it on next loop and reconnect
skateboard_dev->close(); dev->close();
return connection::no_data; return connection::no_data;
} }
if (!skateboard_dev->skateboard_is_on) if (!dev->skateboard_is_on)
{ {
// This means that the dongle is still connected, but the skateboard is turned off. // This means that the dongle is still connected, but the skateboard is turned off.
// There is no need to reconnect the hid device again, we just have to check the input report for proper data. // There is no need to reconnect the hid device again, we just have to check the input report for proper data.
@ -356,17 +355,22 @@ void skateboard_pad_handler::apply_pad_data(const pad_ensemble& binding)
dev->new_output_data = false; dev->new_output_data = false;
if (dev->new_output_data) // Disabled until needed
{ //const auto now = steady_clock::now();
if (const int res = send_output_report(dev); res >= 0) //const auto elapsed = now - dev->last_output;
{
dev->new_output_data = false; //if (dev->new_output_data || elapsed > min_output_interval)
} //{
else if (res == -1) // if (const int res = send_output_report(dev); res >= 0)
{ // {
skateboard_log.error("apply_pad_data: send_output_report failed! error=%s", hid_error(dev->hidDevice)); // dev->new_output_data = false;
} // dev->last_output = now;
} // }
// else if (res == -1)
// {
// skateboard_log.error("apply_pad_data: send_output_report failed! error=%s", hid_error(dev->hidDevice));
// }
//}
} }
void skateboard_pad_handler::SetPadData(const std::string& padId, u8 player_id, u8 /*large_motor*/, u8 /*small_motor*/, s32 /*r*/, s32 /*g*/, s32 /*b*/, bool /*player_led*/, bool /*battery_led*/, u32 /*battery_led_brightness*/) void skateboard_pad_handler::SetPadData(const std::string& padId, u8 player_id, u8 /*large_motor*/, u8 /*small_motor*/, s32 /*r*/, s32 /*g*/, s32 /*b*/, bool /*player_led*/, bool /*battery_led*/, u32 /*battery_led_brightness*/)

View file

@ -142,10 +142,11 @@ void xinput_pad_handler::SetPadData(const std::string& padId, u8 /*player_id*/,
// 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.
XINPUT_VIBRATION vibrate; XINPUT_VIBRATION vibrate
{
vibrate.wLeftMotorSpeed = large_motor * 257; // between 0 to 65535 .wLeftMotorSpeed = static_cast<u16>(large_motor * 257), // between 0 to 65535
vibrate.wRightMotorSpeed = small_motor * 257; // between 0 to 65535 .wRightMotorSpeed = static_cast<u16>(small_motor * 257) // between 0 to 65535
};
xinputSetState(static_cast<u32>(device_number), &vibrate); xinputSetState(static_cast<u32>(device_number), &vibrate);
} }
@ -449,10 +450,10 @@ std::shared_ptr<PadDevice> xinput_pad_handler::get_device(const std::string& dev
if (device_number < 0) if (device_number < 0)
return nullptr; return nullptr;
std::shared_ptr<XInputDevice> x_device = std::make_shared<XInputDevice>(); std::shared_ptr<XInputDevice> dev = std::make_shared<XInputDevice>();
x_device->deviceNumber = static_cast<u32>(device_number); dev->deviceNumber = static_cast<u32>(device_number);
return x_device; return dev;
} }
bool xinput_pad_handler::get_is_left_trigger(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode) bool xinput_pad_handler::get_is_left_trigger(const std::shared_ptr<PadDevice>& /*device*/, u64 keyCode)
@ -568,22 +569,27 @@ void xinput_pad_handler::apply_pad_data(const pad_ensemble& binding)
const u8 speed_large = cfg->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0; const u8 speed_large = cfg->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = cfg->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0; const u8 speed_small = cfg->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
dev->newVibrateData |= dev->large_motor != speed_large || dev->small_motor != speed_small; dev->new_output_data |= dev->large_motor != speed_large || dev->small_motor != speed_small;
dev->large_motor = speed_large; dev->large_motor = speed_large;
dev->small_motor = speed_small; dev->small_motor = speed_small;
const auto now = steady_clock::now();
const auto elapsed = now - dev->last_output;
// XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. So I'll use 20ms to be on the safe side. No lag was noticable. // XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. So I'll use 20ms to be on the safe side. No lag was noticable.
if (dev->newVibrateData && steady_clock::now() - dev->last_vibration > 20ms) if ((dev->new_output_data && elapsed > 20ms) || elapsed > min_output_interval)
{ {
XINPUT_VIBRATION vibrate; XINPUT_VIBRATION vibrate
vibrate.wLeftMotorSpeed = speed_large * 257; // between 0 to 65535 {
vibrate.wRightMotorSpeed = speed_small * 257; // between 0 to 65535 .wLeftMotorSpeed = static_cast<u16>(speed_large * 257), // between 0 to 65535
.wRightMotorSpeed = static_cast<u16>(speed_small * 257) // between 0 to 65535
};
if (xinputSetState(padnum, &vibrate) == ERROR_SUCCESS) if (xinputSetState(padnum, &vibrate) == ERROR_SUCCESS)
{ {
dev->newVibrateData = false; dev->new_output_data = false;
dev->last_vibration = steady_clock::now(); dev->last_output = now;
} }
} }
} }

View file

@ -98,8 +98,6 @@ class xinput_pad_handler final : public PadHandlerBase
struct XInputDevice : public PadDevice struct XInputDevice : public PadDevice
{ {
u32 deviceNumber{ 0 }; u32 deviceNumber{ 0 };
bool newVibrateData{ true };
steady_clock::time_point last_vibration;
bool is_scp_device{ false }; bool is_scp_device{ false };
DWORD state{ ERROR_NOT_CONNECTED }; // holds internal controller state change DWORD state{ ERROR_NOT_CONNECTED }; // holds internal controller state change
SCP_EXTN state_scp{}; SCP_EXTN state_scp{};