From c3f54ff2329d79bdbb273678b5123cf0b1cd090c Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 19:43:16 -0500 Subject: core/hid: Add emulated controllers --- src/core/hid/emulated_controller.cpp | 745 +++++++++++++++++++++++++++++++++++ 1 file changed, 745 insertions(+) create mode 100644 src/core/hid/emulated_controller.cpp (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp new file mode 100644 index 000000000..4eb5d99bc --- /dev/null +++ b/src/core/hid/emulated_controller.cpp @@ -0,0 +1,745 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include + +#include "core/hid/emulated_controller.h" +#include "core/hid/input_converter.h" + +namespace Core::HID { +constexpr s32 HID_JOYSTICK_MAX = 0x7fff; +constexpr s32 HID_TRIGGER_MAX = 0x7fff; + +EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {} + +EmulatedController::~EmulatedController() = default; + +NpadType EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { + switch (type) { + case Settings::ControllerType::ProController: + return NpadType::ProController; + case Settings::ControllerType::DualJoyconDetached: + return NpadType::JoyconDual; + case Settings::ControllerType::LeftJoycon: + return NpadType::JoyconLeft; + case Settings::ControllerType::RightJoycon: + return NpadType::JoyconRight; + case Settings::ControllerType::Handheld: + return NpadType::Handheld; + case Settings::ControllerType::GameCube: + return NpadType::GameCube; + default: + return NpadType::ProController; + } +} + +Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type) { + switch (type) { + case NpadType::ProController: + return Settings::ControllerType::ProController; + case NpadType::JoyconDual: + return Settings::ControllerType::DualJoyconDetached; + case NpadType::JoyconLeft: + return Settings::ControllerType::LeftJoycon; + case NpadType::JoyconRight: + return Settings::ControllerType::RightJoycon; + case NpadType::Handheld: + return Settings::ControllerType::Handheld; + case NpadType::GameCube: + return Settings::ControllerType::GameCube; + default: + return Settings::ControllerType::ProController; + } +} + +void EmulatedController::ReloadFromSettings() { + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + + for (std::size_t index = 0; index < player.buttons.size(); ++index) { + button_params[index] = Common::ParamPackage(player.buttons[index]); + } + for (std::size_t index = 0; index < player.analogs.size(); ++index) { + stick_params[index] = Common::ParamPackage(player.analogs[index]); + } + for (std::size_t index = 0; index < player.motions.size(); ++index) { + motion_params[index] = Common::ParamPackage(player.motions[index]); + } + ReloadInput(); +} + +void EmulatedController::ReloadInput() { + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + const auto left_side = button_params[Settings::NativeButton::ZL]; + const auto right_side = button_params[Settings::NativeButton::ZR]; + + std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, + button_params.begin() + Settings::NativeButton::BUTTON_NS_END, + button_devices.begin(), Input::CreateDevice); + std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, + stick_params.begin() + Settings::NativeAnalog::STICK_HID_END, + stick_devices.begin(), Input::CreateDevice); + std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, + motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, + motion_devices.begin(), Input::CreateDevice); + + trigger_devices[0] = + Input::CreateDevice(button_params[Settings::NativeButton::ZL]); + trigger_devices[1] = + Input::CreateDevice(button_params[Settings::NativeButton::ZR]); + + controller.colors_state.left = { + .body = player.body_color_left, + .button = player.button_color_left, + }; + + controller.colors_state.right = { + .body = player.body_color_right, + .button = player.button_color_right, + }; + + controller.colors_state.fullkey = controller.colors_state.left; + + battery_devices[0] = Input::CreateDevice(left_side); + battery_devices[1] = Input::CreateDevice(right_side); + + for (std::size_t index = 0; index < button_devices.size(); ++index) { + if (!button_devices[index]) { + continue; + } + Input::InputCallback button_callback{ + [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + button_devices[index]->SetCallback(button_callback); + } + + for (std::size_t index = 0; index < stick_devices.size(); ++index) { + if (!stick_devices[index]) { + continue; + } + Input::InputCallback stick_callback{ + [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + stick_devices[index]->SetCallback(stick_callback); + } + + for (std::size_t index = 0; index < trigger_devices.size(); ++index) { + if (!trigger_devices[index]) { + continue; + } + Input::InputCallback trigger_callback{ + [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }}; + trigger_devices[index]->SetCallback(trigger_callback); + } + + for (std::size_t index = 0; index < battery_devices.size(); ++index) { + if (!battery_devices[index]) { + continue; + } + Input::InputCallback battery_callback{ + [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }}; + battery_devices[index]->SetCallback(battery_callback); + } + + for (std::size_t index = 0; index < motion_devices.size(); ++index) { + if (!motion_devices[index]) { + continue; + } + Input::InputCallback motion_callback{ + [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; + motion_devices[index]->SetCallback(motion_callback); + } + + SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + + if (player.connected) { + Connect(); + } else { + Disconnect(); + } +} + +void EmulatedController::UnloadInput() { + for (auto& button : button_devices) { + button.reset(); + } + for (auto& stick : stick_devices) { + stick.reset(); + } + for (auto& motion : motion_devices) { + motion.reset(); + } + for (auto& trigger : trigger_devices) { + trigger.reset(); + } + for (auto& battery : battery_devices) { + battery.reset(); + } +} + +void EmulatedController::EnableConfiguration() { + is_configuring = true; + SaveCurrentConfig(); +} + +void EmulatedController::DisableConfiguration() { + is_configuring = false; +} + +bool EmulatedController::IsConfiguring() const { + return is_configuring; +} + +void EmulatedController::SaveCurrentConfig() { + if (!is_configuring) { + return; + } + + const auto player_index = NpadIdTypeToIndex(npad_id_type); + auto& player = Settings::values.players.GetValue()[player_index]; + + for (std::size_t index = 0; index < player.buttons.size(); ++index) { + player.buttons[index] = button_params[index].Serialize(); + } + for (std::size_t index = 0; index < player.analogs.size(); ++index) { + player.analogs[index] = stick_params[index].Serialize(); + } + for (std::size_t index = 0; index < player.motions.size(); ++index) { + player.motions[index] = motion_params[index].Serialize(); + } +} + +void EmulatedController::RestoreConfig() { + if (!is_configuring) { + return; + } + ReloadFromSettings(); +} + +std::vector EmulatedController::GetMappedDevices() const { + std::vector devices; + for (const auto& param : button_params) { + if (!param.Has("engine")) { + continue; + } + const auto devices_it = std::find_if( + devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { + return param.Get("engine", "") == param_.Get("engine", "") && + param.Get("guid", "") == param_.Get("guid", "") && + param.Get("port", "") == param_.Get("port", ""); + }); + if (devices_it != devices.end()) { + continue; + } + Common::ParamPackage device{}; + device.Set("engine", param.Get("engine", "")); + device.Set("guid", param.Get("guid", "")); + device.Set("port", param.Get("port", "")); + devices.push_back(device); + } + + for (const auto& param : stick_params) { + if (!param.Has("engine")) { + continue; + } + if (param.Get("engine", "") == "analog_from_button") { + continue; + } + const auto devices_it = std::find_if( + devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { + return param.Get("engine", "") == param_.Get("engine", "") && + param.Get("guid", "") == param_.Get("guid", "") && + param.Get("port", "") == param_.Get("port", ""); + }); + if (devices_it != devices.end()) { + continue; + } + Common::ParamPackage device{}; + device.Set("engine", param.Get("engine", "")); + device.Set("guid", param.Get("guid", "")); + device.Set("port", param.Get("port", "")); + devices.push_back(device); + } + return devices; +} + +Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const { + if (index >= button_params.size()) { + return {}; + } + return button_params[index]; +} + +Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const { + if (index >= stick_params.size()) { + return {}; + } + return stick_params[index]; +} + +Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const { + if (index >= motion_params.size()) { + return {}; + } + return motion_params[index]; +} + +void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) { + if (index >= button_params.size()) { + return; + } + button_params[index] = param; + ReloadInput(); +} + +void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) { + if (index >= stick_params.size()) { + return; + } + stick_params[index] = param; + ReloadInput(); +} + +void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) { + if (index >= motion_params.size()) { + return; + } + motion_params[index] = param; + ReloadInput(); +} + +void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.button_values.size()) { + return; + } + std::lock_guard lock{mutex}; + bool value_changed = false; + const auto new_status = TransformToButton(callback); + auto& current_status = controller.button_values[index]; + current_status.toggle = new_status.toggle; + + // Update button status with current + if (!current_status.toggle) { + current_status.locked = false; + if (current_status.value != new_status.value) { + current_status.value = new_status.value; + value_changed = true; + } + } else { + // Toggle button and lock status + if (new_status.value && !current_status.locked) { + current_status.locked = true; + current_status.value = !current_status.value; + value_changed = true; + } + + // Unlock button ready for next press + if (!new_status.value && current_status.locked) { + current_status.locked = false; + } + } + + if (!value_changed) { + return; + } + + if (is_configuring) { + controller.npad_button_state.raw = NpadButton::None; + controller.debug_pad_button_state.raw = 0; + TriggerOnChange(ControllerTriggerType::Button); + return; + } + + switch (index) { + case Settings::NativeButton::A: + controller.npad_button_state.a.Assign(current_status.value); + controller.debug_pad_button_state.a.Assign(current_status.value); + break; + case Settings::NativeButton::B: + controller.npad_button_state.b.Assign(current_status.value); + controller.debug_pad_button_state.b.Assign(current_status.value); + break; + case Settings::NativeButton::X: + controller.npad_button_state.x.Assign(current_status.value); + controller.debug_pad_button_state.x.Assign(current_status.value); + break; + case Settings::NativeButton::Y: + controller.npad_button_state.y.Assign(current_status.value); + controller.debug_pad_button_state.y.Assign(current_status.value); + break; + case Settings::NativeButton::LStick: + controller.npad_button_state.stick_l.Assign(current_status.value); + break; + case Settings::NativeButton::RStick: + controller.npad_button_state.stick_r.Assign(current_status.value); + break; + case Settings::NativeButton::L: + controller.npad_button_state.l.Assign(current_status.value); + controller.debug_pad_button_state.l.Assign(current_status.value); + break; + case Settings::NativeButton::R: + controller.npad_button_state.r.Assign(current_status.value); + controller.debug_pad_button_state.r.Assign(current_status.value); + break; + case Settings::NativeButton::ZL: + controller.npad_button_state.zl.Assign(current_status.value); + controller.debug_pad_button_state.zl.Assign(current_status.value); + break; + case Settings::NativeButton::ZR: + controller.npad_button_state.zr.Assign(current_status.value); + controller.debug_pad_button_state.zr.Assign(current_status.value); + break; + case Settings::NativeButton::Plus: + controller.npad_button_state.plus.Assign(current_status.value); + controller.debug_pad_button_state.plus.Assign(current_status.value); + break; + case Settings::NativeButton::Minus: + controller.npad_button_state.minus.Assign(current_status.value); + controller.debug_pad_button_state.minus.Assign(current_status.value); + break; + case Settings::NativeButton::DLeft: + controller.npad_button_state.left.Assign(current_status.value); + controller.debug_pad_button_state.d_left.Assign(current_status.value); + break; + case Settings::NativeButton::DUp: + controller.npad_button_state.up.Assign(current_status.value); + controller.debug_pad_button_state.d_up.Assign(current_status.value); + break; + case Settings::NativeButton::DRight: + controller.npad_button_state.right.Assign(current_status.value); + controller.debug_pad_button_state.d_right.Assign(current_status.value); + break; + case Settings::NativeButton::DDown: + controller.npad_button_state.down.Assign(current_status.value); + controller.debug_pad_button_state.d_down.Assign(current_status.value); + break; + case Settings::NativeButton::SL: + controller.npad_button_state.left_sl.Assign(current_status.value); + controller.npad_button_state.right_sl.Assign(current_status.value); + break; + case Settings::NativeButton::SR: + controller.npad_button_state.left_sr.Assign(current_status.value); + controller.npad_button_state.right_sr.Assign(current_status.value); + break; + case Settings::NativeButton::Home: + case Settings::NativeButton::Screenshot: + break; + } + TriggerOnChange(ControllerTriggerType::Button); +} + +void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.stick_values.size()) { + return; + } + std::lock_guard lock{mutex}; + controller.stick_values[index] = TransformToStick(callback); + + if (is_configuring) { + controller.analog_stick_state.left = {}; + controller.analog_stick_state.right = {}; + TriggerOnChange(ControllerTriggerType::Stick); + return; + } + + const AnalogStickState stick{ + .x = static_cast(controller.stick_values[index].x.value * HID_JOYSTICK_MAX), + .y = static_cast(controller.stick_values[index].y.value * HID_JOYSTICK_MAX), + }; + + switch (index) { + case Settings::NativeAnalog::LStick: + controller.analog_stick_state.left = stick; + controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left); + controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up); + controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right); + controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down); + break; + case Settings::NativeAnalog::RStick: + controller.analog_stick_state.right = stick; + controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left); + controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up); + controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right); + controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); + break; + } + + TriggerOnChange(ControllerTriggerType::Stick); +} + +void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.trigger_values.size()) { + return; + } + std::lock_guard lock{mutex}; + controller.trigger_values[index] = TransformToTrigger(callback); + + if (is_configuring) { + controller.gc_trigger_state.left = 0; + controller.gc_trigger_state.right = 0; + TriggerOnChange(ControllerTriggerType::Trigger); + return; + } + + const auto trigger = controller.trigger_values[index]; + + switch (index) { + case Settings::NativeTrigger::LTrigger: + controller.gc_trigger_state.left = static_cast(trigger.analog.value * HID_TRIGGER_MAX); + controller.npad_button_state.zl.Assign(trigger.pressed); + break; + case Settings::NativeTrigger::RTrigger: + controller.gc_trigger_state.right = + static_cast(trigger.analog.value * HID_TRIGGER_MAX); + controller.npad_button_state.zr.Assign(trigger.pressed); + break; + } + + TriggerOnChange(ControllerTriggerType::Trigger); +} + +void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.motion_values.size()) { + return; + } + std::lock_guard lock{mutex}; + auto& raw_status = controller.motion_values[index].raw_status; + auto& emulated = controller.motion_values[index].emulated; + + raw_status = TransformToMotion(callback); + emulated.SetAcceleration(Common::Vec3f{ + raw_status.accel.x.value, + raw_status.accel.y.value, + raw_status.accel.z.value, + }); + emulated.SetGyroscope(Common::Vec3f{ + raw_status.gyro.x.value, + raw_status.gyro.y.value, + raw_status.gyro.z.value, + }); + emulated.UpdateRotation(raw_status.delta_timestamp); + emulated.UpdateOrientation(raw_status.delta_timestamp); + + if (is_configuring) { + TriggerOnChange(ControllerTriggerType::Motion); + return; + } + + auto& motion = controller.motion_state[index]; + motion.accel = emulated.GetAcceleration(); + motion.gyro = emulated.GetGyroscope(); + motion.rotation = emulated.GetGyroscope(); + motion.orientation = emulated.GetOrientation(); + motion.is_at_rest = emulated.IsMoving(motion_sensitivity); + + TriggerOnChange(ControllerTriggerType::Motion); +} + +void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) { + if (index >= controller.battery_values.size()) { + return; + } + std::lock_guard lock{mutex}; + controller.battery_values[index] = TransformToBattery(callback); + + if (is_configuring) { + TriggerOnChange(ControllerTriggerType::Battery); + return; + } + + bool is_charging = false; + bool is_powered = false; + BatteryLevel battery_level = 0; + switch (controller.battery_values[index]) { + case Input::BatteryLevel::Charging: + is_charging = true; + is_powered = true; + battery_level = 6; + break; + case Input::BatteryLevel::Medium: + battery_level = 6; + break; + case Input::BatteryLevel::Low: + battery_level = 4; + break; + case Input::BatteryLevel::Critical: + battery_level = 2; + break; + case Input::BatteryLevel::Empty: + battery_level = 0; + break; + case Input::BatteryLevel::Full: + default: + is_powered = true; + battery_level = 8; + break; + } + + switch (index) { + case 0: + controller.battery_state.left = { + .is_powered = is_powered, + .is_charging = is_charging, + .battery_level = battery_level, + }; + break; + case 1: + controller.battery_state.right = { + .is_powered = is_powered, + .is_charging = is_charging, + .battery_level = battery_level, + }; + break; + case 2: + controller.battery_state.dual = { + .is_powered = is_powered, + .is_charging = is_charging, + .battery_level = battery_level, + }; + break; + } + TriggerOnChange(ControllerTriggerType::Battery); +} + +bool EmulatedController::SetVibration([[maybe_unused]] std::size_t device_index, + [[maybe_unused]] VibrationValue vibration) { + return false; +} + +int EmulatedController::TestVibration(std::size_t device_index) { + return 1; +} + +void EmulatedController::Connect() { + std::lock_guard lock{mutex}; + if (is_connected) { + LOG_WARNING(Service_HID, "Tried to turn on a connected controller {}", npad_id_type); + return; + } + is_connected = true; + TriggerOnChange(ControllerTriggerType::Connected); +} + +void EmulatedController::Disconnect() { + std::lock_guard lock{mutex}; + if (!is_connected) { + LOG_WARNING(Service_HID, "Tried to turn off a disconnected controller {}", npad_id_type); + return; + } + is_connected = false; + TriggerOnChange(ControllerTriggerType::Disconnected); +} + +bool EmulatedController::IsConnected() const { + return is_connected; +} + +bool EmulatedController::IsVibrationEnabled() const { + return is_vibration_enabled; +} + +NpadIdType EmulatedController::GetNpadIdType() const { + return npad_id_type; +} + +NpadType EmulatedController::GetNpadType() const { + return npad_type; +} + +void EmulatedController::SetNpadType(NpadType npad_type_) { + std::lock_guard lock{mutex}; + if (npad_type == npad_type_) { + return; + } + npad_type = npad_type_; + TriggerOnChange(ControllerTriggerType::Type); +} + +ButtonValues EmulatedController::GetButtonsValues() const { + return controller.button_values; +} + +SticksValues EmulatedController::GetSticksValues() const { + return controller.stick_values; +} + +TriggerValues EmulatedController::GetTriggersValues() const { + return controller.trigger_values; +} + +ControllerMotionValues EmulatedController::GetMotionValues() const { + return controller.motion_values; +} + +ColorValues EmulatedController::GetColorsValues() const { + return controller.color_values; +} + +BatteryValues EmulatedController::GetBatteryValues() const { + return controller.battery_values; +} + +NpadButtonState EmulatedController::GetNpadButtons() const { + if (is_configuring) { + return {}; + } + return controller.npad_button_state; +} + +DebugPadButton EmulatedController::GetDebugPadButtons() const { + if (is_configuring) { + return {}; + } + return controller.debug_pad_button_state; +} + +AnalogSticks EmulatedController::GetSticks() const { + if (is_configuring) { + return {}; + } + return controller.analog_stick_state; +} + +NpadGcTriggerState EmulatedController::GetTriggers() const { + if (is_configuring) { + return {}; + } + return controller.gc_trigger_state; +} + +MotionState EmulatedController::GetMotions() const { + return controller.motion_state; +} + +ControllerColors EmulatedController::GetColors() const { + return controller.colors_state; +} + +BatteryLevelState EmulatedController::GetBattery() const { + return controller.battery_state; +} + +void EmulatedController::TriggerOnChange(ControllerTriggerType type) { + for (const std::pair poller_pair : callback_list) { + const ControllerUpdateCallback& poller = poller_pair.second; + if (poller.on_change) { + poller.on_change(type); + } + } +} + +int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { + std::lock_guard lock{mutex}; + callback_list.insert_or_assign(last_callback_key, update_callback); + return last_callback_key++; +} + +void EmulatedController::DeleteCallback(int key) { + std::lock_guard lock{mutex}; + if (!callback_list.contains(key)) { + LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); + return; + } + callback_list.erase(key); +} +} // namespace Core::HID -- cgit v1.2.3 From 06a5ef5874144a70e30e577a83ba68d1dad79e78 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 11 Oct 2021 00:43:11 -0500 Subject: core/hid: Add output devices --- src/core/hid/emulated_controller.cpp | 119 +++++++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 27 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 4eb5d99bc..b9d16657a 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -66,12 +66,32 @@ void EmulatedController::ReloadFromSettings() { for (std::size_t index = 0; index < player.motions.size(); ++index) { motion_params[index] = Common::ParamPackage(player.motions[index]); } + + controller.colors_state.left = { + .body = player.body_color_left, + .button = player.button_color_left, + }; + + controller.colors_state.right = { + .body = player.body_color_right, + .button = player.button_color_right, + }; + + controller.colors_state.fullkey = controller.colors_state.left; + + SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + + if (player.connected) { + Connect(); + } else { + Disconnect(); + } + ReloadInput(); } void EmulatedController::ReloadInput() { const auto player_index = NpadIdTypeToIndex(npad_id_type); - const auto& player = Settings::values.players.GetValue()[player_index]; const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -90,21 +110,13 @@ void EmulatedController::ReloadInput() { trigger_devices[1] = Input::CreateDevice(button_params[Settings::NativeButton::ZR]); - controller.colors_state.left = { - .body = player.body_color_left, - .button = player.button_color_left, - }; - - controller.colors_state.right = { - .body = player.body_color_right, - .button = player.button_color_right, - }; - - controller.colors_state.fullkey = controller.colors_state.left; - battery_devices[0] = Input::CreateDevice(left_side); battery_devices[1] = Input::CreateDevice(right_side); + button_params[Settings::NativeButton::ZL].Set("output",true); + output_devices[0] = + Input::CreateDevice(button_params[Settings::NativeButton::ZL]); + for (std::size_t index = 0; index < button_devices.size(); ++index) { if (!button_devices[index]) { continue; @@ -149,14 +161,6 @@ void EmulatedController::ReloadInput() { [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; motion_devices[index]->SetCallback(motion_callback); } - - SetNpadType(MapSettingsTypeToNPad(player.controller_type)); - - if (player.connected) { - Connect(); - } else { - Disconnect(); - } } void EmulatedController::UnloadInput() { @@ -197,7 +201,8 @@ void EmulatedController::SaveCurrentConfig() { const auto player_index = NpadIdTypeToIndex(npad_id_type); auto& player = Settings::values.players.GetValue()[player_index]; - + player.connected = is_connected; + player.controller_type = MapNPadToSettingsType(npad_type); for (std::size_t index = 0; index < player.buttons.size(); ++index) { player.buttons[index] = button_params[index].Serialize(); } @@ -601,13 +606,50 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t TriggerOnChange(ControllerTriggerType::Battery); } -bool EmulatedController::SetVibration([[maybe_unused]] std::size_t device_index, - [[maybe_unused]] VibrationValue vibration) { - return false; +bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { + if (!output_devices[device_index]) { + return false; + } + + const Input::VibrationStatus status = { + .low_amplitude = vibration.high_amplitude, + .low_frequency = vibration.high_amplitude, + .high_amplitude = vibration.high_amplitude, + .high_frequency = vibration.high_amplitude, + }; + return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; +} + +bool EmulatedController::TestVibration(std::size_t device_index) { + if (!output_devices[device_index]) { + return false; + } + + // Send a slight vibration to test for rumble support + constexpr Input::VibrationStatus status = { + .low_amplitude = 0.001f, + .low_frequency = 160.0f, + .high_amplitude = 0.001f, + .high_frequency = 320.0f, + }; + return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; } -int EmulatedController::TestVibration(std::size_t device_index) { - return 1; +void EmulatedController::SetLedPattern() { + for (auto& device : output_devices) { + if (!device) { + continue; + } + + const LedPattern pattern = GetLedPattern(); + const Input::LedStatus status = { + .led_1 = pattern.position1 != 0, + .led_2 = pattern.position2 != 0, + .led_3 = pattern.position3 != 0, + .led_4 = pattern.position4 != 0, + }; + device->SetLED(status); + } } void EmulatedController::Connect() { @@ -655,6 +697,29 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { TriggerOnChange(ControllerTriggerType::Type); } +LedPattern EmulatedController::GetLedPattern() const { + switch (npad_id_type) { + case NpadIdType::Player1: + return LedPattern{1, 0, 0, 0}; + case NpadIdType::Player2: + return LedPattern{1, 1, 0, 0}; + case NpadIdType::Player3: + return LedPattern{1, 1, 1, 0}; + case NpadIdType::Player4: + return LedPattern{1, 1, 1, 1}; + case NpadIdType::Player5: + return LedPattern{1, 0, 0, 1}; + case NpadIdType::Player6: + return LedPattern{1, 0, 1, 0}; + case NpadIdType::Player7: + return LedPattern{1, 0, 1, 1}; + case NpadIdType::Player8: + return LedPattern{0, 1, 1, 0}; + default: + return LedPattern{0, 0, 0, 0}; + } +} + ButtonValues EmulatedController::GetButtonsValues() const { return controller.button_values; } -- cgit v1.2.3 From e0da5c1bbcdf85676f968b63c8ae2587f0464193 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 15 Oct 2021 19:07:47 -0500 Subject: kraken: Fix errors from rebase and format files --- src/core/hid/emulated_controller.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index b9d16657a..b04ab4cd8 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -91,6 +91,7 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { + // If you load any device here add the equivalent to the UnloadInput() function const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -113,7 +114,7 @@ void EmulatedController::ReloadInput() { battery_devices[0] = Input::CreateDevice(left_side); battery_devices[1] = Input::CreateDevice(right_side); - button_params[Settings::NativeButton::ZL].Set("output",true); + button_params[Settings::NativeButton::ZL].Set("output", true); output_devices[0] = Input::CreateDevice(button_params[Settings::NativeButton::ZL]); @@ -179,6 +180,9 @@ void EmulatedController::UnloadInput() { for (auto& battery : battery_devices) { battery.reset(); } + for (auto& output : output_devices) { + output.reset(); + } } void EmulatedController::EnableConfiguration() { -- cgit v1.2.3 From 4d308fd0b4fc8f14754c47811e751bf068b330b8 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 18 Oct 2021 23:15:46 -0500 Subject: hid: Fix controller connection/disconnection --- src/core/hid/emulated_controller.cpp | 98 ++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 21 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index b04ab4cd8..7ef6ef118 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -54,6 +54,7 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type } void EmulatedController::ReloadFromSettings() { + //LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type)); const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto& player = Settings::values.players.GetValue()[player_index]; @@ -91,6 +92,7 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { + //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto left_side = button_params[Settings::NativeButton::ZL]; @@ -187,11 +189,29 @@ void EmulatedController::UnloadInput() { void EmulatedController::EnableConfiguration() { is_configuring = true; - SaveCurrentConfig(); + temporary_is_connected = is_connected; + temporary_npad_type = npad_type; } void EmulatedController::DisableConfiguration() { is_configuring = false; + + // Apply temporary npad type to the real controller + if (temporary_npad_type != npad_type) { + if (is_connected) { + Disconnect(); + } + SetNpadType(temporary_npad_type); + } + + // Apply temporary connected status to the real controller + if (temporary_is_connected != is_connected) { + if (temporary_is_connected) { + Connect(); + return; + } + Disconnect(); + } } bool EmulatedController::IsConfiguring() const { @@ -199,10 +219,6 @@ bool EmulatedController::IsConfiguring() const { } void EmulatedController::SaveCurrentConfig() { - if (!is_configuring) { - return; - } - const auto player_index = NpadIdTypeToIndex(npad_id_type); auto& player = Settings::values.players.GetValue()[player_index]; player.connected = is_connected; @@ -657,26 +673,47 @@ void EmulatedController::SetLedPattern() { } void EmulatedController::Connect() { - std::lock_guard lock{mutex}; - if (is_connected) { - LOG_WARNING(Service_HID, "Tried to turn on a connected controller {}", npad_id_type); - return; + { + std::lock_guard lock{mutex}; + if (is_configuring) { + temporary_is_connected = true; + TriggerOnChange(ControllerTriggerType::Connected); + return; + } + + if (is_connected) { + return; + } + is_connected = true; } - is_connected = true; + LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Connected); } void EmulatedController::Disconnect() { - std::lock_guard lock{mutex}; - if (!is_connected) { - LOG_WARNING(Service_HID, "Tried to turn off a disconnected controller {}", npad_id_type); - return; + { + std::lock_guard lock{mutex}; + if (is_configuring) { + temporary_is_connected = false; + LOG_ERROR(Service_HID, "Disconnected temporal controller {}", + NpadIdTypeToIndex(npad_id_type)); + TriggerOnChange(ControllerTriggerType::Disconnected); + return; + } + + if (!is_connected) { + return; + } + is_connected = false; } - is_connected = false; + LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Disconnected); } -bool EmulatedController::IsConnected() const { +bool EmulatedController::IsConnected(bool temporary) const { + if (temporary) { + return temporary_is_connected; + } return is_connected; } @@ -688,16 +725,35 @@ NpadIdType EmulatedController::GetNpadIdType() const { return npad_id_type; } -NpadType EmulatedController::GetNpadType() const { +NpadType EmulatedController::GetNpadType(bool temporary) const { + if (temporary) { + return temporary_npad_type; + } return npad_type; } void EmulatedController::SetNpadType(NpadType npad_type_) { - std::lock_guard lock{mutex}; - if (npad_type == npad_type_) { - return; + { + std::lock_guard lock{mutex}; + + if (is_configuring) { + if (temporary_npad_type == npad_type_) { + return; + } + temporary_npad_type = npad_type_; + TriggerOnChange(ControllerTriggerType::Type); + return; + } + + if (npad_type == npad_type_) { + return; + } + if (is_connected) { + LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", + NpadIdTypeToIndex(npad_id_type)); + } + npad_type = npad_type_; } - npad_type = npad_type_; TriggerOnChange(ControllerTriggerType::Type); } -- cgit v1.2.3 From 601ac43495904f3f7666d79a800a8b4eda5a8461 Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 19 Oct 2021 00:12:24 -0500 Subject: core/hid: Only signal when needed --- src/core/hid/emulated_controller.cpp | 259 ++++++++++++++++++----------------- 1 file changed, 136 insertions(+), 123 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7ef6ef118..e102c9437 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -94,7 +94,6 @@ void EmulatedController::ReloadFromSettings() { void EmulatedController::ReloadInput() { //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function - const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -337,120 +336,130 @@ void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t i if (index >= controller.button_values.size()) { return; } - std::lock_guard lock{mutex}; - bool value_changed = false; - const auto new_status = TransformToButton(callback); - auto& current_status = controller.button_values[index]; - current_status.toggle = new_status.toggle; - - // Update button status with current - if (!current_status.toggle) { - current_status.locked = false; - if (current_status.value != new_status.value) { - current_status.value = new_status.value; - value_changed = true; - } - } else { - // Toggle button and lock status - if (new_status.value && !current_status.locked) { - current_status.locked = true; - current_status.value = !current_status.value; - value_changed = true; - } + { + std::lock_guard lock{mutex}; + bool value_changed = false; + const auto new_status = TransformToButton(callback); + auto& current_status = controller.button_values[index]; + current_status.toggle = new_status.toggle; - // Unlock button ready for next press - if (!new_status.value && current_status.locked) { + // Update button status with current + if (!current_status.toggle) { current_status.locked = false; + if (current_status.value != new_status.value) { + current_status.value = new_status.value; + value_changed = true; + } + } else { + // Toggle button and lock status + if (new_status.value && !current_status.locked) { + current_status.locked = true; + current_status.value = !current_status.value; + value_changed = true; + } + + // Unlock button ready for next press + if (!new_status.value && current_status.locked) { + current_status.locked = false; + } } - } - if (!value_changed) { - return; - } + if (!value_changed) { + return; + } - if (is_configuring) { - controller.npad_button_state.raw = NpadButton::None; - controller.debug_pad_button_state.raw = 0; - TriggerOnChange(ControllerTriggerType::Button); - return; - } + if (is_configuring) { + controller.npad_button_state.raw = NpadButton::None; + controller.debug_pad_button_state.raw = 0; + TriggerOnChange(ControllerTriggerType::Button, false); + return; + } - switch (index) { - case Settings::NativeButton::A: - controller.npad_button_state.a.Assign(current_status.value); - controller.debug_pad_button_state.a.Assign(current_status.value); - break; - case Settings::NativeButton::B: - controller.npad_button_state.b.Assign(current_status.value); - controller.debug_pad_button_state.b.Assign(current_status.value); - break; - case Settings::NativeButton::X: - controller.npad_button_state.x.Assign(current_status.value); - controller.debug_pad_button_state.x.Assign(current_status.value); - break; - case Settings::NativeButton::Y: - controller.npad_button_state.y.Assign(current_status.value); - controller.debug_pad_button_state.y.Assign(current_status.value); - break; - case Settings::NativeButton::LStick: - controller.npad_button_state.stick_l.Assign(current_status.value); - break; - case Settings::NativeButton::RStick: - controller.npad_button_state.stick_r.Assign(current_status.value); - break; - case Settings::NativeButton::L: - controller.npad_button_state.l.Assign(current_status.value); - controller.debug_pad_button_state.l.Assign(current_status.value); - break; - case Settings::NativeButton::R: - controller.npad_button_state.r.Assign(current_status.value); - controller.debug_pad_button_state.r.Assign(current_status.value); - break; - case Settings::NativeButton::ZL: - controller.npad_button_state.zl.Assign(current_status.value); - controller.debug_pad_button_state.zl.Assign(current_status.value); - break; - case Settings::NativeButton::ZR: - controller.npad_button_state.zr.Assign(current_status.value); - controller.debug_pad_button_state.zr.Assign(current_status.value); - break; - case Settings::NativeButton::Plus: - controller.npad_button_state.plus.Assign(current_status.value); - controller.debug_pad_button_state.plus.Assign(current_status.value); - break; - case Settings::NativeButton::Minus: - controller.npad_button_state.minus.Assign(current_status.value); - controller.debug_pad_button_state.minus.Assign(current_status.value); - break; - case Settings::NativeButton::DLeft: - controller.npad_button_state.left.Assign(current_status.value); - controller.debug_pad_button_state.d_left.Assign(current_status.value); - break; - case Settings::NativeButton::DUp: - controller.npad_button_state.up.Assign(current_status.value); - controller.debug_pad_button_state.d_up.Assign(current_status.value); - break; - case Settings::NativeButton::DRight: - controller.npad_button_state.right.Assign(current_status.value); - controller.debug_pad_button_state.d_right.Assign(current_status.value); - break; - case Settings::NativeButton::DDown: - controller.npad_button_state.down.Assign(current_status.value); - controller.debug_pad_button_state.d_down.Assign(current_status.value); - break; - case Settings::NativeButton::SL: - controller.npad_button_state.left_sl.Assign(current_status.value); - controller.npad_button_state.right_sl.Assign(current_status.value); - break; - case Settings::NativeButton::SR: - controller.npad_button_state.left_sr.Assign(current_status.value); - controller.npad_button_state.right_sr.Assign(current_status.value); - break; - case Settings::NativeButton::Home: - case Settings::NativeButton::Screenshot: - break; + switch (index) { + case Settings::NativeButton::A: + controller.npad_button_state.a.Assign(current_status.value); + controller.debug_pad_button_state.a.Assign(current_status.value); + break; + case Settings::NativeButton::B: + controller.npad_button_state.b.Assign(current_status.value); + controller.debug_pad_button_state.b.Assign(current_status.value); + break; + case Settings::NativeButton::X: + controller.npad_button_state.x.Assign(current_status.value); + controller.debug_pad_button_state.x.Assign(current_status.value); + break; + case Settings::NativeButton::Y: + controller.npad_button_state.y.Assign(current_status.value); + controller.debug_pad_button_state.y.Assign(current_status.value); + break; + case Settings::NativeButton::LStick: + controller.npad_button_state.stick_l.Assign(current_status.value); + break; + case Settings::NativeButton::RStick: + controller.npad_button_state.stick_r.Assign(current_status.value); + break; + case Settings::NativeButton::L: + controller.npad_button_state.l.Assign(current_status.value); + controller.debug_pad_button_state.l.Assign(current_status.value); + break; + case Settings::NativeButton::R: + controller.npad_button_state.r.Assign(current_status.value); + controller.debug_pad_button_state.r.Assign(current_status.value); + break; + case Settings::NativeButton::ZL: + controller.npad_button_state.zl.Assign(current_status.value); + controller.debug_pad_button_state.zl.Assign(current_status.value); + break; + case Settings::NativeButton::ZR: + controller.npad_button_state.zr.Assign(current_status.value); + controller.debug_pad_button_state.zr.Assign(current_status.value); + break; + case Settings::NativeButton::Plus: + controller.npad_button_state.plus.Assign(current_status.value); + controller.debug_pad_button_state.plus.Assign(current_status.value); + break; + case Settings::NativeButton::Minus: + controller.npad_button_state.minus.Assign(current_status.value); + controller.debug_pad_button_state.minus.Assign(current_status.value); + break; + case Settings::NativeButton::DLeft: + controller.npad_button_state.left.Assign(current_status.value); + controller.debug_pad_button_state.d_left.Assign(current_status.value); + break; + case Settings::NativeButton::DUp: + controller.npad_button_state.up.Assign(current_status.value); + controller.debug_pad_button_state.d_up.Assign(current_status.value); + break; + case Settings::NativeButton::DRight: + controller.npad_button_state.right.Assign(current_status.value); + controller.debug_pad_button_state.d_right.Assign(current_status.value); + break; + case Settings::NativeButton::DDown: + controller.npad_button_state.down.Assign(current_status.value); + controller.debug_pad_button_state.d_down.Assign(current_status.value); + break; + case Settings::NativeButton::SL: + controller.npad_button_state.left_sl.Assign(current_status.value); + controller.npad_button_state.right_sl.Assign(current_status.value); + break; + case Settings::NativeButton::SR: + controller.npad_button_state.left_sr.Assign(current_status.value); + controller.npad_button_state.right_sr.Assign(current_status.value); + break; + case Settings::NativeButton::Home: + case Settings::NativeButton::Screenshot: + break; + } + } + if (!is_connected) { + if (npad_id_type == NpadIdType::Player1 && npad_type != NpadType::Handheld) { + Connect(); + } + if (npad_id_type == NpadIdType::Handheld && npad_type == NpadType::Handheld) { + Connect(); + } } - TriggerOnChange(ControllerTriggerType::Button); + TriggerOnChange(ControllerTriggerType::Button, true); } void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) { @@ -463,7 +472,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in if (is_configuring) { controller.analog_stick_state.left = {}; controller.analog_stick_state.right = {}; - TriggerOnChange(ControllerTriggerType::Stick); + TriggerOnChange(ControllerTriggerType::Stick, false); return; } @@ -489,7 +498,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in break; } - TriggerOnChange(ControllerTriggerType::Stick); + TriggerOnChange(ControllerTriggerType::Stick, true); } void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) { @@ -502,7 +511,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t if (is_configuring) { controller.gc_trigger_state.left = 0; controller.gc_trigger_state.right = 0; - TriggerOnChange(ControllerTriggerType::Trigger); + TriggerOnChange(ControllerTriggerType::Trigger, false); return; } @@ -520,7 +529,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t break; } - TriggerOnChange(ControllerTriggerType::Trigger); + TriggerOnChange(ControllerTriggerType::Trigger, true); } void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) { @@ -546,7 +555,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i emulated.UpdateOrientation(raw_status.delta_timestamp); if (is_configuring) { - TriggerOnChange(ControllerTriggerType::Motion); + TriggerOnChange(ControllerTriggerType::Motion, false); return; } @@ -557,7 +566,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i motion.orientation = emulated.GetOrientation(); motion.is_at_rest = emulated.IsMoving(motion_sensitivity); - TriggerOnChange(ControllerTriggerType::Motion); + TriggerOnChange(ControllerTriggerType::Motion, true); } void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) { @@ -568,7 +577,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t controller.battery_values[index] = TransformToBattery(callback); if (is_configuring) { - TriggerOnChange(ControllerTriggerType::Battery); + TriggerOnChange(ControllerTriggerType::Battery, false); return; } @@ -593,6 +602,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t case Input::BatteryLevel::Empty: battery_level = 0; break; + case Input::BatteryLevel::None: case Input::BatteryLevel::Full: default: is_powered = true; @@ -623,7 +633,7 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t }; break; } - TriggerOnChange(ControllerTriggerType::Battery); + TriggerOnChange(ControllerTriggerType::Battery, true); } bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { @@ -677,7 +687,7 @@ void EmulatedController::Connect() { std::lock_guard lock{mutex}; if (is_configuring) { temporary_is_connected = true; - TriggerOnChange(ControllerTriggerType::Connected); + TriggerOnChange(ControllerTriggerType::Connected,false); return; } @@ -687,7 +697,7 @@ void EmulatedController::Connect() { is_connected = true; } LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Connected); + TriggerOnChange(ControllerTriggerType::Connected,true); } void EmulatedController::Disconnect() { @@ -697,7 +707,7 @@ void EmulatedController::Disconnect() { temporary_is_connected = false; LOG_ERROR(Service_HID, "Disconnected temporal controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected); + TriggerOnChange(ControllerTriggerType::Disconnected,false); return; } @@ -707,7 +717,7 @@ void EmulatedController::Disconnect() { is_connected = false; } LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected); + TriggerOnChange(ControllerTriggerType::Disconnected,true); } bool EmulatedController::IsConnected(bool temporary) const { @@ -741,7 +751,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { return; } temporary_npad_type = npad_type_; - TriggerOnChange(ControllerTriggerType::Type); + TriggerOnChange(ControllerTriggerType::Type,false); return; } @@ -754,7 +764,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { } npad_type = npad_type_; } - TriggerOnChange(ControllerTriggerType::Type); + TriggerOnChange(ControllerTriggerType::Type,true); } LedPattern EmulatedController::GetLedPattern() const { @@ -844,9 +854,12 @@ BatteryLevelState EmulatedController::GetBattery() const { return controller.battery_state; } -void EmulatedController::TriggerOnChange(ControllerTriggerType type) { +void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_service_update) { for (const std::pair poller_pair : callback_list) { const ControllerUpdateCallback& poller = poller_pair.second; + if (!is_service_update && poller.is_service) { + continue; + } if (poller.on_change) { poller.on_change(type); } -- cgit v1.2.3 From c3ff0a8ac0d1c3f9c0791b5263dae53c06ad6048 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 20 Oct 2021 14:41:56 -0500 Subject: core/hid: Fix rumble too strong at 1% --- src/core/hid/emulated_controller.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index e102c9437..7b0c4a49b 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -54,7 +54,6 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type } void EmulatedController::ReloadFromSettings() { - //LOG_ERROR(Service_HID, "reload config from settings {}", NpadIdTypeToIndex(npad_id_type)); const auto player_index = NpadIdTypeToIndex(npad_id_type); const auto& player = Settings::values.players.GetValue()[player_index]; @@ -92,7 +91,7 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { - //LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); + // LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; @@ -640,12 +639,22 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v if (!output_devices[device_index]) { return false; } + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + const f32 strength = static_cast(player.vibration_strength) / 100.0f; + + // Exponential amplification is too strong at low amplitudes. Switch to a linear + // amplification if strength is set below 0.7f + const Input::VibrationAmplificationType type = + strength > 0.7f ? Input::VibrationAmplificationType::Exponential + : Input::VibrationAmplificationType::Linear; const Input::VibrationStatus status = { - .low_amplitude = vibration.high_amplitude, - .low_frequency = vibration.high_amplitude, - .high_amplitude = vibration.high_amplitude, - .high_frequency = vibration.high_amplitude, + .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), + .low_frequency = vibration.low_frequency, + .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), + .high_frequency = vibration.high_frequency, + .type = type, }; return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; } @@ -661,6 +670,7 @@ bool EmulatedController::TestVibration(std::size_t device_index) { .low_frequency = 160.0f, .high_amplitude = 0.001f, .high_frequency = 320.0f, + .type = Input::VibrationAmplificationType::Linear, }; return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; } @@ -687,7 +697,7 @@ void EmulatedController::Connect() { std::lock_guard lock{mutex}; if (is_configuring) { temporary_is_connected = true; - TriggerOnChange(ControllerTriggerType::Connected,false); + TriggerOnChange(ControllerTriggerType::Connected, false); return; } @@ -697,7 +707,7 @@ void EmulatedController::Connect() { is_connected = true; } LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Connected,true); + TriggerOnChange(ControllerTriggerType::Connected, true); } void EmulatedController::Disconnect() { @@ -707,7 +717,7 @@ void EmulatedController::Disconnect() { temporary_is_connected = false; LOG_ERROR(Service_HID, "Disconnected temporal controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected,false); + TriggerOnChange(ControllerTriggerType::Disconnected, false); return; } @@ -717,7 +727,7 @@ void EmulatedController::Disconnect() { is_connected = false; } LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); - TriggerOnChange(ControllerTriggerType::Disconnected,true); + TriggerOnChange(ControllerTriggerType::Disconnected, true); } bool EmulatedController::IsConnected(bool temporary) const { @@ -751,7 +761,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { return; } temporary_npad_type = npad_type_; - TriggerOnChange(ControllerTriggerType::Type,false); + TriggerOnChange(ControllerTriggerType::Type, false); return; } @@ -764,7 +774,7 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { } npad_type = npad_type_; } - TriggerOnChange(ControllerTriggerType::Type,true); + TriggerOnChange(ControllerTriggerType::Type, true); } LedPattern EmulatedController::GetLedPattern() const { -- cgit v1.2.3 From af55dd193533be577d0a3d01f93a4a3a2c27cd5d Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 20 Oct 2021 17:53:14 -0500 Subject: configuration: Migrate controller settings to emulated controller --- src/core/hid/emulated_controller.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7b0c4a49b..662260327 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -91,7 +91,6 @@ void EmulatedController::ReloadFromSettings() { } void EmulatedController::ReloadInput() { - // LOG_ERROR(Service_HID, "reload config {}", NpadIdTypeToIndex(npad_id_type)); // If you load any device here add the equivalent to the UnloadInput() function const auto left_side = button_params[Settings::NativeButton::ZL]; const auto right_side = button_params[Settings::NativeButton::ZR]; -- cgit v1.2.3 From 85052b8662d9512077780f717fb2e168390ed705 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 20 Oct 2021 23:18:04 -0500 Subject: service/hid: Fix gesture input --- src/core/hid/emulated_controller.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 662260327..1ff3022c5 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -705,7 +705,6 @@ void EmulatedController::Connect() { } is_connected = true; } - LOG_ERROR(Service_HID, "Connected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Connected, true); } @@ -714,8 +713,6 @@ void EmulatedController::Disconnect() { std::lock_guard lock{mutex}; if (is_configuring) { temporary_is_connected = false; - LOG_ERROR(Service_HID, "Disconnected temporal controller {}", - NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Disconnected, false); return; } @@ -725,7 +722,6 @@ void EmulatedController::Disconnect() { } is_connected = false; } - LOG_ERROR(Service_HID, "Disconnected controller {}", NpadIdTypeToIndex(npad_id_type)); TriggerOnChange(ControllerTriggerType::Disconnected, true); } -- cgit v1.2.3 From b5e72de753ae4de5c5fae7087abb00dc4242451d Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 21 Oct 2021 13:56:52 -0500 Subject: kraken: Address comments from review review fixes --- src/core/hid/emulated_controller.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 1ff3022c5..d59758e99 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included -#include - #include "core/hid/emulated_controller.h" #include "core/hid/input_converter.h" @@ -635,6 +633,9 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t } bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { + if (device_index >= output_devices.size()) { + return false; + } if (!output_devices[device_index]) { return false; } @@ -659,6 +660,9 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v } bool EmulatedController::TestVibration(std::size_t device_index) { + if (device_index >= output_devices.size()) { + return false; + } if (!output_devices[device_index]) { return false; } @@ -733,7 +737,9 @@ bool EmulatedController::IsConnected(bool temporary) const { } bool EmulatedController::IsVibrationEnabled() const { - return is_vibration_enabled; + const auto player_index = NpadIdTypeToIndex(npad_id_type); + const auto& player = Settings::values.players.GetValue()[player_index]; + return player.vibration_enabled; } NpadIdType EmulatedController::GetNpadIdType() const { -- cgit v1.2.3 From b564f024f0be5023cf13fb2fca953ea6c1feeeb6 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 22 Oct 2021 23:04:06 -0500 Subject: Morph review first wave --- src/core/hid/emulated_controller.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index d59758e99..228f80183 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -865,10 +865,10 @@ BatteryLevelState EmulatedController::GetBattery() const { return controller.battery_state; } -void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_service_update) { - for (const std::pair poller_pair : callback_list) { +void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { + for (const auto& poller_pair : callback_list) { const ControllerUpdateCallback& poller = poller_pair.second; - if (!is_service_update && poller.is_service) { + if (!is_npad_service_update && poller.is_npad_service) { continue; } if (poller.on_change) { -- cgit v1.2.3 From 464c4d26ac8e7af6302390684445b357e5cda4e4 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 24 Oct 2021 11:22:20 -0500 Subject: settings: Fix mouse and keyboard mappings --- src/core/hid/emulated_controller.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 228f80183..bd0b89c05 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -246,7 +246,7 @@ std::vector EmulatedController::GetMappedDevices() const { devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { return param.Get("engine", "") == param_.Get("engine", "") && param.Get("guid", "") == param_.Get("guid", "") && - param.Get("port", "") == param_.Get("port", ""); + param.Get("port", 0) == param_.Get("port", 0); }); if (devices_it != devices.end()) { continue; @@ -254,7 +254,7 @@ std::vector EmulatedController::GetMappedDevices() const { Common::ParamPackage device{}; device.Set("engine", param.Get("engine", "")); device.Set("guid", param.Get("guid", "")); - device.Set("port", param.Get("port", "")); + device.Set("port", param.Get("port", 0)); devices.push_back(device); } @@ -269,7 +269,7 @@ std::vector EmulatedController::GetMappedDevices() const { devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { return param.Get("engine", "") == param_.Get("engine", "") && param.Get("guid", "") == param_.Get("guid", "") && - param.Get("port", "") == param_.Get("port", ""); + param.Get("port", 0) == param_.Get("port", 0); }); if (devices_it != devices.end()) { continue; @@ -277,7 +277,7 @@ std::vector EmulatedController::GetMappedDevices() const { Common::ParamPackage device{}; device.Set("engine", param.Get("engine", "")); device.Set("guid", param.Get("guid", "")); - device.Set("port", param.Get("port", "")); + device.Set("port", param.Get("port", 0)); devices.push_back(device); } return devices; -- cgit v1.2.3 From c6c32daf40ae1c720f0a2897c538bb1117371ea5 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 24 Oct 2021 20:28:54 -0500 Subject: input_common: Add manual update options to input devices --- src/core/hid/emulated_controller.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index bd0b89c05..48add394b 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -122,6 +122,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback button_callback{ [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; button_devices[index]->SetCallback(button_callback); + button_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < stick_devices.size(); ++index) { @@ -131,6 +132,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback stick_callback{ [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; stick_devices[index]->SetCallback(stick_callback); + stick_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < trigger_devices.size(); ++index) { @@ -140,6 +142,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback trigger_callback{ [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }}; trigger_devices[index]->SetCallback(trigger_callback); + trigger_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < battery_devices.size(); ++index) { @@ -149,6 +152,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback battery_callback{ [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }}; battery_devices[index]->SetCallback(battery_callback); + battery_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < motion_devices.size(); ++index) { @@ -158,6 +162,7 @@ void EmulatedController::ReloadInput() { Input::InputCallback motion_callback{ [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; motion_devices[index]->SetCallback(motion_callback); + motion_devices[index]->ForceUpdate(); } } @@ -843,6 +848,10 @@ AnalogSticks EmulatedController::GetSticks() const { if (is_configuring) { return {}; } + // Some drivers like stick from buttons need constant refreshing + for (auto& device : stick_devices) { + device->SoftUpdate(); + } return controller.analog_stick_state; } -- cgit v1.2.3 From 064ddacf49aa7155e26add55983b81fdda997077 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 24 Oct 2021 23:23:54 -0500 Subject: core/hid: Rework battery mappings --- src/core/hid/emulated_controller.cpp | 50 +++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 48add394b..83ced5635 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -87,11 +87,23 @@ void EmulatedController::ReloadFromSettings() { ReloadInput(); } +void EmulatedController::LoadDevices() { + const auto left_joycon = button_params[Settings::NativeButton::ZL]; + const auto right_joycon = button_params[Settings::NativeButton::ZR]; -void EmulatedController::ReloadInput() { - // If you load any device here add the equivalent to the UnloadInput() function - const auto left_side = button_params[Settings::NativeButton::ZL]; - const auto right_side = button_params[Settings::NativeButton::ZR]; + // Triggers for GC controllers + trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; + trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR]; + + battery_params[LeftIndex] = left_joycon; + battery_params[RightIndex] = right_joycon; + battery_params[LeftIndex].Set("battery", true); + battery_params[RightIndex].Set("battery", true); + + output_params[LeftIndex] = left_joycon; + output_params[RightIndex] = right_joycon; + output_params[LeftIndex].Set("output", true); + output_params[RightIndex].Set("output", true); std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, button_params.begin() + Settings::NativeButton::BUTTON_NS_END, @@ -102,19 +114,17 @@ void EmulatedController::ReloadInput() { std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, motion_devices.begin(), Input::CreateDevice); + std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), + Input::CreateDevice); + std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(), + Input::CreateDevice); + std::transform(output_params.begin(), output_params.end(), output_devices.begin(), + Input::CreateDevice); +} - trigger_devices[0] = - Input::CreateDevice(button_params[Settings::NativeButton::ZL]); - trigger_devices[1] = - Input::CreateDevice(button_params[Settings::NativeButton::ZR]); - - battery_devices[0] = Input::CreateDevice(left_side); - battery_devices[1] = Input::CreateDevice(right_side); - - button_params[Settings::NativeButton::ZL].Set("output", true); - output_devices[0] = - Input::CreateDevice(button_params[Settings::NativeButton::ZL]); - +void EmulatedController::ReloadInput() { + // If you load any device here add the equivalent to the UnloadInput() function + LoadDevices(); for (std::size_t index = 0; index < button_devices.size(); ++index) { if (!button_devices[index]) { continue; @@ -241,7 +251,7 @@ void EmulatedController::RestoreConfig() { ReloadFromSettings(); } -std::vector EmulatedController::GetMappedDevices() const { +std::vector EmulatedController::GetMappedDevices(DeviceIndex device_index) const { std::vector devices; for (const auto& param : button_params) { if (!param.Has("engine")) { @@ -612,21 +622,21 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t } switch (index) { - case 0: + case LeftIndex: controller.battery_state.left = { .is_powered = is_powered, .is_charging = is_charging, .battery_level = battery_level, }; break; - case 1: + case RightIndex: controller.battery_state.right = { .is_powered = is_powered, .is_charging = is_charging, .battery_level = battery_level, }; break; - case 2: + case DualIndex: controller.battery_state.dual = { .is_powered = is_powered, .is_charging = is_charging, -- cgit v1.2.3 From 7348e205d94e2fff777781498a2ef7931163703a Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 26 Oct 2021 23:37:46 -0500 Subject: input_common: Add multiple vibration curves --- src/core/hid/emulated_controller.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 83ced5635..916368c68 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -251,7 +251,8 @@ void EmulatedController::RestoreConfig() { ReloadFromSettings(); } -std::vector EmulatedController::GetMappedDevices(DeviceIndex device_index) const { +std::vector EmulatedController::GetMappedDevices( + DeviceIndex device_index) const { std::vector devices; for (const auto& param : button_params) { if (!param.Has("engine")) { @@ -658,6 +659,10 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v const auto& player = Settings::values.players.GetValue()[player_index]; const f32 strength = static_cast(player.vibration_strength) / 100.0f; + if (!player.vibration_enabled) { + return false; + } + // Exponential amplification is too strong at low amplitudes. Switch to a linear // amplification if strength is set below 0.7f const Input::VibrationAmplificationType type = @@ -860,6 +865,9 @@ AnalogSticks EmulatedController::GetSticks() const { } // Some drivers like stick from buttons need constant refreshing for (auto& device : stick_devices) { + if (!device) { + continue; + } device->SoftUpdate(); } return controller.analog_stick_state; -- cgit v1.2.3 From c085e54316c5520ed7d58a92a7faa9e896bb6c71 Mon Sep 17 00:00:00 2001 From: german77 Date: Wed, 27 Oct 2021 00:20:28 -0500 Subject: core/hid: Add TAS input --- src/core/hid/emulated_controller.cpp | 72 ++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 916368c68..2b051ccaf 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -105,6 +105,8 @@ void EmulatedController::LoadDevices() { output_params[LeftIndex].Set("output", true); output_params[RightIndex].Set("output", true); + LoadTASParams(); + std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, button_params.begin() + Settings::NativeButton::BUTTON_NS_END, button_devices.begin(), Input::CreateDevice); @@ -120,6 +122,51 @@ void EmulatedController::LoadDevices() { Input::CreateDevice); std::transform(output_params.begin(), output_params.end(), output_devices.begin(), Input::CreateDevice); + + // Initialize TAS devices + std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), + Input::CreateDevice); + std::transform(tas_stick_params.begin(), tas_stick_params.begin(), tas_stick_devices.begin(), + Input::CreateDevice); +} + +void EmulatedController::LoadTASParams() { + const auto player_index = NpadIdTypeToIndex(npad_id_type); + Common::ParamPackage common_params{}; + common_params.Set("engine", "tas"); + common_params.Set("pad", static_cast(player_index)); + for (auto& param : tas_button_params) { + param = common_params; + } + for (auto& param : tas_stick_params) { + param = common_params; + } + + tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0); + tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1); + tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2); + tas_button_params[Settings::NativeButton::Y].Set("button", 1 << 3); + tas_button_params[Settings::NativeButton::LStick].Set("button", 1 << 4); + tas_button_params[Settings::NativeButton::RStick].Set("button", 1 << 5); + tas_button_params[Settings::NativeButton::L].Set("button", 1 << 6); + tas_button_params[Settings::NativeButton::R].Set("button", 1 << 7); + tas_button_params[Settings::NativeButton::ZL].Set("button", 1 << 8); + tas_button_params[Settings::NativeButton::ZR].Set("button", 1 << 9); + tas_button_params[Settings::NativeButton::Plus].Set("button", 1 << 10); + tas_button_params[Settings::NativeButton::Minus].Set("button", 1 << 11); + tas_button_params[Settings::NativeButton::DLeft].Set("button", 1 << 12); + tas_button_params[Settings::NativeButton::DUp].Set("button", 1 << 13); + tas_button_params[Settings::NativeButton::DRight].Set("button", 1 << 14); + tas_button_params[Settings::NativeButton::DDown].Set("button", 1 << 15); + tas_button_params[Settings::NativeButton::SL].Set("button", 1 << 16); + tas_button_params[Settings::NativeButton::SR].Set("button", 1 << 17); + tas_button_params[Settings::NativeButton::Home].Set("button", 1 << 18); + tas_button_params[Settings::NativeButton::Screenshot].Set("button", 1 << 19); + + tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); + tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); + tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2); + tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); } void EmulatedController::ReloadInput() { @@ -174,6 +221,25 @@ void EmulatedController::ReloadInput() { motion_devices[index]->SetCallback(motion_callback); motion_devices[index]->ForceUpdate(); } + + // Register TAS devices. No need to force update + for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { + if (!tas_button_devices[index]) { + continue; + } + Input::InputCallback button_callback{ + [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + tas_button_devices[index]->SetCallback(button_callback); + } + + for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) { + if (!tas_stick_devices[index]) { + continue; + } + Input::InputCallback stick_callback{ + [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + tas_stick_devices[index]->SetCallback(stick_callback); + } } void EmulatedController::UnloadInput() { @@ -195,6 +261,12 @@ void EmulatedController::UnloadInput() { for (auto& output : output_devices) { output.reset(); } + for (auto& button : tas_button_devices) { + button.reset(); + } + for (auto& stick : tas_stick_devices) { + stick.reset(); + } } void EmulatedController::EnableConfiguration() { -- cgit v1.2.3 From 5f69fdbfccdf68ddb5bb22de32321fa352b22c0a Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 30 Oct 2021 12:12:52 -0500 Subject: core/hid: Explain better what a temporary value does --- src/core/hid/emulated_controller.cpp | 38 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 2b051ccaf..3c3fa16d6 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -88,8 +88,9 @@ void EmulatedController::ReloadFromSettings() { ReloadInput(); } void EmulatedController::LoadDevices() { - const auto left_joycon = button_params[Settings::NativeButton::ZL]; - const auto right_joycon = button_params[Settings::NativeButton::ZR]; + // TODO(german77): Use more buttons to detect the correct device + const auto left_joycon = button_params[Settings::NativeButton::A]; + const auto right_joycon = button_params[Settings::NativeButton::DRight]; // Triggers for GC controllers trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; @@ -142,6 +143,7 @@ void EmulatedController::LoadTASParams() { param = common_params; } + // TODO(german77): Replace this with an input profile or something better tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0); tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1); tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2); @@ -271,24 +273,24 @@ void EmulatedController::UnloadInput() { void EmulatedController::EnableConfiguration() { is_configuring = true; - temporary_is_connected = is_connected; - temporary_npad_type = npad_type; + tmp_is_connected = is_connected; + tmp_npad_type = npad_type; } void EmulatedController::DisableConfiguration() { is_configuring = false; // Apply temporary npad type to the real controller - if (temporary_npad_type != npad_type) { + if (tmp_npad_type != npad_type) { if (is_connected) { Disconnect(); } - SetNpadType(temporary_npad_type); + SetNpadType(tmp_npad_type); } // Apply temporary connected status to the real controller - if (temporary_is_connected != is_connected) { - if (temporary_is_connected) { + if (tmp_is_connected != is_connected) { + if (tmp_is_connected) { Connect(); return; } @@ -791,7 +793,7 @@ void EmulatedController::Connect() { { std::lock_guard lock{mutex}; if (is_configuring) { - temporary_is_connected = true; + tmp_is_connected = true; TriggerOnChange(ControllerTriggerType::Connected, false); return; } @@ -808,7 +810,7 @@ void EmulatedController::Disconnect() { { std::lock_guard lock{mutex}; if (is_configuring) { - temporary_is_connected = false; + tmp_is_connected = false; TriggerOnChange(ControllerTriggerType::Disconnected, false); return; } @@ -821,9 +823,9 @@ void EmulatedController::Disconnect() { TriggerOnChange(ControllerTriggerType::Disconnected, true); } -bool EmulatedController::IsConnected(bool temporary) const { - if (temporary) { - return temporary_is_connected; +bool EmulatedController::IsConnected(bool get_temporary_value) const { + if (get_temporary_value) { + return tmp_is_connected; } return is_connected; } @@ -838,9 +840,9 @@ NpadIdType EmulatedController::GetNpadIdType() const { return npad_id_type; } -NpadType EmulatedController::GetNpadType(bool temporary) const { - if (temporary) { - return temporary_npad_type; +NpadType EmulatedController::GetNpadType(bool get_temporary_value) const { + if (get_temporary_value) { + return tmp_npad_type; } return npad_type; } @@ -850,10 +852,10 @@ void EmulatedController::SetNpadType(NpadType npad_type_) { std::lock_guard lock{mutex}; if (is_configuring) { - if (temporary_npad_type == npad_type_) { + if (tmp_npad_type == npad_type_) { return; } - temporary_npad_type = npad_type_; + tmp_npad_type = npad_type_; TriggerOnChange(ControllerTriggerType::Type, false); return; } -- cgit v1.2.3 From 61d9eb9f690d6afe141f24ba75c99b54e122dfa3 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 30 Oct 2021 20:16:10 -0500 Subject: input_common: Revert deleted TAS functions --- src/core/hid/emulated_controller.cpp | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 3c3fa16d6..69568f4e9 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -127,7 +127,7 @@ void EmulatedController::LoadDevices() { // Initialize TAS devices std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), Input::CreateDevice); - std::transform(tas_stick_params.begin(), tas_stick_params.begin(), tas_stick_devices.begin(), + std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(), Input::CreateDevice); } @@ -135,7 +135,7 @@ void EmulatedController::LoadTASParams() { const auto player_index = NpadIdTypeToIndex(npad_id_type); Common::ParamPackage common_params{}; common_params.Set("engine", "tas"); - common_params.Set("pad", static_cast(player_index)); + common_params.Set("port", static_cast(player_index)); for (auto& param : tas_button_params) { param = common_params; } @@ -144,26 +144,26 @@ void EmulatedController::LoadTASParams() { } // TODO(german77): Replace this with an input profile or something better - tas_button_params[Settings::NativeButton::A].Set("button", 1 << 0); - tas_button_params[Settings::NativeButton::B].Set("button", 1 << 1); - tas_button_params[Settings::NativeButton::X].Set("button", 1 << 2); - tas_button_params[Settings::NativeButton::Y].Set("button", 1 << 3); - tas_button_params[Settings::NativeButton::LStick].Set("button", 1 << 4); - tas_button_params[Settings::NativeButton::RStick].Set("button", 1 << 5); - tas_button_params[Settings::NativeButton::L].Set("button", 1 << 6); - tas_button_params[Settings::NativeButton::R].Set("button", 1 << 7); - tas_button_params[Settings::NativeButton::ZL].Set("button", 1 << 8); - tas_button_params[Settings::NativeButton::ZR].Set("button", 1 << 9); - tas_button_params[Settings::NativeButton::Plus].Set("button", 1 << 10); - tas_button_params[Settings::NativeButton::Minus].Set("button", 1 << 11); - tas_button_params[Settings::NativeButton::DLeft].Set("button", 1 << 12); - tas_button_params[Settings::NativeButton::DUp].Set("button", 1 << 13); - tas_button_params[Settings::NativeButton::DRight].Set("button", 1 << 14); - tas_button_params[Settings::NativeButton::DDown].Set("button", 1 << 15); - tas_button_params[Settings::NativeButton::SL].Set("button", 1 << 16); - tas_button_params[Settings::NativeButton::SR].Set("button", 1 << 17); - tas_button_params[Settings::NativeButton::Home].Set("button", 1 << 18); - tas_button_params[Settings::NativeButton::Screenshot].Set("button", 1 << 19); + tas_button_params[Settings::NativeButton::A].Set("button", 0); + tas_button_params[Settings::NativeButton::B].Set("button", 1); + tas_button_params[Settings::NativeButton::X].Set("button", 2); + tas_button_params[Settings::NativeButton::Y].Set("button", 3); + tas_button_params[Settings::NativeButton::LStick].Set("button", 4); + tas_button_params[Settings::NativeButton::RStick].Set("button", 5); + tas_button_params[Settings::NativeButton::L].Set("button", 6); + tas_button_params[Settings::NativeButton::R].Set("button", 7); + tas_button_params[Settings::NativeButton::ZL].Set("button", 8); + tas_button_params[Settings::NativeButton::ZR].Set("button", 9); + tas_button_params[Settings::NativeButton::Plus].Set("button", 10); + tas_button_params[Settings::NativeButton::Minus].Set("button", 11); + tas_button_params[Settings::NativeButton::DLeft].Set("button", 12); + tas_button_params[Settings::NativeButton::DUp].Set("button", 13); + tas_button_params[Settings::NativeButton::DRight].Set("button", 14); + tas_button_params[Settings::NativeButton::DDown].Set("button", 15); + tas_button_params[Settings::NativeButton::SL].Set("button", 16); + tas_button_params[Settings::NativeButton::SR].Set("button", 17); + tas_button_params[Settings::NativeButton::Home].Set("button", 18); + tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19); tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); -- cgit v1.2.3 From 2b1b0c2a30e242b08ec120e09803ec54d5445703 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 30 Oct 2021 22:23:10 -0500 Subject: kraken: Address comments from review start lion review --- src/core/hid/emulated_controller.cpp | 88 ++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 43 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 69568f4e9..49893cdbd 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -110,25 +110,25 @@ void EmulatedController::LoadDevices() { std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, button_params.begin() + Settings::NativeButton::BUTTON_NS_END, - button_devices.begin(), Input::CreateDevice); + button_devices.begin(), Common::Input::CreateDevice); std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, stick_params.begin() + Settings::NativeAnalog::STICK_HID_END, - stick_devices.begin(), Input::CreateDevice); + stick_devices.begin(), Common::Input::CreateDevice); std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, - motion_devices.begin(), Input::CreateDevice); + motion_devices.begin(), Common::Input::CreateDevice); std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(), - Input::CreateDevice); + Common::Input::CreateDevice); std::transform(output_params.begin(), output_params.end(), output_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); // Initialize TAS devices std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(), - Input::CreateDevice); + Common::Input::CreateDevice); } void EmulatedController::LoadTASParams() { @@ -178,8 +178,8 @@ void EmulatedController::ReloadInput() { if (!button_devices[index]) { continue; } - Input::InputCallback button_callback{ - [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; button_devices[index]->SetCallback(button_callback); button_devices[index]->ForceUpdate(); } @@ -188,8 +188,8 @@ void EmulatedController::ReloadInput() { if (!stick_devices[index]) { continue; } - Input::InputCallback stick_callback{ - [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + Common::Input::InputCallback stick_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; stick_devices[index]->SetCallback(stick_callback); stick_devices[index]->ForceUpdate(); } @@ -198,8 +198,8 @@ void EmulatedController::ReloadInput() { if (!trigger_devices[index]) { continue; } - Input::InputCallback trigger_callback{ - [this, index](Input::CallbackStatus callback) { SetTrigger(callback, index); }}; + Common::Input::InputCallback trigger_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetTrigger(callback, index); }}; trigger_devices[index]->SetCallback(trigger_callback); trigger_devices[index]->ForceUpdate(); } @@ -208,8 +208,8 @@ void EmulatedController::ReloadInput() { if (!battery_devices[index]) { continue; } - Input::InputCallback battery_callback{ - [this, index](Input::CallbackStatus callback) { SetBattery(callback, index); }}; + Common::Input::InputCallback battery_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetBattery(callback, index); }}; battery_devices[index]->SetCallback(battery_callback); battery_devices[index]->ForceUpdate(); } @@ -218,8 +218,8 @@ void EmulatedController::ReloadInput() { if (!motion_devices[index]) { continue; } - Input::InputCallback motion_callback{ - [this, index](Input::CallbackStatus callback) { SetMotion(callback, index); }}; + Common::Input::InputCallback motion_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetMotion(callback, index); }}; motion_devices[index]->SetCallback(motion_callback); motion_devices[index]->ForceUpdate(); } @@ -229,8 +229,8 @@ void EmulatedController::ReloadInput() { if (!tas_button_devices[index]) { continue; } - Input::InputCallback button_callback{ - [this, index](Input::CallbackStatus callback) { SetButton(callback, index); }}; + Common::Input::InputCallback button_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; tas_button_devices[index]->SetCallback(button_callback); } @@ -238,8 +238,8 @@ void EmulatedController::ReloadInput() { if (!tas_stick_devices[index]) { continue; } - Input::InputCallback stick_callback{ - [this, index](Input::CallbackStatus callback) { SetStick(callback, index); }}; + Common::Input::InputCallback stick_callback{ + [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; tas_stick_devices[index]->SetCallback(stick_callback); } } @@ -418,7 +418,7 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage ReloadInput(); } -void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.button_values.size()) { return; } @@ -548,7 +548,7 @@ void EmulatedController::SetButton(Input::CallbackStatus callback, std::size_t i TriggerOnChange(ControllerTriggerType::Button, true); } -void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.stick_values.size()) { return; } @@ -587,7 +587,7 @@ void EmulatedController::SetStick(Input::CallbackStatus callback, std::size_t in TriggerOnChange(ControllerTriggerType::Stick, true); } -void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.trigger_values.size()) { return; } @@ -618,7 +618,7 @@ void EmulatedController::SetTrigger(Input::CallbackStatus callback, std::size_t TriggerOnChange(ControllerTriggerType::Trigger, true); } -void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.motion_values.size()) { return; } @@ -655,7 +655,7 @@ void EmulatedController::SetMotion(Input::CallbackStatus callback, std::size_t i TriggerOnChange(ControllerTriggerType::Motion, true); } -void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std::size_t index) { if (index >= controller.battery_values.size()) { return; } @@ -671,25 +671,25 @@ void EmulatedController::SetBattery(Input::CallbackStatus callback, std::size_t bool is_powered = false; BatteryLevel battery_level = 0; switch (controller.battery_values[index]) { - case Input::BatteryLevel::Charging: + case Common::Input::BatteryLevel::Charging: is_charging = true; is_powered = true; battery_level = 6; break; - case Input::BatteryLevel::Medium: + case Common::Input::BatteryLevel::Medium: battery_level = 6; break; - case Input::BatteryLevel::Low: + case Common::Input::BatteryLevel::Low: battery_level = 4; break; - case Input::BatteryLevel::Critical: + case Common::Input::BatteryLevel::Critical: battery_level = 2; break; - case Input::BatteryLevel::Empty: + case Common::Input::BatteryLevel::Empty: battery_level = 0; break; - case Input::BatteryLevel::None: - case Input::BatteryLevel::Full: + case Common::Input::BatteryLevel::None: + case Common::Input::BatteryLevel::Full: default: is_powered = true; battery_level = 8; @@ -739,18 +739,19 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v // Exponential amplification is too strong at low amplitudes. Switch to a linear // amplification if strength is set below 0.7f - const Input::VibrationAmplificationType type = - strength > 0.7f ? Input::VibrationAmplificationType::Exponential - : Input::VibrationAmplificationType::Linear; + const Common::Input::VibrationAmplificationType type = + strength > 0.7f ? Common::Input::VibrationAmplificationType::Exponential + : Common::Input::VibrationAmplificationType::Linear; - const Input::VibrationStatus status = { + const Common::Input::VibrationStatus status = { .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), .low_frequency = vibration.low_frequency, .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), .high_frequency = vibration.high_frequency, .type = type, }; - return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; + return output_devices[device_index]->SetVibration(status) == + Common::Input::VibrationError::None; } bool EmulatedController::TestVibration(std::size_t device_index) { @@ -762,14 +763,15 @@ bool EmulatedController::TestVibration(std::size_t device_index) { } // Send a slight vibration to test for rumble support - constexpr Input::VibrationStatus status = { + constexpr Common::Input::VibrationStatus status = { .low_amplitude = 0.001f, .low_frequency = 160.0f, .high_amplitude = 0.001f, .high_frequency = 320.0f, - .type = Input::VibrationAmplificationType::Linear, + .type = Common::Input::VibrationAmplificationType::Linear, }; - return output_devices[device_index]->SetVibration(status) == Input::VibrationError::None; + return output_devices[device_index]->SetVibration(status) == + Common::Input::VibrationError::None; } void EmulatedController::SetLedPattern() { @@ -779,7 +781,7 @@ void EmulatedController::SetLedPattern() { } const LedPattern pattern = GetLedPattern(); - const Input::LedStatus status = { + const Common::Input::LedStatus status = { .led_1 = pattern.position1 != 0, .led_2 = pattern.position2 != 0, .led_3 = pattern.position3 != 0, -- cgit v1.2.3 From 730f07830247cfcdc551c253d30c6717fc16316c Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 31 Oct 2021 10:41:44 -0500 Subject: settings: Fix Debug controller type options --- src/core/hid/emulated_controller.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 49893cdbd..9a1864279 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -77,7 +77,12 @@ void EmulatedController::ReloadFromSettings() { controller.colors_state.fullkey = controller.colors_state.left; - SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + // Other or debug controller should always be a pro controller + if (npad_id_type != NpadIdType::Other) { + SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + } else { + SetNpadType(NpadType::ProController); + } if (player.connected) { Connect(); @@ -606,12 +611,12 @@ void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std: switch (index) { case Settings::NativeTrigger::LTrigger: controller.gc_trigger_state.left = static_cast(trigger.analog.value * HID_TRIGGER_MAX); - controller.npad_button_state.zl.Assign(trigger.pressed); + controller.npad_button_state.zl.Assign(trigger.pressed.value); break; case Settings::NativeTrigger::RTrigger: controller.gc_trigger_state.right = static_cast(trigger.analog.value * HID_TRIGGER_MAX); - controller.npad_button_state.zr.Assign(trigger.pressed); + controller.npad_button_state.zr.Assign(trigger.pressed.value); break; } -- cgit v1.2.3 From 77fa4d4bf60526826ef8b53ee3870f7d2a761976 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 1 Nov 2021 14:17:53 -0600 Subject: second commit lion review --- src/core/hid/emulated_controller.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 9a1864279..7bab00bb1 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -993,10 +993,11 @@ int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { void EmulatedController::DeleteCallback(int key) { std::lock_guard lock{mutex}; - if (!callback_list.contains(key)) { + const auto& iterator = callback_list.find(key); + if (iterator == callback_list.end()) { LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); return; } - callback_list.erase(key); + callback_list.erase(iterator); } } // namespace Core::HID -- cgit v1.2.3 From 136eb9c4c2b2425c2dd45a79cf444dee7170714d Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 1 Nov 2021 19:49:14 -0600 Subject: core/hid: Fully emulate motion from button --- src/core/hid/emulated_controller.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7bab00bb1..2db2b4da0 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -644,6 +644,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std:: }); emulated.UpdateRotation(raw_status.delta_timestamp); emulated.UpdateOrientation(raw_status.delta_timestamp); + force_update_motion = raw_status.force_update; if (is_configuring) { TriggerOnChange(ControllerTriggerType::Motion, false); @@ -653,7 +654,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std:: auto& motion = controller.motion_state[index]; motion.accel = emulated.GetAcceleration(); motion.gyro = emulated.GetGyroscope(); - motion.rotation = emulated.GetGyroscope(); + motion.rotation = emulated.GetRotations(); motion.orientation = emulated.GetOrientation(); motion.is_at_rest = emulated.IsMoving(motion_sensitivity); @@ -962,6 +963,14 @@ NpadGcTriggerState EmulatedController::GetTriggers() const { } MotionState EmulatedController::GetMotions() const { + if (force_update_motion) { + for (auto& device : motion_devices) { + if (!device) { + continue; + } + device->ForceUpdate(); + } + } return controller.motion_state; } -- cgit v1.2.3 From 157e0b85fdd805e02d234dccf1ce578e3159adee Mon Sep 17 00:00:00 2001 From: german77 Date: Tue, 2 Nov 2021 22:50:30 -0600 Subject: core/hid: Prevent Emulated controller from flapping with multiple inputs devices --- src/core/hid/emulated_controller.cpp | 68 ++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 10 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 2db2b4da0..6fe3744fd 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -183,8 +183,11 @@ void EmulatedController::ReloadInput() { if (!button_devices[index]) { continue; } + const auto uuid = Common::UUID{button_params[index].Get("guid", "")}; Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; + [this, index, uuid](Common::Input::CallbackStatus callback) { + SetButton(callback, index, uuid); + }}; button_devices[index]->SetCallback(button_callback); button_devices[index]->ForceUpdate(); } @@ -193,8 +196,11 @@ void EmulatedController::ReloadInput() { if (!stick_devices[index]) { continue; } + const auto uuid = Common::UUID{stick_params[index].Get("guid", "")}; Common::Input::InputCallback stick_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; + [this, index, uuid](Common::Input::CallbackStatus callback) { + SetStick(callback, index, uuid); + }}; stick_devices[index]->SetCallback(stick_callback); stick_devices[index]->ForceUpdate(); } @@ -203,8 +209,11 @@ void EmulatedController::ReloadInput() { if (!trigger_devices[index]) { continue; } + const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")}; Common::Input::InputCallback trigger_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetTrigger(callback, index); }}; + [this, index, uuid](Common::Input::CallbackStatus callback) { + SetTrigger(callback, index, uuid); + }}; trigger_devices[index]->SetCallback(trigger_callback); trigger_devices[index]->ForceUpdate(); } @@ -229,13 +238,18 @@ void EmulatedController::ReloadInput() { motion_devices[index]->ForceUpdate(); } + // Use a common UUID for TAS + const auto tas_uuid = Common::UUID{0x0, 0x7A5}; + // Register TAS devices. No need to force update for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { if (!tas_button_devices[index]) { continue; } Common::Input::InputCallback button_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetButton(callback, index); }}; + [this, index, tas_uuid](Common::Input::CallbackStatus callback) { + SetButton(callback, index, tas_uuid); + }}; tas_button_devices[index]->SetCallback(button_callback); } @@ -244,7 +258,9 @@ void EmulatedController::ReloadInput() { continue; } Common::Input::InputCallback stick_callback{ - [this, index](Common::Input::CallbackStatus callback) { SetStick(callback, index); }}; + [this, index, tas_uuid](Common::Input::CallbackStatus callback) { + SetStick(callback, index, tas_uuid); + }}; tas_stick_devices[index]->SetCallback(stick_callback); } } @@ -423,7 +439,8 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage ReloadInput(); } -void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index, + Common::UUID uuid) { if (index >= controller.button_values.size()) { return; } @@ -432,7 +449,16 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std:: bool value_changed = false; const auto new_status = TransformToButton(callback); auto& current_status = controller.button_values[index]; + + // Only read button values that have the same uuid or are pressed once + if (current_status.uuid != uuid) { + if (!new_status.value) { + return; + } + } + current_status.toggle = new_status.toggle; + current_status.uuid = uuid; // Update button status with current if (!current_status.toggle) { @@ -553,12 +579,23 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std:: TriggerOnChange(ControllerTriggerType::Button, true); } -void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index, + Common::UUID uuid) { if (index >= controller.stick_values.size()) { return; } std::lock_guard lock{mutex}; - controller.stick_values[index] = TransformToStick(callback); + const auto stick_value = TransformToStick(callback); + + // Only read stick values that have the same uuid or are over the threshold to avoid flapping + if (controller.stick_values[index].uuid != uuid) { + if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) { + return; + } + } + + controller.stick_values[index] = stick_value; + controller.stick_values[index].uuid = uuid; if (is_configuring) { controller.analog_stick_state.left = {}; @@ -592,12 +629,23 @@ void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::s TriggerOnChange(ControllerTriggerType::Stick, true); } -void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index) { +void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, + Common::UUID uuid) { if (index >= controller.trigger_values.size()) { return; } std::lock_guard lock{mutex}; - controller.trigger_values[index] = TransformToTrigger(callback); + const auto trigger_value = TransformToTrigger(callback); + + // Only read trigger values that have the same uuid or are pressed once + if (controller.stick_values[index].uuid != uuid) { + if (!trigger_value.pressed.value) { + return; + } + } + + controller.trigger_values[index] = trigger_value; + controller.trigger_values[index].uuid = uuid; if (is_configuring) { controller.gc_trigger_state.left = 0; -- cgit v1.2.3 From 5d0f3540c4b085103afa27d6120ea29e0324a5a2 Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 4 Nov 2021 12:08:54 -0600 Subject: core/hid: Rename NpadType to NpadStyleIndex --- src/core/hid/emulated_controller.cpp | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 6fe3744fd..a200992f2 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -13,38 +13,38 @@ EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type( EmulatedController::~EmulatedController() = default; -NpadType EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { +NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { switch (type) { case Settings::ControllerType::ProController: - return NpadType::ProController; + return NpadStyleIndex::ProController; case Settings::ControllerType::DualJoyconDetached: - return NpadType::JoyconDual; + return NpadStyleIndex::JoyconDual; case Settings::ControllerType::LeftJoycon: - return NpadType::JoyconLeft; + return NpadStyleIndex::JoyconLeft; case Settings::ControllerType::RightJoycon: - return NpadType::JoyconRight; + return NpadStyleIndex::JoyconRight; case Settings::ControllerType::Handheld: - return NpadType::Handheld; + return NpadStyleIndex::Handheld; case Settings::ControllerType::GameCube: - return NpadType::GameCube; + return NpadStyleIndex::GameCube; default: - return NpadType::ProController; + return NpadStyleIndex::ProController; } } -Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadType type) { +Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { switch (type) { - case NpadType::ProController: + case NpadStyleIndex::ProController: return Settings::ControllerType::ProController; - case NpadType::JoyconDual: + case NpadStyleIndex::JoyconDual: return Settings::ControllerType::DualJoyconDetached; - case NpadType::JoyconLeft: + case NpadStyleIndex::JoyconLeft: return Settings::ControllerType::LeftJoycon; - case NpadType::JoyconRight: + case NpadStyleIndex::JoyconRight: return Settings::ControllerType::RightJoycon; - case NpadType::Handheld: + case NpadStyleIndex::Handheld: return Settings::ControllerType::Handheld; - case NpadType::GameCube: + case NpadStyleIndex::GameCube: return Settings::ControllerType::GameCube; default: return Settings::ControllerType::ProController; @@ -79,9 +79,9 @@ void EmulatedController::ReloadFromSettings() { // Other or debug controller should always be a pro controller if (npad_id_type != NpadIdType::Other) { - SetNpadType(MapSettingsTypeToNPad(player.controller_type)); + SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); } else { - SetNpadType(NpadType::ProController); + SetNpadStyleIndex(NpadStyleIndex::ProController); } if (player.connected) { @@ -306,7 +306,7 @@ void EmulatedController::DisableConfiguration() { if (is_connected) { Disconnect(); } - SetNpadType(tmp_npad_type); + SetNpadStyleIndex(tmp_npad_type); } // Apply temporary connected status to the real controller @@ -569,10 +569,10 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std:: } } if (!is_connected) { - if (npad_id_type == NpadIdType::Player1 && npad_type != NpadType::Handheld) { + if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) { Connect(); } - if (npad_id_type == NpadIdType::Handheld && npad_type == NpadType::Handheld) { + if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) { Connect(); } } @@ -896,14 +896,14 @@ NpadIdType EmulatedController::GetNpadIdType() const { return npad_id_type; } -NpadType EmulatedController::GetNpadType(bool get_temporary_value) const { +NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { if (get_temporary_value) { return tmp_npad_type; } return npad_type; } -void EmulatedController::SetNpadType(NpadType npad_type_) { +void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { { std::lock_guard lock{mutex}; -- cgit v1.2.3 From d14e74132ceaa8b5efef8a7d543cb50429cb4fb3 Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 4 Nov 2021 13:08:30 -0600 Subject: settings: Fix controller preview not displaying the correct controller --- src/core/hid/emulated_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index a200992f2..a9038e06f 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -880,7 +880,7 @@ void EmulatedController::Disconnect() { } bool EmulatedController::IsConnected(bool get_temporary_value) const { - if (get_temporary_value) { + if (get_temporary_value && is_configuring) { return tmp_is_connected; } return is_connected; @@ -897,7 +897,7 @@ NpadIdType EmulatedController::GetNpadIdType() const { } NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { - if (get_temporary_value) { + if (get_temporary_value && is_configuring) { return tmp_npad_type; } return npad_type; -- cgit v1.2.3 From 71f9b90dd90c442425900ee16af8b4e39ac54aed Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 8 Nov 2021 20:28:09 -0600 Subject: core/hid: Remove usage of native types, fix a couple of errors with motion --- src/core/hid/emulated_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index a9038e06f..54c1a2324 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -347,7 +347,7 @@ void EmulatedController::RestoreConfig() { } std::vector EmulatedController::GetMappedDevices( - DeviceIndex device_index) const { + EmulatedDeviceIndex device_index) const { std::vector devices; for (const auto& param : button_params) { if (!param.Has("engine")) { @@ -704,7 +704,7 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std:: motion.gyro = emulated.GetGyroscope(); motion.rotation = emulated.GetRotations(); motion.orientation = emulated.GetOrientation(); - motion.is_at_rest = emulated.IsMoving(motion_sensitivity); + motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); TriggerOnChange(ControllerTriggerType::Motion, true); } -- cgit v1.2.3 From 23bf2e3bb6fe0881e28767e768ad9c0a9f851d57 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Mon, 22 Nov 2021 22:15:34 -0600 Subject: service/hid: Finish converting LIFO objects and address some nits --- src/core/hid/emulated_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 54c1a2324..54d4ed93d 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -723,7 +723,7 @@ void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std: bool is_charging = false; bool is_powered = false; - BatteryLevel battery_level = 0; + NpadBatteryLevel battery_level = 0; switch (controller.battery_values[index]) { case Common::Input::BatteryLevel::Charging: is_charging = true; -- cgit v1.2.3 From 182cd9004f75df21979d0edd47910fecbd129b63 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 26 Nov 2021 19:29:08 -0600 Subject: config: Remove vibration configuration --- src/core/hid/emulated_controller.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core/hid/emulated_controller.cpp') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 54d4ed93d..06ae41c3e 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -92,10 +92,11 @@ void EmulatedController::ReloadFromSettings() { ReloadInput(); } + void EmulatedController::LoadDevices() { // TODO(german77): Use more buttons to detect the correct device - const auto left_joycon = button_params[Settings::NativeButton::A]; - const auto right_joycon = button_params[Settings::NativeButton::DRight]; + const auto left_joycon = button_params[Settings::NativeButton::DRight]; + const auto right_joycon = button_params[Settings::NativeButton::A]; // Triggers for GC controllers trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; -- cgit v1.2.3