From a4074001fe2e8ed72c87093f57ec972815661b81 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 20 Dec 2022 13:09:10 -0600 Subject: core: hid: Migrate ring from emulated devices to emulated controller --- src/core/hid/emulated_controller.cpp | 46 +++++++++++++++++++++++++++++ src/core/hid/emulated_controller.h | 35 +++++++++++++++++++++- src/core/hid/emulated_devices.cpp | 46 ----------------------------- src/core/hid/emulated_devices.h | 18 ----------- src/core/hle/service/hid/hidbus/ringcon.cpp | 6 ++-- src/core/hle/service/hid/hidbus/ringcon.h | 4 +-- 6 files changed, 86 insertions(+), 69 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 7a01f3f4c..128101e8c 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -139,6 +139,7 @@ void EmulatedController::LoadDevices() { camera_params = Common::ParamPackage{"engine:camera,camera:1"}; nfc_params = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; + ring_params = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; output_params[LeftIndex] = left_joycon; output_params[RightIndex] = right_joycon; @@ -160,6 +161,7 @@ void EmulatedController::LoadDevices() { std::ranges::transform(battery_params, battery_devices.begin(), Common::Input::CreateInputDevice); camera_devices = Common::Input::CreateInputDevice(camera_params); + ring_analog_device = Common::Input::CreateInputDevice(ring_params); nfc_devices = Common::Input::CreateInputDevice(nfc_params); std::ranges::transform(output_params, output_devices.begin(), Common::Input::CreateOutputDevice); @@ -343,6 +345,13 @@ void EmulatedController::ReloadInput() { camera_devices->ForceUpdate(); } + if (ring_analog_device) { + ring_analog_device->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); }, + }); + } + if (nfc_devices) { if (npad_id_type == NpadIdType::Handheld || npad_id_type == NpadIdType::Player1) { nfc_devices->SetCallback({ @@ -436,6 +445,7 @@ void EmulatedController::UnloadInput() { stick.reset(); } camera_devices.reset(); + ring_analog_device.reset(); nfc_devices.reset(); } @@ -501,6 +511,7 @@ void EmulatedController::SaveCurrentConfig() { for (std::size_t index = 0; index < player.motions.size(); ++index) { player.motions[index] = motion_params[index].Serialize(); } + Settings::values.ringcon_analogs = ring_params.Serialize(); } void EmulatedController::RestoreConfig() { @@ -1005,6 +1016,24 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback TriggerOnChange(ControllerTriggerType::IrSensor, true); } +void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) { + std::unique_lock lock{mutex}; + const auto force_value = TransformToStick(callback); + + controller.ring_analog_value = force_value.x; + + if (is_configuring) { + lock.unlock(); + TriggerOnChange(ControllerTriggerType::RingController, false); + return; + } + + controller.ring_analog_state.force = force_value.x.value; + + lock.unlock(); + TriggerOnChange(ControllerTriggerType::RingController, true); +} + void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { std::unique_lock lock{mutex}; controller.nfc_values = TransformToNfc(callback); @@ -1104,6 +1133,15 @@ bool EmulatedController::SetCameraFormat( camera_format)) == Common::Input::CameraError::None; } +Common::ParamPackage EmulatedController::GetRingParam() const { + return ring_params; +} + +void EmulatedController::SetRingParam(Common::ParamPackage param) { + ring_params = std::move(param); + ReloadInput(); +} + bool EmulatedController::HasNfc() const { const auto& nfc_output_device = output_devices[3]; @@ -1395,6 +1433,10 @@ CameraValues EmulatedController::GetCameraValues() const { return controller.camera_values; } +RingAnalogValue EmulatedController::GetRingSensorValues() const { + return controller.ring_analog_value; +} + HomeButtonState EmulatedController::GetHomeButtons() const { std::scoped_lock lock{mutex}; if (is_configuring) { @@ -1478,6 +1520,10 @@ const CameraState& EmulatedController::GetCamera() const { return controller.camera_state; } +RingSensorForce EmulatedController::GetRingSensorForce() const { + return controller.ring_analog_state; +} + const NfcState& EmulatedController::GetNfc() const { std::scoped_lock lock{mutex}; return controller.nfc_state; diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index a398543a6..aed331a1a 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -38,6 +38,7 @@ using TriggerDevices = using BatteryDevices = std::array, max_emulated_controllers>; using CameraDevices = std::unique_ptr; +using RingAnalogDevice = std::unique_ptr; using NfcDevices = std::unique_ptr; using OutputDevices = std::array, output_devices_size>; @@ -47,6 +48,7 @@ using ControllerMotionParams = std::array; using BatteryParams = std::array; using CameraParams = Common::ParamPackage; +using RingAnalogParams = Common::ParamPackage; using NfcParams = Common::ParamPackage; using OutputParams = std::array; @@ -58,6 +60,7 @@ using ControllerMotionValues = std::array; using BatteryValues = std::array; using CameraValues = Common::Input::CameraStatus; +using RingAnalogValue = Common::Input::AnalogStatus; using NfcValues = Common::Input::NfcStatus; using VibrationValues = std::array; @@ -84,6 +87,10 @@ struct CameraState { std::size_t sample{}; }; +struct RingSensorForce { + f32 force; +}; + struct NfcState { Common::Input::NfcState state{}; std::vector data{}; @@ -116,6 +123,7 @@ struct ControllerStatus { BatteryValues battery_values{}; VibrationValues vibration_values{}; CameraValues camera_values{}; + RingAnalogValue ring_analog_value{}; NfcValues nfc_values{}; // Data for HID serices @@ -129,6 +137,7 @@ struct ControllerStatus { ControllerColors colors_state{}; BatteryLevelState battery_state{}; CameraState camera_state{}; + RingSensorForce ring_analog_state{}; NfcState nfc_state{}; }; @@ -141,6 +150,7 @@ enum class ControllerTriggerType { Battery, Vibration, IrSensor, + RingController, Nfc, Connected, Disconnected, @@ -294,6 +304,9 @@ public: /// Returns the latest camera status from the controller with parameters CameraValues GetCameraValues() const; + /// Returns the latest status of analog input from the ring sensor with parameters + RingAnalogValue GetRingSensorValues() const; + /// Returns the latest status of button input for the hid::HomeButton service HomeButtonState GetHomeButtons() const; @@ -324,6 +337,9 @@ public: /// Returns the latest camera status from the controller const CameraState& GetCamera() const; + /// Returns the latest ringcon force sensor value + RingSensorForce GetRingSensorForce() const; + /// Returns the latest ntag status from the controller const NfcState& GetNfc() const; @@ -353,6 +369,15 @@ public: */ bool SetCameraFormat(Core::IrSensor::ImageTransferProcessorFormat camera_format); + // Returns the current mapped ring device + Common::ParamPackage GetRingParam() const; + + /** + * Updates the current mapped ring device + * @param param ParamPackage with ring sensor data to be mapped + */ + void SetRingParam(Common::ParamPackage param); + /// Returns true if the device has nfc support bool HasNfc() const; @@ -435,7 +460,7 @@ private: /** * Updates the battery status of the controller * @param callback A CallbackStatus containing the battery status - * @param index Button ID of the to be updated + * @param index battery ID of the to be updated */ void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index); @@ -445,6 +470,12 @@ private: */ void SetCamera(const Common::Input::CallbackStatus& callback); + /** + * Updates the ring analog sensor status of the ring controller + * @param callback A CallbackStatus containing the force status + */ + void SetRingAnalog(const Common::Input::CallbackStatus& callback); + /** * Updates the nfc status of the controller * @param callback A CallbackStatus containing the nfc status @@ -485,6 +516,7 @@ private: TriggerParams trigger_params; BatteryParams battery_params; CameraParams camera_params; + RingAnalogParams ring_params; NfcParams nfc_params; OutputParams output_params; @@ -494,6 +526,7 @@ private: TriggerDevices trigger_devices; BatteryDevices battery_devices; CameraDevices camera_devices; + RingAnalogDevice ring_analog_device; NfcDevices nfc_devices; OutputDevices output_devices; diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index e421828d2..836f32c0f 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -14,7 +14,6 @@ EmulatedDevices::EmulatedDevices() = default; EmulatedDevices::~EmulatedDevices() = default; void EmulatedDevices::ReloadFromSettings() { - ring_params = Common::ParamPackage(Settings::values.ringcon_analogs); ReloadInput(); } @@ -66,8 +65,6 @@ void EmulatedDevices::ReloadInput() { key_index++; } - ring_analog_device = Common::Input::CreateInputDevice(ring_params); - for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) { if (!mouse_button_devices[index]) { continue; @@ -122,13 +119,6 @@ void EmulatedDevices::ReloadInput() { }, }); } - - if (ring_analog_device) { - ring_analog_device->SetCallback({ - .on_change = - [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); }, - }); - } } void EmulatedDevices::UnloadInput() { @@ -145,7 +135,6 @@ void EmulatedDevices::UnloadInput() { for (auto& button : keyboard_modifier_devices) { button.reset(); } - ring_analog_device.reset(); } void EmulatedDevices::EnableConfiguration() { @@ -165,7 +154,6 @@ void EmulatedDevices::SaveCurrentConfig() { if (!is_configuring) { return; } - Settings::values.ringcon_analogs = ring_params.Serialize(); } void EmulatedDevices::RestoreConfig() { @@ -175,15 +163,6 @@ void EmulatedDevices::RestoreConfig() { ReloadFromSettings(); } -Common::ParamPackage EmulatedDevices::GetRingParam() const { - return ring_params; -} - -void EmulatedDevices::SetRingParam(Common::ParamPackage param) { - ring_params = std::move(param); - ReloadInput(); -} - void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback, std::size_t index) { if (index >= device_status.keyboard_values.size()) { @@ -430,23 +409,6 @@ void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callbac TriggerOnChange(DeviceTriggerType::Mouse); } -void EmulatedDevices::SetRingAnalog(const Common::Input::CallbackStatus& callback) { - std::lock_guard lock{mutex}; - const auto force_value = TransformToStick(callback); - - device_status.ring_analog_value = force_value.x; - - if (is_configuring) { - device_status.ring_analog_value = {}; - TriggerOnChange(DeviceTriggerType::RingController); - return; - } - - device_status.ring_analog_state.force = force_value.x.value; - - TriggerOnChange(DeviceTriggerType::RingController); -} - KeyboardValues EmulatedDevices::GetKeyboardValues() const { std::scoped_lock lock{mutex}; return device_status.keyboard_values; @@ -462,10 +424,6 @@ MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const { return device_status.mouse_button_values; } -RingAnalogValue EmulatedDevices::GetRingSensorValues() const { - return device_status.ring_analog_value; -} - KeyboardKey EmulatedDevices::GetKeyboard() const { std::scoped_lock lock{mutex}; return device_status.keyboard_state; @@ -491,10 +449,6 @@ AnalogStickState EmulatedDevices::GetMouseWheel() const { return device_status.mouse_wheel_state; } -RingSensorForce EmulatedDevices::GetRingSensorForce() const { - return device_status.ring_analog_state; -} - void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { std::scoped_lock lock{callback_mutex}; for (const auto& poller_pair : callback_list) { diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 4cdbf9dc6..76f9150df 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -26,11 +26,9 @@ using MouseButtonDevices = std::array, Settings::NativeMouseWheel::NumMouseWheels>; using MouseStickDevice = std::unique_ptr; -using RingAnalogDevice = std::unique_ptr; using MouseButtonParams = std::array; -using RingAnalogParams = Common::ParamPackage; using KeyboardValues = std::array; @@ -41,17 +39,12 @@ using MouseButtonValues = using MouseAnalogValues = std::array; using MouseStickValue = Common::Input::TouchStatus; -using RingAnalogValue = Common::Input::AnalogStatus; struct MousePosition { f32 x; f32 y; }; -struct RingSensorForce { - f32 force; -}; - struct DeviceStatus { // Data from input_common KeyboardValues keyboard_values{}; @@ -59,7 +52,6 @@ struct DeviceStatus { MouseButtonValues mouse_button_values{}; MouseAnalogValues mouse_analog_values{}; MouseStickValue mouse_stick_value{}; - RingAnalogValue ring_analog_value{}; // Data for HID serices KeyboardKey keyboard_state{}; @@ -67,7 +59,6 @@ struct DeviceStatus { MouseButton mouse_button_state{}; MousePosition mouse_position_state{}; AnalogStickState mouse_wheel_state{}; - RingSensorForce ring_analog_state{}; }; enum class DeviceTriggerType { @@ -138,9 +129,6 @@ public: /// Returns the latest status of button input from the mouse with parameters MouseButtonValues GetMouseButtonsValues() const; - /// Returns the latest status of analog input from the ring sensor with parameters - RingAnalogValue GetRingSensorValues() const; - /// Returns the latest status of button input from the keyboard KeyboardKey GetKeyboard() const; @@ -156,9 +144,6 @@ public: /// Returns the latest mouse wheel change AnalogStickState GetMouseWheel() const; - /// Returns the latest ringcon force sensor value - RingSensorForce GetRingSensorForce() const; - /** * Adds a callback to the list of events * @param update_callback InterfaceUpdateCallback that will be triggered @@ -224,14 +209,11 @@ private: bool is_configuring{false}; - RingAnalogParams ring_params; - KeyboardDevices keyboard_devices; KeyboardModifierDevices keyboard_modifier_devices; MouseButtonDevices mouse_button_devices; MouseAnalogDevices mouse_analog_devices; MouseStickDevice mouse_stick_device; - RingAnalogDevice ring_analog_device; mutable std::mutex mutex; mutable std::mutex callback_mutex; diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index 57f1a2a26..af776d506 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hid/emulated_devices.h" +#include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" @@ -12,16 +12,18 @@ namespace Service::HID { RingController::RingController(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) : HidbusBase(service_context_) { - input = hid_core_.GetEmulatedDevices(); + input = hid_core_.GetEmulatedController(Core::HID::NpadIdType::Player1); } RingController::~RingController() = default; void RingController::OnInit() { + input->SetPollingMode(Common::Input::PollingMode::Ring); return; } void RingController::OnRelease() { + input->SetPollingMode(Common::Input::PollingMode::Active); return; }; diff --git a/src/core/hle/service/hid/hidbus/ringcon.h b/src/core/hle/service/hid/hidbus/ringcon.h index b37df50ac..845ce85a5 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.h +++ b/src/core/hle/service/hid/hidbus/ringcon.h @@ -9,7 +9,7 @@ #include "core/hle/service/hid/hidbus/hidbus_base.h" namespace Core::HID { -class EmulatedDevices; +class EmulatedController; } // namespace Core::HID namespace Service::HID { @@ -248,6 +248,6 @@ private: .zero = {.value = idle_value, .crc = 225}, }; - Core::HID::EmulatedDevices* input; + Core::HID::EmulatedController* input; }; } // namespace Service::HID -- cgit v1.2.3 From ed5fa10e9729cf55205533f62a428e646aa5ed7c Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 20 Dec 2022 13:23:31 -0600 Subject: core: hid: Enable pulling color data from controllers --- src/core/hid/emulated_controller.cpp | 80 ++++++++++++++++++++++++++++++++++++ src/core/hid/emulated_controller.h | 12 ++++++ src/core/hid/input_converter.cpp | 14 +++++++ src/core/hid/input_converter.h | 10 ++++- src/input_common/drivers/joycon.cpp | 11 ++++- src/input_common/input_engine.cpp | 37 +++++++++++++++++ src/input_common/input_engine.h | 6 +++ src/input_common/input_poller.cpp | 67 ++++++++++++++++++++++++++++++ src/input_common/input_poller.h | 11 +++++ 9 files changed, 246 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 128101e8c..89638cb85 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -93,6 +93,7 @@ void EmulatedController::ReloadFromSettings() { motion_params[index] = Common::ParamPackage(player.motions[index]); } + controller.color_values = {}; controller.colors_state.fullkey = { .body = GetNpadColor(player.body_color_left), .button = GetNpadColor(player.button_color_left), @@ -132,6 +133,11 @@ void EmulatedController::LoadDevices() { trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR]; + color_params[LeftIndex] = left_joycon; + color_params[RightIndex] = right_joycon; + color_params[LeftIndex].Set("color", true); + color_params[RightIndex].Set("color", true); + battery_params[LeftIndex] = left_joycon; battery_params[RightIndex] = right_joycon; battery_params[LeftIndex].Set("battery", true); @@ -160,6 +166,7 @@ void EmulatedController::LoadDevices() { Common::Input::CreateInputDevice); std::ranges::transform(battery_params, battery_devices.begin(), Common::Input::CreateInputDevice); + std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice); camera_devices = Common::Input::CreateInputDevice(camera_params); ring_analog_device = Common::Input::CreateInputDevice(ring_params); nfc_devices = Common::Input::CreateInputDevice(nfc_params); @@ -324,6 +331,19 @@ void EmulatedController::ReloadInput() { battery_devices[index]->ForceUpdate(); } + for (std::size_t index = 0; index < color_devices.size(); ++index) { + if (!color_devices[index]) { + continue; + } + color_devices[index]->SetCallback({ + .on_change = + [this, index](const Common::Input::CallbackStatus& callback) { + SetColors(callback, index); + }, + }); + color_devices[index]->ForceUpdate(); + } + for (std::size_t index = 0; index < motion_devices.size(); ++index) { if (!motion_devices[index]) { continue; @@ -429,6 +449,9 @@ void EmulatedController::UnloadInput() { for (auto& battery : battery_devices) { battery.reset(); } + for (auto& color : color_devices) { + color.reset(); + } for (auto& output : output_devices) { output.reset(); } @@ -458,6 +481,11 @@ void EmulatedController::EnableConfiguration() { void EmulatedController::DisableConfiguration() { is_configuring = false; + // Get Joycon colors before turning on the controller + for (const auto& color_device : color_devices) { + color_device->ForceUpdate(); + } + // Apply temporary npad type to the real controller if (tmp_npad_type != npad_type) { if (is_connected) { @@ -926,6 +954,58 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback TriggerOnChange(ControllerTriggerType::Motion, true); } +void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback, + std::size_t index) { + if (index >= controller.color_values.size()) { + return; + } + std::unique_lock lock{mutex}; + controller.color_values[index] = TransformToColor(callback); + + if (is_configuring) { + lock.unlock(); + TriggerOnChange(ControllerTriggerType::Color, false); + return; + } + + if (controller.color_values[index].body == 0) { + return; + } + + controller.colors_state.fullkey = { + .body = GetNpadColor(controller.color_values[index].body), + .button = GetNpadColor(controller.color_values[index].buttons), + }; + if (npad_type == NpadStyleIndex::ProController) { + controller.colors_state.left = { + .body = GetNpadColor(controller.color_values[index].left_grip), + .button = GetNpadColor(controller.color_values[index].buttons), + }; + controller.colors_state.right = { + .body = GetNpadColor(controller.color_values[index].right_grip), + .button = GetNpadColor(controller.color_values[index].buttons), + }; + } else { + switch (index) { + case LeftIndex: + controller.colors_state.left = { + .body = GetNpadColor(controller.color_values[index].body), + .button = GetNpadColor(controller.color_values[index].buttons), + }; + break; + case RightIndex: + controller.colors_state.right = { + .body = GetNpadColor(controller.color_values[index].body), + .button = GetNpadColor(controller.color_values[index].buttons), + }; + break; + } + } + + lock.unlock(); + TriggerOnChange(ControllerTriggerType::Color, true); +} + void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index) { if (index >= controller.battery_values.size()) { diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index aed331a1a..d044cc36b 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -35,6 +35,8 @@ using ControllerMotionDevices = std::array, Settings::NativeMotion::NumMotions>; using TriggerDevices = std::array, Settings::NativeTrigger::NumTriggers>; +using ColorDevices = + std::array, max_emulated_controllers>; using BatteryDevices = std::array, max_emulated_controllers>; using CameraDevices = std::unique_ptr; @@ -46,6 +48,7 @@ using ButtonParams = std::array; using ControllerMotionParams = std::array; using TriggerParams = std::array; +using ColorParams = std::array; using BatteryParams = std::array; using CameraParams = Common::ParamPackage; using RingAnalogParams = Common::ParamPackage; @@ -457,6 +460,13 @@ private: */ void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index); + /** + * Updates the color status of the controller + * @param callback A CallbackStatus containing the color status + * @param index color ID of the to be updated + */ + void SetColors(const Common::Input::CallbackStatus& callback, std::size_t index); + /** * Updates the battery status of the controller * @param callback A CallbackStatus containing the battery status @@ -515,6 +525,7 @@ private: ControllerMotionParams motion_params; TriggerParams trigger_params; BatteryParams battery_params; + ColorParams color_params; CameraParams camera_params; RingAnalogParams ring_params; NfcParams nfc_params; @@ -525,6 +536,7 @@ private: ControllerMotionDevices motion_devices; TriggerDevices trigger_devices; BatteryDevices battery_devices; + ColorDevices color_devices; CameraDevices camera_devices; RingAnalogDevice ring_analog_device; NfcDevices nfc_devices; diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 502692875..d7e253044 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -304,6 +304,20 @@ Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& cal return nfc; } +Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback) { + Common::Input::BodyColorStatus color{}; + switch (callback.type) { + case Common::Input::InputType::Color: + color = callback.color_status; + break; + default: + LOG_ERROR(Input, "Conversion from type {} to color not implemented", callback.type); + break; + } + + return color; +} + void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { const auto& properties = analog.properties; float& raw_value = analog.raw_value; diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h index b7eb6e660..c51c03e57 100644 --- a/src/core/hid/input_converter.h +++ b/src/core/hid/input_converter.h @@ -88,10 +88,18 @@ Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatu * Converts raw input data into a valid nfc status. * * @param callback Supported callbacks: Nfc. - * @return A valid CameraObject object. + * @return A valid data tag vector. */ Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& callback); +/** + * Converts raw input data into a valid color status. + * + * @param callback Supported callbacks: Color. + * @return A valid Color object. + */ +Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback); + /** * Converts raw analog data into a valid analog value * @param analog An analog object containing raw data and properties diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index 1fca11d34..c6f78c989 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp @@ -335,7 +335,16 @@ void Joycons::OnBatteryUpdate(std::size_t port, Joycon::ControllerType type, } void Joycons::OnColorUpdate(std::size_t port, Joycon::ControllerType type, - const Joycon::Color& value) {} + const Joycon::Color& value) { + const auto identifier = GetIdentifier(port, type); + Common::Input::BodyColorStatus color{ + .body = value.body, + .buttons = value.buttons, + .left_grip = value.left_grip, + .right_grip = value.right_grip, + }; + SetColor(identifier, color); +} void Joycons::OnButtonUpdate(std::size_t port, Joycon::ControllerType type, int id, bool value) { const auto identifier = GetIdentifier(port, type); diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 61cfd0911..91aa96aa7 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp @@ -79,6 +79,17 @@ void InputEngine::SetBattery(const PadIdentifier& identifier, Common::Input::Bat TriggerOnBatteryChange(identifier, value); } +void InputEngine::SetColor(const PadIdentifier& identifier, Common::Input::BodyColorStatus value) { + { + std::scoped_lock lock{mutex}; + ControllerData& controller = controller_list.at(identifier); + if (!configuring) { + controller.color = value; + } + } + TriggerOnColorChange(identifier, value); +} + void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) { { std::scoped_lock lock{mutex}; @@ -176,6 +187,18 @@ Common::Input::BatteryLevel InputEngine::GetBattery(const PadIdentifier& identif return controller.battery; } +Common::Input::BodyColorStatus InputEngine::GetColor(const PadIdentifier& identifier) const { + std::scoped_lock lock{mutex}; + const auto controller_iter = controller_list.find(identifier); + if (controller_iter == controller_list.cend()) { + LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), + identifier.pad, identifier.port); + return {}; + } + const ControllerData& controller = controller_iter->second; + return controller.color; +} + BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const { std::scoped_lock lock{mutex}; const auto controller_iter = controller_list.find(identifier); @@ -328,6 +351,20 @@ void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier, } } +void InputEngine::TriggerOnColorChange(const PadIdentifier& identifier, + [[maybe_unused]] Common::Input::BodyColorStatus value) { + std::scoped_lock lock{mutex_callback}; + for (const auto& poller_pair : callback_list) { + const InputIdentifier& poller = poller_pair.second; + if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Color, 0)) { + continue; + } + if (poller.callback.on_change) { + poller.callback.on_change(); + } + } +} + void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion, const BasicMotion& value) { std::scoped_lock lock{mutex_callback}; diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index 6cbcf5207..6301c5719 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -40,6 +40,7 @@ enum class EngineInputType { Battery, Button, Camera, + Color, HatButton, Motion, Nfc, @@ -199,6 +200,7 @@ public: bool GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const; f32 GetAxis(const PadIdentifier& identifier, int axis) const; Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const; + Common::Input::BodyColorStatus GetColor(const PadIdentifier& identifier) const; BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const; Common::Input::NfcStatus GetNfc(const PadIdentifier& identifier) const; @@ -212,6 +214,7 @@ protected: void SetHatButton(const PadIdentifier& identifier, int button, u8 value); void SetAxis(const PadIdentifier& identifier, int axis, f32 value); void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value); + void SetColor(const PadIdentifier& identifier, Common::Input::BodyColorStatus value); void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value); void SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value); @@ -227,6 +230,7 @@ private: std::unordered_map axes; std::unordered_map motions; Common::Input::BatteryLevel battery{}; + Common::Input::BodyColorStatus color{}; Common::Input::CameraStatus camera{}; Common::Input::NfcStatus nfc{}; }; @@ -235,6 +239,8 @@ private: void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value); void TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value); void TriggerOnBatteryChange(const PadIdentifier& identifier, Common::Input::BatteryLevel value); + void TriggerOnColorChange(const PadIdentifier& identifier, + Common::Input::BodyColorStatus value); void TriggerOnMotionChange(const PadIdentifier& identifier, int motion, const BasicMotion& value); void TriggerOnCameraChange(const PadIdentifier& identifier, diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index fb8be42e2..368ffbdd5 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -498,6 +498,58 @@ private: InputEngine* input_engine; }; +class InputFromColor final : public Common::Input::InputDevice { +public: + explicit InputFromColor(PadIdentifier identifier_, InputEngine* input_engine_) + : identifier(identifier_), input_engine(input_engine_) { + UpdateCallback engine_callback{[this]() { OnChange(); }}; + const InputIdentifier input_identifier{ + .identifier = identifier, + .type = EngineInputType::Color, + .index = 0, + .callback = engine_callback, + }; + last_color_value = {}; + callback_key = input_engine->SetCallback(input_identifier); + } + + ~InputFromColor() override { + input_engine->DeleteCallback(callback_key); + } + + Common::Input::BodyColorStatus GetStatus() const { + return input_engine->GetColor(identifier); + } + + void ForceUpdate() override { + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Color, + .color_status = GetStatus(), + }; + + last_color_value = status.color_status; + TriggerOnChange(status); + } + + void OnChange() { + const Common::Input::CallbackStatus status{ + .type = Common::Input::InputType::Color, + .color_status = GetStatus(), + }; + + if (status.color_status.body != last_color_value.body) { + last_color_value = status.color_status; + TriggerOnChange(status); + } + } + +private: + const PadIdentifier identifier; + int callback_key; + Common::Input::BodyColorStatus last_color_value; + InputEngine* input_engine; +}; + class InputFromMotion final : public Common::Input::InputDevice { public: explicit InputFromMotion(PadIdentifier identifier_, int motion_sensor_, float gyro_threshold_, @@ -966,6 +1018,18 @@ std::unique_ptr InputFactory::CreateBatteryDevice( return std::make_unique(identifier, input_engine.get()); } +std::unique_ptr InputFactory::CreateColorDevice( + const Common::ParamPackage& params) { + const PadIdentifier identifier = { + .guid = Common::UUID{params.Get("guid", "")}, + .port = static_cast(params.Get("port", 0)), + .pad = static_cast(params.Get("pad", 0)), + }; + + input_engine->PreSetController(identifier); + return std::make_unique(identifier, input_engine.get()); +} + std::unique_ptr InputFactory::CreateMotionDevice( Common::ParamPackage params) { const PadIdentifier identifier = { @@ -1053,6 +1117,9 @@ std::unique_ptr InputFactory::Create( if (params.Has("battery")) { return CreateBatteryDevice(params); } + if (params.Has("color")) { + return CreateColorDevice(params); + } if (params.Has("camera")) { return CreateCameraDevice(params); } diff --git a/src/input_common/input_poller.h b/src/input_common/input_poller.h index d7db13ce4..e097e254c 100644 --- a/src/input_common/input_poller.h +++ b/src/input_common/input_poller.h @@ -190,6 +190,17 @@ private: std::unique_ptr CreateBatteryDevice( const Common::ParamPackage& params); + /** + * Creates a color device from the parameters given. + * @param params contains parameters for creating the device: + * - "guid": text string for identifying controllers + * - "port": port of the connected device + * - "pad": slot of the connected controller + * @returns a unique input device with the parameters specified + */ + std::unique_ptr CreateColorDevice( + const Common::ParamPackage& params); + /** * Creates a motion device from the parameters given. * @param params contains parameters for creating the device: -- cgit v1.2.3 From 36d5e0a41151ae39b5fb827c5085142ab4b296a5 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 20 Dec 2022 13:33:45 -0600 Subject: service: hid: Set led pattern and fix color detection --- src/core/hle/service/hid/controllers/npad.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 2f871de31..83b368091 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -272,6 +272,8 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { } break; case Core::HID::NpadStyleIndex::JoyconLeft: + shared_memory->fullkey_color.attribute = ColorAttribute::Ok; + shared_memory->fullkey_color.fullkey = body_colors.left; shared_memory->joycon_color.attribute = ColorAttribute::Ok; shared_memory->joycon_color.left = body_colors.left; shared_memory->battery_level_dual = battery_level.left.battery_level; @@ -285,6 +287,8 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); break; case Core::HID::NpadStyleIndex::JoyconRight: + shared_memory->fullkey_color.attribute = ColorAttribute::Ok; + shared_memory->fullkey_color.fullkey = body_colors.right; shared_memory->joycon_color.attribute = ColorAttribute::Ok; shared_memory->joycon_color.right = body_colors.right; shared_memory->battery_level_right = battery_level.right.battery_level; @@ -332,6 +336,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { controller.is_connected = true; controller.device->Connect(); + controller.device->SetLedPattern(); SignalStyleSetChangedEvent(npad_id); WriteEmptyEntry(controller.shared_memory); } -- cgit v1.2.3 From 6d6b7bdbc327528d155f0422ef096846559844c0 Mon Sep 17 00:00:00 2001 From: german77 Date: Thu, 22 Dec 2022 01:07:46 -0600 Subject: input_common: Implement joycon nfc --- src/core/hid/emulated_controller.cpp | 3 +- src/input_common/CMakeLists.txt | 2 + src/input_common/drivers/joycon.cpp | 4 +- src/input_common/helpers/joycon_driver.cpp | 44 +++ src/input_common/helpers/joycon_driver.h | 24 +- src/input_common/helpers/joycon_protocol/nfc.cpp | 414 +++++++++++++++++++++ src/input_common/helpers/joycon_protocol/nfc.h | 61 +++ .../helpers/joycon_protocol/poller.cpp | 4 + src/input_common/helpers/joycon_protocol/poller.h | 1 + 9 files changed, 544 insertions(+), 13 deletions(-) create mode 100644 src/input_common/helpers/joycon_protocol/nfc.cpp create mode 100644 src/input_common/helpers/joycon_protocol/nfc.h (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 89638cb85..1e4ec4add 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -144,7 +144,8 @@ void EmulatedController::LoadDevices() { battery_params[RightIndex].Set("battery", true); camera_params = Common::ParamPackage{"engine:camera,camera:1"}; - nfc_params = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; + nfc_params = right_joycon; + nfc_params.Set("nfc", true); ring_params = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; output_params[LeftIndex] = left_joycon; diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index addecc9b3..9c901af2a 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -64,6 +64,8 @@ if (ENABLE_SDL2) helpers/joycon_protocol/generic_functions.cpp helpers/joycon_protocol/generic_functions.h helpers/joycon_protocol/joycon_types.h + helpers/joycon_protocol/nfc.cpp + helpers/joycon_protocol/nfc.h helpers/joycon_protocol/poller.cpp helpers/joycon_protocol/poller.h helpers/joycon_protocol/ringcon.cpp diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index 049ecc4f2..29f0dc0c8 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp @@ -388,7 +388,9 @@ void Joycons::OnRingConUpdate(f32 ring_data) { void Joycons::OnAmiiboUpdate(std::size_t port, const std::vector& amiibo_data) { const auto identifier = GetIdentifier(port, Joycon::ControllerType::Right); - SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); + const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved + : Common::Input::NfcState::NewAmiibo; + SetNfc(identifier, {nfc_state, amiibo_data}); } std::shared_ptr Joycons::GetHandle(PadIdentifier identifier) const { diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index c0a03fe2e..c3debffd1 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -5,6 +5,12 @@ #include "common/swap.h" #include "common/thread.h" #include "input_common/helpers/joycon_driver.h" +#include "input_common/helpers/joycon_protocol/calibration.h" +#include "input_common/helpers/joycon_protocol/generic_functions.h" +#include "input_common/helpers/joycon_protocol/nfc.h" +#include "input_common/helpers/joycon_protocol/poller.h" +#include "input_common/helpers/joycon_protocol/ringcon.h" +#include "input_common/helpers/joycon_protocol/rumble.h" namespace InputCommon::Joycon { JoyconDriver::JoyconDriver(std::size_t port_) : port{port_} { @@ -72,6 +78,7 @@ DriverResult JoyconDriver::InitializeDevice() { // Initialize HW Protocols calibration_protocol = std::make_unique(hidapi_handle); generic_protocol = std::make_unique(hidapi_handle); + nfc_protocol = std::make_unique(hidapi_handle); ring_protocol = std::make_unique(hidapi_handle); rumble_protocol = std::make_unique(hidapi_handle); @@ -193,6 +200,25 @@ void JoyconDriver::OnNewData(std::span buffer) { .min_value = ring_calibration.min_value, }; + if (nfc_protocol->IsEnabled()) { + if (amiibo_detected) { + if (!nfc_protocol->HasAmiibo()) { + joycon_poller->updateAmiibo({}); + amiibo_detected = false; + return; + } + } + + if (!amiibo_detected) { + std::vector data(0x21C); + const auto result = nfc_protocol->ScanAmiibo(data); + if (result == DriverResult::Success) { + joycon_poller->updateAmiibo(data); + amiibo_detected = true; + } + } + } + switch (report_mode) { case InputReport::STANDARD_FULL_60HZ: joycon_poller->ReadActiveMode(buffer, motion_status, ring_status); @@ -225,6 +251,24 @@ void JoyconDriver::SetPollingMode() { generic_protocol->EnableImu(false); } + if (nfc_protocol->IsEnabled()) { + amiibo_detected = false; + nfc_protocol->DisableNfc(); + } + + if (nfc_enabled && supported_features.nfc) { + auto result = nfc_protocol->EnableNfc(); + if (result == DriverResult::Success) { + result = nfc_protocol->StartNFCPollingMode(); + } + if (result == DriverResult::Success) { + disable_input_thread = false; + return; + } + nfc_protocol->DisableNfc(); + LOG_ERROR(Input, "Error enabling NFC"); + } + if (ring_protocol->IsEnabled()) { ring_connected = false; ring_protocol->DisableRingCon(); diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index dc5d60221..c9118ee93 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h @@ -8,14 +8,15 @@ #include #include -#include "input_common/helpers/joycon_protocol/calibration.h" -#include "input_common/helpers/joycon_protocol/generic_functions.h" #include "input_common/helpers/joycon_protocol/joycon_types.h" -#include "input_common/helpers/joycon_protocol/poller.h" -#include "input_common/helpers/joycon_protocol/ringcon.h" -#include "input_common/helpers/joycon_protocol/rumble.h" namespace InputCommon::Joycon { +class CalibrationProtocol; +class GenericProtocol; +class NfcProtocol; +class JoyconPoller; +class RingConProtocol; +class RumbleProtocol; class JoyconDriver final { public: @@ -84,17 +85,18 @@ private: SupportedFeatures GetSupportedFeatures(); // Protocol Features - std::unique_ptr calibration_protocol = nullptr; - std::unique_ptr generic_protocol = nullptr; - std::unique_ptr joycon_poller = nullptr; - std::unique_ptr ring_protocol = nullptr; - std::unique_ptr rumble_protocol = nullptr; + std::unique_ptr calibration_protocol; + std::unique_ptr generic_protocol; + std::unique_ptr nfc_protocol; + std::unique_ptr joycon_poller; + std::unique_ptr ring_protocol; + std::unique_ptr rumble_protocol; // Connection status bool is_connected{}; u64 delta_time; std::size_t error_counter{}; - std::shared_ptr hidapi_handle = nullptr; + std::shared_ptr hidapi_handle; std::chrono::time_point last_update; // External device status diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp new file mode 100644 index 000000000..69b2bfe05 --- /dev/null +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp @@ -0,0 +1,414 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "common/logging/log.h" +#include "input_common/helpers/joycon_protocol/nfc.h" + +namespace InputCommon::Joycon { + +NfcProtocol::NfcProtocol(std::shared_ptr handle) : JoyconCommonProtocol(handle) {} + +DriverResult NfcProtocol::EnableNfc() { + LOG_INFO(Input, "Enable NFC"); + DriverResult result{DriverResult::Success}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); + } + if (result == DriverResult::Success) { + result = EnableMCU(true); + } + if (result == DriverResult::Success) { + result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); + } + if (result == DriverResult::Success) { + const MCUConfig config{ + .command = MCUCommand::ConfigureMCU, + .sub_command = MCUSubCommand::SetMCUMode, + .mode = MCUMode::NFC, + .crc = {}, + }; + + result = ConfigureMCU(config); + } + + SetNonBlocking(); + return result; +} + +DriverResult NfcProtocol::DisableNfc() { + LOG_DEBUG(Input, "Disable NFC"); + DriverResult result{DriverResult::Success}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = EnableMCU(false); + } + + is_enabled = false; + + SetNonBlocking(); + return result; +} + +DriverResult NfcProtocol::StartNFCPollingMode() { + LOG_DEBUG(Input, "Start NFC pooling Mode"); + DriverResult result{DriverResult::Success}; + TagFoundData tag_data{}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); + } + if (result == DriverResult::Success) { + result = WaitUntilNfcIsReady(); + } + if (result == DriverResult::Success) { + is_enabled = true; + } + + SetNonBlocking(); + return result; +} + +DriverResult NfcProtocol::ScanAmiibo(std::vector& data) { + LOG_DEBUG(Input, "Start NFC pooling Mode"); + DriverResult result{DriverResult::Success}; + TagFoundData tag_data{}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = StartPolling(tag_data); + } + if (result == DriverResult::Success) { + result = ReadTag(tag_data); + } + if (result == DriverResult::Success) { + result = WaitUntilNfcIsReady(); + } + if (result == DriverResult::Success) { + result = StartPolling(tag_data); + } + if (result == DriverResult::Success) { + result = GetAmiiboData(data); + } + + SetNonBlocking(); + return result; +} + +bool NfcProtocol::HasAmiibo() { + DriverResult result{DriverResult::Success}; + TagFoundData tag_data{}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = StartPolling(tag_data); + } + + SetNonBlocking(); + return result == DriverResult::Success; +} + +DriverResult NfcProtocol::WaitUntilNfcIsReady() { + constexpr std::size_t timeout_limit = 10; + std::vector output; + std::size_t tries = 0; + + do { + auto result = SendStartWaitingRecieveRequest(output); + + if (result != DriverResult::Success) { + return result; + } + if (tries++ > timeout_limit) { + return DriverResult::Timeout; + } + } while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[55] != 0x31 || + output[56] != 0x00); + + return DriverResult::Success; +} + +DriverResult NfcProtocol::StartPolling(TagFoundData& data) { + LOG_DEBUG(Input, "Start Polling for tag"); + constexpr std::size_t timeout_limit = 7; + std::vector output; + std::size_t tries = 0; + + do { + const auto result = SendStartPollingRequest(output); + if (result != DriverResult::Success) { + return result; + } + if (tries++ > timeout_limit) { + return DriverResult::Timeout; + } + } while (output[49] != 0x2a || (output[51] << 8) + output[50] != 0x0500 || output[56] != 0x09); + + data.type = output[62]; + data.uuid.resize(output[64]); + memcpy(data.uuid.data(), output.data() + 65, data.uuid.size()); + + return DriverResult::Success; +} + +DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { + constexpr std::size_t timeout_limit = 10; + std::vector output; + std::size_t tries = 0; + + std::string uuid_string = ""; + for (auto& content : data.uuid) { + uuid_string += " " + fmt::format("{:02x}", content); + } + + LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string); + + tries = 0; + std::size_t ntag_pages = 0; + // Read Tag data +loop1: + while (true) { + auto result = SendReadAmiiboRequest(output, ntag_pages); + + int attempt = 0; + while (1) { + if (attempt != 0) { + result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output); + } + if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) { + return DriverResult::ErrorReadingData; + } + if (output[49] == 0x3a && output[51] == 0x07 && output[52] == 0x01) { + if (data.type != 2) { + goto loop1; + } + switch (output[74]) { + case 0: + ntag_pages = 135; + break; + case 3: + ntag_pages = 45; + break; + case 4: + ntag_pages = 231; + break; + default: + return DriverResult::ErrorReadingData; + } + goto loop1; + } + if (output[49] == 0x2a && output[56] == 0x04) { + // finished + SendStopPollingRequest(output); + return DriverResult::Success; + } + if (output[49] == 0x2a) { + goto loop1; + } + if (attempt++ > 6) { + goto loop1; + } + } + + if (result != DriverResult::Success) { + return result; + } + if (tries++ > timeout_limit) { + return DriverResult::Timeout; + } + } + + return DriverResult::Success; +} + +DriverResult NfcProtocol::GetAmiiboData(std::vector& ntag_data) { + constexpr std::size_t timeout_limit = 10; + std::vector output; + std::size_t tries = 0; + + std::size_t ntag_pages = 135; + std::size_t ntag_buffer_pos = 0; + // Read Tag data +loop1: + while (true) { + auto result = SendReadAmiiboRequest(output, ntag_pages); + + int attempt = 0; + while (1) { + if (attempt != 0) { + result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output); + } + if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) { + return DriverResult::ErrorReadingData; + } + if (output[49] == 0x3a && output[51] == 0x07) { + std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF; + if (output[52] == 0x01) { + memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, + payload_size - 60); + ntag_buffer_pos += payload_size - 60; + } else { + memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size); + } + goto loop1; + } + if (output[49] == 0x2a && output[56] == 0x04) { + LOG_INFO(Input, "Finished reading amiibo"); + return DriverResult::Success; + } + if (output[49] == 0x2a) { + goto loop1; + } + if (attempt++ > 4) { + goto loop1; + } + } + + if (result != DriverResult::Success) { + return result; + } + if (tries++ > timeout_limit) { + return DriverResult::Timeout; + } + } + + return DriverResult::Success; +} + +DriverResult NfcProtocol::SendStartPollingRequest(std::vector& output) { + NFCRequestState request{ + .sub_command = MCUSubCommand::ReadDeviceMode, + .command_argument = NFCReadCommand::StartPolling, + .packet_id = 0x0, + .packet_flag = MCUPacketFlag::LastCommandPacket, + .data_length = sizeof(NFCPollingCommandData), + .nfc_polling = + { + .enable_mifare = 0x01, + .unknown_1 = 0x00, + .unknown_2 = 0x00, + .unknown_3 = 0x2c, + .unknown_4 = 0x01, + }, + .crc = {}, + }; + + std::vector request_data(sizeof(NFCRequestState)); + memcpy(request_data.data(), &request, sizeof(NFCRequestState)); + request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); + return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); +} + +DriverResult NfcProtocol::SendStopPollingRequest(std::vector& output) { + NFCRequestState request{ + .sub_command = MCUSubCommand::ReadDeviceMode, + .command_argument = NFCReadCommand::StopPolling, + .packet_id = 0x0, + .packet_flag = MCUPacketFlag::LastCommandPacket, + .data_length = 0, + .raw_data = {}, + .crc = {}, + }; + + std::vector request_data(sizeof(NFCRequestState)); + memcpy(request_data.data(), &request, sizeof(NFCRequestState)); + request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); + return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); +} + +DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector& output) { + NFCRequestState request{ + .sub_command = MCUSubCommand::ReadDeviceMode, + .command_argument = NFCReadCommand::StartWaitingRecieve, + .packet_id = 0x0, + .packet_flag = MCUPacketFlag::LastCommandPacket, + .data_length = 0, + .raw_data = {}, + .crc = {}, + }; + + std::vector request_data(sizeof(NFCRequestState)); + memcpy(request_data.data(), &request, sizeof(NFCRequestState)); + request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); + return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); +} + +DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector& output, std::size_t ntag_pages) { + NFCRequestState request{ + .sub_command = MCUSubCommand::ReadDeviceMode, + .command_argument = NFCReadCommand::Ntag, + .packet_id = 0x0, + .packet_flag = MCUPacketFlag::LastCommandPacket, + .data_length = sizeof(NFCReadCommandData), + .nfc_read = + { + .unknown = 0xd0, + .uuid_length = 0x07, + .unknown_2 = 0x00, + .uid = {}, + .tag_type = NFCTagType::AllTags, + .read_block = GetReadBlockCommand(ntag_pages), + }, + .crc = {}, + }; + + std::vector request_data(sizeof(NFCRequestState)); + memcpy(request_data.data(), &request, sizeof(NFCRequestState)); + request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); + return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); +} + +NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const { + if (pages == 0) { + return { + .block_count = 1, + }; + } + + if (pages == 45) { + return { + .block_count = 1, + .blocks = + { + NFCReadBlock{0x00, 0x2C}, + }, + }; + } + + if (pages == 135) { + return { + .block_count = 3, + .blocks = + { + NFCReadBlock{0x00, 0x3b}, + {0x3c, 0x77}, + {0x78, 0x86}, + }, + }; + } + + if (pages == 231) { + return { + .block_count = 4, + .blocks = + { + NFCReadBlock{0x00, 0x3b}, + {0x3c, 0x77}, + {0x78, 0x83}, + {0xb4, 0xe6}, + }, + }; + } + + return {}; +} + +bool NfcProtocol::IsEnabled() { + return is_enabled; +} + +} // namespace InputCommon::Joycon diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h new file mode 100644 index 000000000..0ede03d50 --- /dev/null +++ b/src/input_common/helpers/joycon_protocol/nfc.h @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Based on dkms-hid-nintendo implementation, CTCaer joycon toolkit and dekuNukem reverse +// engineering https://github.com/nicman23/dkms-hid-nintendo/blob/master/src/hid-nintendo.c +// https://github.com/CTCaer/jc_toolkit +// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering + +#pragma once + +#include + +#include "input_common/helpers/joycon_protocol/common_protocol.h" +#include "input_common/helpers/joycon_protocol/joycon_types.h" + +namespace InputCommon::Joycon { + +class NfcProtocol final : private JoyconCommonProtocol { +public: + NfcProtocol(std::shared_ptr handle); + + DriverResult EnableNfc(); + + DriverResult DisableNfc(); + + DriverResult StartNFCPollingMode(); + + DriverResult ScanAmiibo(std::vector& data); + + bool HasAmiibo(); + + bool IsEnabled(); + +private: + struct TagFoundData { + u8 type; + std::vector uuid; + }; + + DriverResult WaitUntilNfcIsReady(); + + DriverResult StartPolling(TagFoundData& data); + + DriverResult ReadTag(const TagFoundData& data); + + DriverResult GetAmiiboData(std::vector& data); + + DriverResult SendStartPollingRequest(std::vector& output); + + DriverResult SendStopPollingRequest(std::vector& output); + + DriverResult SendStartWaitingRecieveRequest(std::vector& output); + + DriverResult SendReadAmiiboRequest(std::vector& output, std::size_t ntag_pages); + + NFCReadBlockCommand GetReadBlockCommand(std::size_t pages) const; + + bool is_enabled{}; +}; + +} // namespace InputCommon::Joycon diff --git a/src/input_common/helpers/joycon_protocol/poller.cpp b/src/input_common/helpers/joycon_protocol/poller.cpp index cb76e1e06..fd05d98f3 100644 --- a/src/input_common/helpers/joycon_protocol/poller.cpp +++ b/src/input_common/helpers/joycon_protocol/poller.cpp @@ -74,6 +74,10 @@ void JoyconPoller::UpdateColor(const Color& color) { callbacks.on_color_data(color); } +void JoyconPoller::updateAmiibo(const std::vector& amiibo_data) { + callbacks.on_amiibo_data(amiibo_data); +} + void JoyconPoller::UpdateRing(s16 value, const RingStatus& ring_status) { float normalized_value = static_cast(value - ring_status.default_value); if (normalized_value > 0) { diff --git a/src/input_common/helpers/joycon_protocol/poller.h b/src/input_common/helpers/joycon_protocol/poller.h index 68b14b8ba..c40fc7bca 100644 --- a/src/input_common/helpers/joycon_protocol/poller.h +++ b/src/input_common/helpers/joycon_protocol/poller.h @@ -36,6 +36,7 @@ public: void UpdateColor(const Color& color); void UpdateRing(s16 value, const RingStatus& ring_status); + void updateAmiibo(const std::vector& amiibo_data); private: void UpdateActiveLeftPadInput(const InputReportActive& input, -- cgit v1.2.3 From 1c08d532e059fab603facb43f758f37fe148c1fc Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 22 Dec 2022 20:47:51 -0600 Subject: core: hid: Fix input regressions --- src/core/hid/emulated_controller.cpp | 55 ++++++++++++++-------- src/core/hid/emulated_controller.h | 12 +++-- src/core/hle/service/hid/controllers/npad.cpp | 1 + src/core/hle/service/hid/hidbus.cpp | 24 +++++----- src/input_common/helpers/joycon_driver.cpp | 2 +- .../helpers/joycon_protocol/ringcon.cpp | 3 -- 6 files changed, 56 insertions(+), 41 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 1e4ec4add..1ed57f949 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -107,6 +107,8 @@ void EmulatedController::ReloadFromSettings() { .button = GetNpadColor(player.button_color_right), }; + ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs); + // Other or debug controller should always be a pro controller if (npad_id_type != NpadIdType::Other) { SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); @@ -144,14 +146,15 @@ void EmulatedController::LoadDevices() { battery_params[RightIndex].Set("battery", true); camera_params = Common::ParamPackage{"engine:camera,camera:1"}; - nfc_params = right_joycon; - nfc_params.Set("nfc", true); - ring_params = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; + ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; + nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; + nfc_params[1] = right_joycon; + nfc_params[1].Set("nfc", true); output_params[LeftIndex] = left_joycon; output_params[RightIndex] = right_joycon; output_params[2] = camera_params; - output_params[3] = nfc_params; + output_params[3] = nfc_params[0]; output_params[LeftIndex].Set("output", true); output_params[RightIndex].Set("output", true); output_params[2].Set("output", true); @@ -169,8 +172,9 @@ void EmulatedController::LoadDevices() { Common::Input::CreateInputDevice); std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice); camera_devices = Common::Input::CreateInputDevice(camera_params); - ring_analog_device = Common::Input::CreateInputDevice(ring_params); - nfc_devices = Common::Input::CreateInputDevice(nfc_params); + std::ranges::transform(ring_params, ring_analog_devices.begin(), + Common::Input::CreateInputDevice); + std::ranges::transform(nfc_params, nfc_devices.begin(), Common::Input::CreateInputDevice); std::ranges::transform(output_params, output_devices.begin(), Common::Input::CreateOutputDevice); @@ -366,21 +370,26 @@ void EmulatedController::ReloadInput() { camera_devices->ForceUpdate(); } - if (ring_analog_device) { - ring_analog_device->SetCallback({ + for (std::size_t index = 0; index < ring_analog_devices.size(); ++index) { + if (!ring_analog_devices[index]) { + continue; + } + ring_analog_devices[index]->SetCallback({ .on_change = [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); }, }); + ring_analog_devices[index]->ForceUpdate(); } - if (nfc_devices) { - if (npad_id_type == NpadIdType::Handheld || npad_id_type == NpadIdType::Player1) { - nfc_devices->SetCallback({ - .on_change = - [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); }, - }); - nfc_devices->ForceUpdate(); + for (std::size_t index = 0; index < nfc_devices.size(); ++index) { + if (!nfc_devices[index]) { + continue; } + nfc_devices[index]->SetCallback({ + .on_change = + [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); }, + }); + nfc_devices[index]->ForceUpdate(); } // Register TAS devices. No need to force update @@ -469,8 +478,12 @@ void EmulatedController::UnloadInput() { stick.reset(); } camera_devices.reset(); - ring_analog_device.reset(); - nfc_devices.reset(); + for (auto& ring : ring_analog_devices) { + ring.reset(); + } + for (auto& nfc : nfc_devices) { + nfc.reset(); + } } void EmulatedController::EnableConfiguration() { @@ -540,7 +553,9 @@ void EmulatedController::SaveCurrentConfig() { for (std::size_t index = 0; index < player.motions.size(); ++index) { player.motions[index] = motion_params[index].Serialize(); } - Settings::values.ringcon_analogs = ring_params.Serialize(); + if (npad_id_type == NpadIdType::Player1) { + Settings::values.ringcon_analogs = ring_params[0].Serialize(); + } } void EmulatedController::RestoreConfig() { @@ -1215,11 +1230,11 @@ bool EmulatedController::SetCameraFormat( } Common::ParamPackage EmulatedController::GetRingParam() const { - return ring_params; + return ring_params[0]; } void EmulatedController::SetRingParam(Common::ParamPackage param) { - ring_params = std::move(param); + ring_params[0] = std::move(param); ReloadInput(); } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index d044cc36b..c517aa5d7 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -40,8 +40,10 @@ using ColorDevices = using BatteryDevices = std::array, max_emulated_controllers>; using CameraDevices = std::unique_ptr; -using RingAnalogDevice = std::unique_ptr; -using NfcDevices = std::unique_ptr; +using RingAnalogDevices = + std::array, max_emulated_controllers>; +using NfcDevices = + std::array, max_emulated_controllers>; using OutputDevices = std::array, output_devices_size>; using ButtonParams = std::array; @@ -51,8 +53,8 @@ using TriggerParams = std::array; using BatteryParams = std::array; using CameraParams = Common::ParamPackage; -using RingAnalogParams = Common::ParamPackage; -using NfcParams = Common::ParamPackage; +using RingAnalogParams = std::array; +using NfcParams = std::array; using OutputParams = std::array; using ButtonValues = std::array; @@ -538,7 +540,7 @@ private: BatteryDevices battery_devices; ColorDevices color_devices; CameraDevices camera_devices; - RingAnalogDevice ring_analog_device; + RingAnalogDevices ring_analog_devices; NfcDevices nfc_devices; OutputDevices output_devices; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 83b368091..fe5bf94d2 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -337,6 +337,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { controller.is_connected = true; controller.device->Connect(); controller.device->SetLedPattern(); + controller.device->SetPollingMode(Common::Input::PollingMode::Active); SignalStyleSetChangedEvent(npad_id); WriteEmptyEntry(controller.shared_memory); } diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index e5e50845f..17252a84a 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp @@ -297,13 +297,13 @@ void HidBus::EnableExternalDevice(Kernel::HLERequestContext& ctx) { const auto parameters{rp.PopRaw()}; - LOG_INFO(Service_HID, - "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " - "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}", - parameters.enable, parameters.bus_handle.abstracted_pad_id, - parameters.bus_handle.bus_type, parameters.bus_handle.internal_index, - parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval, - parameters.applet_resource_user_id); + LOG_DEBUG(Service_HID, + "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " + "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}", + parameters.enable, parameters.bus_handle.abstracted_pad_id, + parameters.bus_handle.bus_type, parameters.bus_handle.internal_index, + parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval, + parameters.applet_resource_user_id); const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle); @@ -326,11 +326,11 @@ void HidBus::GetExternalDeviceId(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto bus_handle_{rp.PopRaw()}; - LOG_INFO(Service_HID, - "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " - "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid); + LOG_DEBUG(Service_HID, + "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " + "is_valid={}", + bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index, + bus_handle_.player_number, bus_handle_.is_valid); const auto device_index = GetDeviceIndexFromHandle(bus_handle_); diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index c3debffd1..db9ff4875 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -396,7 +396,7 @@ DriverResult JoyconDriver::SetActiveMode() { DriverResult JoyconDriver::SetNfcMode() { std::scoped_lock lock{mutex}; - motion_enabled = false; + motion_enabled = true; hidbus_enabled = false; nfc_enabled = true; passive_enabled = false; diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp index 2d137b85d..47769f344 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.cpp +++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp @@ -55,9 +55,6 @@ DriverResult RingConProtocol::StartRingconPolling() { DriverResult result{DriverResult::Success}; SetBlocking(); - if (result == DriverResult::Success) { - result = WaitSetMCUMode(ReportMode::STANDARD_FULL_60HZ, MCUMode::Standby); - } if (result == DriverResult::Success) { result = IsRingConnected(is_connected); } -- cgit v1.2.3 From e1a3bda4d9881cb99c36b64733b814a3bb437f13 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 23 Dec 2022 08:32:02 -0600 Subject: Address review comments --- src/core/hid/input_converter.cpp | 6 ++---- src/input_common/drivers/joycon.cpp | 2 +- src/input_common/helpers/joycon_driver.cpp | 2 +- src/input_common/helpers/joycon_protocol/calibration.cpp | 10 +++------- src/input_common/helpers/joycon_protocol/calibration.h | 2 +- .../helpers/joycon_protocol/common_protocol.cpp | 6 +++--- .../helpers/joycon_protocol/generic_functions.cpp | 12 ++++++------ .../helpers/joycon_protocol/generic_functions.h | 2 +- src/input_common/helpers/joycon_protocol/nfc.cpp | 9 +++++---- src/input_common/helpers/joycon_protocol/nfc.h | 4 ++-- src/input_common/helpers/joycon_protocol/ringcon.cpp | 16 ++++++++-------- src/input_common/helpers/joycon_protocol/ringcon.h | 4 ++-- src/input_common/helpers/joycon_protocol/rumble.cpp | 13 ++++++++----- src/input_common/helpers/joycon_protocol/rumble.h | 2 +- 14 files changed, 44 insertions(+), 46 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index d7e253044..3f7b8c090 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -305,17 +305,15 @@ Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& cal } Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback) { - Common::Input::BodyColorStatus color{}; switch (callback.type) { case Common::Input::InputType::Color: - color = callback.color_status; + return callback.color_status; break; default: LOG_ERROR(Input, "Conversion from type {} to color not implemented", callback.type); + return {}; break; } - - return color; } void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index 29f0dc0c8..696a6db39 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp @@ -316,7 +316,7 @@ void Joycons::OnBatteryUpdate(std::size_t port, Joycon::ControllerType type, return; } - Common::Input::BatteryLevel battery{value.status.Value()}; + Common::Input::BatteryLevel battery{}; switch (value.status) { case 0: battery = Common::Input::BatteryLevel::Empty; diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index db9ff4875..8982a2397 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -465,7 +465,7 @@ void JoyconDriver::SetCallbacks(const Joycon::JoyconCallbacks& callbacks) { Joycon::DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, ControllerType& controller_type) { - std::array, 4> supported_devices{ + static constexpr std::array, 4> supported_devices{ std::pair{0x2006, Joycon::ControllerType::Left}, {0x2007, Joycon::ControllerType::Right}, {0x2009, Joycon::ControllerType::Pro}, diff --git a/src/input_common/helpers/joycon_protocol/calibration.cpp b/src/input_common/helpers/joycon_protocol/calibration.cpp index ce1ff7061..cd30ab869 100644 --- a/src/input_common/helpers/joycon_protocol/calibration.cpp +++ b/src/input_common/helpers/joycon_protocol/calibration.cpp @@ -9,7 +9,7 @@ namespace InputCommon::Joycon { CalibrationProtocol::CalibrationProtocol(std::shared_ptr handle) - : JoyconCommonProtocol(handle) {} + : JoyconCommonProtocol(std::move(handle)) {} DriverResult CalibrationProtocol::GetLeftJoyStickCalibration(JoyStickCalibration& calibration) { std::vector buffer; @@ -136,12 +136,8 @@ DriverResult CalibrationProtocol::GetRingCalibration(RingCalibration& calibratio ring_data_min = current_value - 800; ring_data_default = current_value; } - if (ring_data_max < current_value) { - ring_data_max = current_value; - } - if (ring_data_min > current_value) { - ring_data_min = current_value; - } + ring_data_max = std::max(ring_data_max, current_value); + ring_data_min = std::min(ring_data_min, current_value); calibration = { .default_value = ring_data_default, .max_value = ring_data_max, diff --git a/src/input_common/helpers/joycon_protocol/calibration.h b/src/input_common/helpers/joycon_protocol/calibration.h index 32ddef4b8..afb52a36a 100644 --- a/src/input_common/helpers/joycon_protocol/calibration.h +++ b/src/input_common/helpers/joycon_protocol/calibration.h @@ -24,7 +24,7 @@ namespace InputCommon::Joycon { /// Driver functions related to retrieving calibration data from the device class CalibrationProtocol final : private JoyconCommonProtocol { public: - CalibrationProtocol(std::shared_ptr handle); + explicit CalibrationProtocol(std::shared_ptr handle); /** * Sends a request to obtain the left stick calibration from memory diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index 43a036e02..a4d08fdaf 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp @@ -6,7 +6,7 @@ namespace InputCommon::Joycon { JoyconCommonProtocol::JoyconCommonProtocol(std::shared_ptr hidapi_handle_) - : hidapi_handle{hidapi_handle_} {} + : hidapi_handle{std::move(hidapi_handle_)} {} u8 JoyconCommonProtocol::GetCounter() { hidapi_handle->packet_counter = (hidapi_handle->packet_counter + 1) & 0x0F; @@ -256,7 +256,7 @@ DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMod } // crc-8-ccitt / polynomial 0x07 look up table -static constexpr uint8_t mcu_crc8_table[256] = { +constexpr std::array mcu_crc8_table = { 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, @@ -278,7 +278,7 @@ u8 JoyconCommonProtocol::CalculateMCU_CRC8(u8* buffer, u8 size) const { u8 crc8 = 0x0; for (int i = 0; i < size; ++i) { - crc8 = mcu_crc8_table[(u8)(crc8 ^ buffer[i])]; + crc8 = mcu_crc8_table[static_cast(crc8 ^ buffer[i])]; } return crc8; } diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.cpp b/src/input_common/helpers/joycon_protocol/generic_functions.cpp index 829f7625d..cbd9ff4f8 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.cpp +++ b/src/input_common/helpers/joycon_protocol/generic_functions.cpp @@ -7,7 +7,7 @@ namespace InputCommon::Joycon { GenericProtocol::GenericProtocol(std::shared_ptr handle) - : JoyconCommonProtocol(handle) {} + : JoyconCommonProtocol(std::move(handle)) {} DriverResult GenericProtocol::EnablePassiveMode() { SetBlocking(); @@ -43,7 +43,7 @@ DriverResult GenericProtocol::GetControllerType(ControllerType& controller_type) } DriverResult GenericProtocol::EnableImu(bool enable) { - const std::vector buffer{static_cast(enable ? 1 : 0)}; + const std::array buffer{static_cast(enable ? 1 : 0)}; std::vector output; SetBlocking(); const auto result = SendSubCommand(SubCommand::ENABLE_IMU, buffer, output); @@ -54,8 +54,8 @@ DriverResult GenericProtocol::EnableImu(bool enable) { DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, AccelerometerSensitivity asen, AccelerometerPerformance afrec) { - const std::vector buffer{static_cast(gsen), static_cast(asen), - static_cast(gfrec), static_cast(afrec)}; + const std::array buffer{static_cast(gsen), static_cast(asen), + static_cast(gfrec), static_cast(afrec)}; std::vector output; SetBlocking(); const auto result = SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer, output); @@ -115,7 +115,7 @@ DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) { } DriverResult GenericProtocol::SetHomeLight() { - const std::vector buffer{0x0f, 0xf0, 0x00}; + static constexpr std::array buffer{0x0f, 0xf0, 0x00}; std::vector output; SetBlocking(); @@ -130,7 +130,7 @@ DriverResult GenericProtocol::SetLedBusy() { } DriverResult GenericProtocol::SetLedPattern(u8 leds) { - const std::vector buffer{leds}; + const std::array buffer{leds}; std::vector output; SetBlocking(); diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.h b/src/input_common/helpers/joycon_protocol/generic_functions.h index c3e2ccadc..239bb7dbf 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.h +++ b/src/input_common/helpers/joycon_protocol/generic_functions.h @@ -16,7 +16,7 @@ namespace InputCommon::Joycon { /// Joycon driver functions that easily implemented class GenericProtocol final : private JoyconCommonProtocol { public: - GenericProtocol(std::shared_ptr handle); + explicit GenericProtocol(std::shared_ptr handle); /// Enables passive mode. This mode only sends button data on change. Sticks will return digital /// data instead of analog. Motion will be disabled diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index 69b2bfe05..8755e310b 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp @@ -7,7 +7,8 @@ namespace InputCommon::Joycon { -NfcProtocol::NfcProtocol(std::shared_ptr handle) : JoyconCommonProtocol(handle) {} +NfcProtocol::NfcProtocol(std::shared_ptr handle) + : JoyconCommonProtocol(std::move(handle)) {} DriverResult NfcProtocol::EnableNfc() { LOG_INFO(Input, "Enable NFC"); @@ -160,9 +161,9 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { std::vector output; std::size_t tries = 0; - std::string uuid_string = ""; + std::string uuid_string; for (auto& content : data.uuid) { - uuid_string += " " + fmt::format("{:02x}", content); + uuid_string += fmt::format(" {:02x}", content); } LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string); @@ -407,7 +408,7 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const { return {}; } -bool NfcProtocol::IsEnabled() { +bool NfcProtocol::IsEnabled() const { return is_enabled; } diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h index 0ede03d50..5cb0e5a65 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.h +++ b/src/input_common/helpers/joycon_protocol/nfc.h @@ -17,7 +17,7 @@ namespace InputCommon::Joycon { class NfcProtocol final : private JoyconCommonProtocol { public: - NfcProtocol(std::shared_ptr handle); + explicit NfcProtocol(std::shared_ptr handle); DriverResult EnableNfc(); @@ -29,7 +29,7 @@ public: bool HasAmiibo(); - bool IsEnabled(); + bool IsEnabled() const; private: struct TagFoundData { diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp index 47769f344..8adad57dd 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.cpp +++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp @@ -7,7 +7,7 @@ namespace InputCommon::Joycon { RingConProtocol::RingConProtocol(std::shared_ptr handle) - : JoyconCommonProtocol(handle) {} + : JoyconCommonProtocol(std::move(handle)) {} DriverResult RingConProtocol::EnableRingCon() { LOG_DEBUG(Input, "Enable Ringcon"); @@ -78,7 +78,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { is_connected = false; do { - std::vector empty_data(0); + std::array empty_data{}; const auto result = SendSubCommand(SubCommand::UNKNOWN_RINGCON, empty_data, output); if (result != DriverResult::Success) { @@ -101,11 +101,11 @@ DriverResult RingConProtocol::ConfigureRing() { std::vector output; std::size_t tries = 0; + static constexpr std::array ring_config{ + 0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16, 0xED, 0x34, 0x36, + 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; do { - std::vector ring_config{0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16, - 0xED, 0x34, 0x36, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6, - 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36}; result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config, output); if (result != DriverResult::Success) { @@ -116,13 +116,13 @@ DriverResult RingConProtocol::ConfigureRing() { } } while (output[14] != 0x5C); - std::vector ringcon_data{0x04, 0x01, 0x01, 0x02}; + static constexpr std::array ringcon_data{0x04, 0x01, 0x01, 0x02}; result = SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data, output); return result; } -bool RingConProtocol::IsEnabled() { +bool RingConProtocol::IsEnabled() const { return is_enabled; } diff --git a/src/input_common/helpers/joycon_protocol/ringcon.h b/src/input_common/helpers/joycon_protocol/ringcon.h index 0c25de23e..6e858f3fc 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.h +++ b/src/input_common/helpers/joycon_protocol/ringcon.h @@ -17,7 +17,7 @@ namespace InputCommon::Joycon { class RingConProtocol final : private JoyconCommonProtocol { public: - RingConProtocol(std::shared_ptr handle); + explicit RingConProtocol(std::shared_ptr handle); DriverResult EnableRingCon(); @@ -25,7 +25,7 @@ public: DriverResult StartRingconPolling(); - bool IsEnabled(); + bool IsEnabled() const; private: DriverResult IsRingConnected(bool& is_connected); diff --git a/src/input_common/helpers/joycon_protocol/rumble.cpp b/src/input_common/helpers/joycon_protocol/rumble.cpp index 17ee38863..fad67a94b 100644 --- a/src/input_common/helpers/joycon_protocol/rumble.cpp +++ b/src/input_common/helpers/joycon_protocol/rumble.cpp @@ -1,17 +1,20 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include + #include "common/logging/log.h" #include "input_common/helpers/joycon_protocol/rumble.h" namespace InputCommon::Joycon { RumbleProtocol::RumbleProtocol(std::shared_ptr handle) - : JoyconCommonProtocol(handle) {} + : JoyconCommonProtocol(std::move(handle)) {} DriverResult RumbleProtocol::EnableRumble(bool is_enabled) { LOG_DEBUG(Input, "Enable Rumble"); - const std::vector buffer{static_cast(is_enabled ? 1 : 0)}; + const std::array buffer{static_cast(is_enabled ? 1 : 0)}; std::vector output; SetBlocking(); const auto result = SendSubCommand(SubCommand::ENABLE_VIBRATION, buffer, output); @@ -20,7 +23,7 @@ DriverResult RumbleProtocol::EnableRumble(bool is_enabled) { } DriverResult RumbleProtocol::SendVibration(const VibrationValue& vibration) { - std::vector buffer(sizeof(DefaultVibrationBuffer)); + std::array buffer{}; if (vibration.high_amplitude <= 0.0f && vibration.low_amplitude <= 0.0f) { return SendVibrationReport(DefaultVibrationBuffer); @@ -66,7 +69,7 @@ u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const { /* More information about these values can be found here: * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md */ - constexpr std::array, 101> high_fequency_amplitude{ + static constexpr std::array, 101> high_fequency_amplitude{ std::pair{0.0f, 0x0}, {0.01f, 0x2}, {0.012f, 0x4}, @@ -183,7 +186,7 @@ u16 RumbleProtocol::EncodeLowAmplitude(f32 amplitude) const { /* More information about these values can be found here: * https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md */ - constexpr std::array, 101> high_fequency_amplitude{ + static constexpr std::array, 101> high_fequency_amplitude{ std::pair{0.0f, 0x0040}, {0.01f, 0x8040}, {0.012f, 0x0041}, diff --git a/src/input_common/helpers/joycon_protocol/rumble.h b/src/input_common/helpers/joycon_protocol/rumble.h index 7d0329f03..6c12b7925 100644 --- a/src/input_common/helpers/joycon_protocol/rumble.h +++ b/src/input_common/helpers/joycon_protocol/rumble.h @@ -17,7 +17,7 @@ namespace InputCommon::Joycon { class RumbleProtocol final : private JoyconCommonProtocol { public: - RumbleProtocol(std::shared_ptr handle); + explicit RumbleProtocol(std::shared_ptr handle); DriverResult EnableRumble(bool is_enabled); -- cgit v1.2.3 From 527dad70976a158e94defc51707347e064a31099 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 26 Dec 2022 11:11:01 -0600 Subject: input_common: Use DriverResult on all engines --- src/common/input.h | 46 ++++++++++------------ src/core/hid/emulated_controller.cpp | 10 ++--- src/input_common/drivers/camera.cpp | 4 +- src/input_common/drivers/camera.h | 4 +- src/input_common/drivers/gc_adapter.cpp | 6 +-- src/input_common/drivers/gc_adapter.h | 2 +- src/input_common/drivers/joycon.cpp | 41 +++++++++---------- src/input_common/drivers/joycon.h | 12 +++--- src/input_common/drivers/sdl_driver.cpp | 4 +- src/input_common/drivers/sdl_driver.h | 2 +- src/input_common/drivers/virtual_amiibo.cpp | 4 +- src/input_common/drivers/virtual_amiibo.h | 2 +- src/input_common/helpers/joycon_driver.cpp | 26 ++++++------ src/input_common/helpers/joycon_driver.h | 10 ++--- .../helpers/joycon_protocol/joycon_types.h | 1 + src/input_common/input_engine.h | 19 +++++---- src/input_common/input_poller.cpp | 11 +++--- 17 files changed, 100 insertions(+), 104 deletions(-) (limited to 'src/core') diff --git a/src/common/input.h b/src/common/input.h index 1e5ba038d..d61cd7ca8 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -64,20 +64,19 @@ enum class CameraFormat { None, }; -// Vibration reply from the controller -enum class VibrationError { - None, - NotSupported, - Disabled, +// Different results that can happen from a device request +enum class DriverResult { + Success, + WrongReply, + Timeout, + UnsupportedControllerType, + HandleInUse, + ErrorReadingData, + ErrorWritingData, + NoDeviceDetected, InvalidHandle, - Unknown, -}; - -// Polling mode reply from the controller -enum class PollingError { - None, NotSupported, - InvalidHandle, + Disabled, Unknown, }; @@ -94,13 +93,6 @@ enum class NfcState { Unknown, }; -// Ir camera reply from the controller -enum class CameraError { - None, - NotSupported, - Unknown, -}; - // Hint for amplification curve to be used enum class VibrationAmplificationType { Linear, @@ -336,22 +328,24 @@ class OutputDevice { public: virtual ~OutputDevice() = default; - virtual void SetLED([[maybe_unused]] const LedStatus& led_status) {} + virtual DriverResult SetLED([[maybe_unused]] const LedStatus& led_status) { + return DriverResult::NotSupported; + } - virtual VibrationError SetVibration([[maybe_unused]] const VibrationStatus& vibration_status) { - return VibrationError::NotSupported; + virtual DriverResult SetVibration([[maybe_unused]] const VibrationStatus& vibration_status) { + return DriverResult::NotSupported; } virtual bool IsVibrationEnabled() { return false; } - virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) { - return PollingError::NotSupported; + virtual DriverResult SetPollingMode([[maybe_unused]] PollingMode polling_mode) { + return DriverResult::NotSupported; } - virtual CameraError SetCameraFormat([[maybe_unused]] CameraFormat camera_format) { - return CameraError::NotSupported; + virtual DriverResult SetCameraFormat([[maybe_unused]] CameraFormat camera_format) { + return DriverResult::NotSupported; } virtual NfcState SupportsNfc() const { diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 1ed57f949..62da5be6c 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -1178,7 +1178,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v .type = type, }; return output_devices[device_index]->SetVibration(status) == - Common::Input::VibrationError::None; + Common::Input::DriverResult::Success; } bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { @@ -1208,8 +1208,8 @@ bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); const auto mapped_nfc_result = output_device->SetPollingMode(polling_mode); - return virtual_nfc_result == Common::Input::PollingError::None || - mapped_nfc_result == Common::Input::PollingError::None; + return virtual_nfc_result == Common::Input::DriverResult::Success || + mapped_nfc_result == Common::Input::DriverResult::Success; } bool EmulatedController::SetCameraFormat( @@ -1220,13 +1220,13 @@ bool EmulatedController::SetCameraFormat( auto& camera_output_device = output_devices[2]; if (right_output_device->SetCameraFormat(static_cast( - camera_format)) == Common::Input::CameraError::None) { + camera_format)) == Common::Input::DriverResult::Success) { return true; } // Fallback to Qt camera if native device doesn't have support return camera_output_device->SetCameraFormat(static_cast( - camera_format)) == Common::Input::CameraError::None; + camera_format)) == Common::Input::DriverResult::Success; } Common::ParamPackage EmulatedController::GetRingParam() const { diff --git a/src/input_common/drivers/camera.cpp b/src/input_common/drivers/camera.cpp index fad9177dc..04970f635 100644 --- a/src/input_common/drivers/camera.cpp +++ b/src/input_common/drivers/camera.cpp @@ -72,11 +72,11 @@ std::size_t Camera::getImageHeight() const { } } -Common::Input::CameraError Camera::SetCameraFormat( +Common::Input::DriverResult Camera::SetCameraFormat( [[maybe_unused]] const PadIdentifier& identifier_, const Common::Input::CameraFormat camera_format) { status.format = camera_format; - return Common::Input::CameraError::None; + return Common::Input::DriverResult::Success; } } // namespace InputCommon diff --git a/src/input_common/drivers/camera.h b/src/input_common/drivers/camera.h index ead3e0fde..24b27e325 100644 --- a/src/input_common/drivers/camera.h +++ b/src/input_common/drivers/camera.h @@ -22,8 +22,8 @@ public: std::size_t getImageWidth() const; std::size_t getImageHeight() const; - Common::Input::CameraError SetCameraFormat(const PadIdentifier& identifier_, - Common::Input::CameraFormat camera_format) override; + Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier_, + Common::Input::CameraFormat camera_format) override; private: Common::Input::CameraStatus status{}; diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 826fa2109..ecb3e9dc2 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -324,7 +324,7 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) { return true; } -Common::Input::VibrationError GCAdapter::SetVibration( +Common::Input::DriverResult GCAdapter::SetVibration( const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; const auto processed_amplitude = @@ -333,9 +333,9 @@ Common::Input::VibrationError GCAdapter::SetVibration( pads[identifier.port].rumble_amplitude = processed_amplitude; if (!rumble_enabled) { - return Common::Input::VibrationError::Disabled; + return Common::Input::DriverResult::Disabled; } - return Common::Input::VibrationError::None; + return Common::Input::DriverResult::Success; } bool GCAdapter::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) { diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index b5270fd0b..3c2eb376d 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -25,7 +25,7 @@ public: explicit GCAdapter(std::string input_engine_); ~GCAdapter() override; - Common::Input::VibrationError SetVibration( + Common::Input::DriverResult SetVibration( const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; bool IsVibrationEnabled(const PadIdentifier& identifier) override; diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index 696a6db39..cf54f1b53 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp @@ -233,8 +233,8 @@ bool Joycons::IsVibrationEnabled(const PadIdentifier& identifier) { return handle->IsVibrationEnabled(); } -Common::Input::VibrationError Joycons::SetVibration( - const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { +Common::Input::DriverResult Joycons::SetVibration(const PadIdentifier& identifier, + const Common::Input::VibrationStatus& vibration) { const Joycon::VibrationValue native_vibration{ .low_amplitude = vibration.low_amplitude, .low_frequency = vibration.low_frequency, @@ -243,32 +243,31 @@ Common::Input::VibrationError Joycons::SetVibration( }; auto handle = GetHandle(identifier); if (handle == nullptr) { - return Common::Input::VibrationError::InvalidHandle; + return Common::Input::DriverResult::InvalidHandle; } handle->SetVibration(native_vibration); - return Common::Input::VibrationError::None; + return Common::Input::DriverResult::Success; } -void Joycons::SetLeds(const PadIdentifier& identifier, const Common::Input::LedStatus& led_status) { +Common::Input::DriverResult Joycons::SetLeds(const PadIdentifier& identifier, + const Common::Input::LedStatus& led_status) { auto handle = GetHandle(identifier); if (handle == nullptr) { - return; + return Common::Input::DriverResult::InvalidHandle; } int led_config = led_status.led_1 ? 1 : 0; led_config += led_status.led_2 ? 2 : 0; led_config += led_status.led_3 ? 4 : 0; led_config += led_status.led_4 ? 8 : 0; - const auto result = handle->SetLedConfig(static_cast(led_config)); - if (result != Joycon::DriverResult::Success) { - LOG_ERROR(Input, "Failed to set led config"); - } + return static_cast( + handle->SetLedConfig(static_cast(led_config))); } -Common::Input::CameraError Joycons::SetCameraFormat(const PadIdentifier& identifier_, - Common::Input::CameraFormat camera_format) { - return Common::Input::CameraError::NotSupported; +Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier_, + Common::Input::CameraFormat camera_format) { + return Common::Input::DriverResult::NotSupported; }; Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) const { @@ -280,32 +279,30 @@ Common::Input::NfcState Joycons::WriteNfcData(const PadIdentifier& identifier_, return Common::Input::NfcState::NotSupported; }; -Common::Input::PollingError Joycons::SetPollingMode(const PadIdentifier& identifier, +Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identifier, const Common::Input::PollingMode polling_mode) { auto handle = GetHandle(identifier); if (handle == nullptr) { LOG_ERROR(Input, "Invalid handle {}", identifier.port); - return Common::Input::PollingError::InvalidHandle; + return Common::Input::DriverResult::InvalidHandle; } switch (polling_mode) { case Common::Input::PollingMode::NFC: - handle->SetNfcMode(); + return static_cast(handle->SetNfcMode()); break; case Common::Input::PollingMode::Active: - handle->SetActiveMode(); + return static_cast(handle->SetActiveMode()); break; case Common::Input::PollingMode::Pasive: - handle->SetPasiveMode(); + return static_cast(handle->SetPasiveMode()); break; case Common::Input::PollingMode::Ring: - handle->SetRingConMode(); + return static_cast(handle->SetRingConMode()); break; default: - return Common::Input::PollingError::NotSupported; + return Common::Input::DriverResult::NotSupported; } - - return Common::Input::PollingError::None; } void Joycons::OnBatteryUpdate(std::size_t port, Joycon::ControllerType type, diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h index 56c117270..1a04c19fd 100644 --- a/src/input_common/drivers/joycon.h +++ b/src/input_common/drivers/joycon.h @@ -29,20 +29,20 @@ public: ~Joycons(); bool IsVibrationEnabled(const PadIdentifier& identifier) override; - Common::Input::VibrationError SetVibration( + Common::Input::DriverResult SetVibration( const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; - void SetLeds(const PadIdentifier& identifier, - const Common::Input::LedStatus& led_status) override; + Common::Input::DriverResult SetLeds(const PadIdentifier& identifier, + const Common::Input::LedStatus& led_status) override; - Common::Input::CameraError SetCameraFormat(const PadIdentifier& identifier_, - Common::Input::CameraFormat camera_format) override; + Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier_, + Common::Input::CameraFormat camera_format) override; Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, const std::vector& data) override; - Common::Input::PollingError SetPollingMode( + Common::Input::DriverResult SetPollingMode( const PadIdentifier& identifier, const Common::Input::PollingMode polling_mode) override; /// Used for automapping features diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index c9496a0d8..51a9d8962 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -545,7 +545,7 @@ std::vector SDLDriver::GetInputDevices() const { return devices; } -Common::Input::VibrationError SDLDriver::SetVibration( +Common::Input::DriverResult SDLDriver::SetVibration( const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { const auto joystick = GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast(identifier.port)); @@ -579,7 +579,7 @@ Common::Input::VibrationError SDLDriver::SetVibration( .vibration = new_vibration, }); - return Common::Input::VibrationError::None; + return Common::Input::DriverResult::Success; } bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) { diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index 366bcc496..ffde169b3 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -63,7 +63,7 @@ public: bool IsStickInverted(const Common::ParamPackage& params) override; - Common::Input::VibrationError SetVibration( + Common::Input::DriverResult SetVibration( const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; bool IsVibrationEnabled(const PadIdentifier& identifier) override; diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp index 63ffaca67..29e129d3c 100644 --- a/src/input_common/drivers/virtual_amiibo.cpp +++ b/src/input_common/drivers/virtual_amiibo.cpp @@ -22,7 +22,7 @@ VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move( VirtualAmiibo::~VirtualAmiibo() = default; -Common::Input::PollingError VirtualAmiibo::SetPollingMode( +Common::Input::DriverResult VirtualAmiibo::SetPollingMode( [[maybe_unused]] const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) { polling_mode = polling_mode_; @@ -37,7 +37,7 @@ Common::Input::PollingError VirtualAmiibo::SetPollingMode( } } - return Common::Input::PollingError::None; + return Common::Input::DriverResult::Success; } Common::Input::NfcState VirtualAmiibo::SupportsNfc( diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h index 0f9dad333..13cacfc0a 100644 --- a/src/input_common/drivers/virtual_amiibo.h +++ b/src/input_common/drivers/virtual_amiibo.h @@ -36,7 +36,7 @@ public: ~VirtualAmiibo() override; // Sets polling mode to a controller - Common::Input::PollingError SetPollingMode( + Common::Input::DriverResult SetPollingMode( const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override; Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index 8982a2397..b00b6110b 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -459,23 +459,23 @@ SerialNumber JoyconDriver::GetHandleSerialNumber() const { return handle_serial_number; } -void JoyconDriver::SetCallbacks(const Joycon::JoyconCallbacks& callbacks) { +void JoyconDriver::SetCallbacks(const JoyconCallbacks& callbacks) { joycon_poller->SetCallbacks(callbacks); } -Joycon::DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, - ControllerType& controller_type) { - static constexpr std::array, 4> supported_devices{ - std::pair{0x2006, Joycon::ControllerType::Left}, - {0x2007, Joycon::ControllerType::Right}, - {0x2009, Joycon::ControllerType::Pro}, - {0x200E, Joycon::ControllerType::Grip}, +DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info, + ControllerType& controller_type) { + static constexpr std::array, 4> supported_devices{ + std::pair{0x2006, ControllerType::Left}, + {0x2007, ControllerType::Right}, + {0x2009, ControllerType::Pro}, + {0x200E, ControllerType::Grip}, }; constexpr u16 nintendo_vendor_id = 0x057e; - controller_type = Joycon::ControllerType::None; + controller_type = ControllerType::None; if (device_info->vendor_id != nintendo_vendor_id) { - return Joycon::DriverResult::UnsupportedControllerType; + return DriverResult::UnsupportedControllerType; } for (const auto& [product_id, type] : supported_devices) { @@ -487,10 +487,10 @@ Joycon::DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_inf return Joycon::DriverResult::UnsupportedControllerType; } -Joycon::DriverResult JoyconDriver::GetSerialNumber(SDL_hid_device_info* device_info, - Joycon::SerialNumber& serial_number) { +DriverResult JoyconDriver::GetSerialNumber(SDL_hid_device_info* device_info, + SerialNumber& serial_number) { if (device_info->serial_number == nullptr) { - return Joycon::DriverResult::Unknown; + return DriverResult::Unknown; } std::memcpy(&serial_number, device_info->serial_number, 15); return Joycon::DriverResult::Success; diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index c9118ee93..bf38a3009 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h @@ -46,15 +46,15 @@ public: DriverResult SetNfcMode(); DriverResult SetRingConMode(); - void SetCallbacks(const Joycon::JoyconCallbacks& callbacks); + void SetCallbacks(const JoyconCallbacks& callbacks); // Returns device type from hidapi handle - static Joycon::DriverResult GetDeviceType(SDL_hid_device_info* device_info, - Joycon::ControllerType& controller_type); + static DriverResult GetDeviceType(SDL_hid_device_info* device_info, + ControllerType& controller_type); // Returns serial number from hidapi handle - static Joycon::DriverResult GetSerialNumber(SDL_hid_device_info* device_info, - Joycon::SerialNumber& serial_number); + static DriverResult GetSerialNumber(SDL_hid_device_info* device_info, + SerialNumber& serial_number); private: struct SupportedFeatures { diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index de512fe63..36c00a8d7 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h @@ -284,6 +284,7 @@ enum class DriverResult { NoDeviceDetected, InvalidHandle, NotSupported, + Disabled, Unknown, }; diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index 6301c5719..50b5a3dc8 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -105,14 +105,17 @@ public: void EndConfiguration(); // Sets a led pattern for a controller - virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier, - [[maybe_unused]] const Common::Input::LedStatus& led_status) {} + virtual Common::Input::DriverResult SetLeds( + [[maybe_unused]] const PadIdentifier& identifier, + [[maybe_unused]] const Common::Input::LedStatus& led_status) { + return Common::Input::DriverResult::NotSupported; + } // Sets rumble to a controller - virtual Common::Input::VibrationError SetVibration( + virtual Common::Input::DriverResult SetVibration( [[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] const Common::Input::VibrationStatus& vibration) { - return Common::Input::VibrationError::NotSupported; + return Common::Input::DriverResult::NotSupported; } // Returns true if device supports vibrations @@ -121,17 +124,17 @@ public: } // Sets polling mode to a controller - virtual Common::Input::PollingError SetPollingMode( + virtual Common::Input::DriverResult SetPollingMode( [[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] const Common::Input::PollingMode polling_mode) { - return Common::Input::PollingError::NotSupported; + return Common::Input::DriverResult::NotSupported; } // Sets camera format to a controller - virtual Common::Input::CameraError SetCameraFormat( + virtual Common::Input::DriverResult SetCameraFormat( [[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] Common::Input::CameraFormat camera_format) { - return Common::Input::CameraError::NotSupported; + return Common::Input::DriverResult::NotSupported; } // Returns success if nfc is supported diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 368ffbdd5..15cbf7e5f 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -806,11 +806,11 @@ public: explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_) : identifier(identifier_), input_engine(input_engine_) {} - void SetLED(const Common::Input::LedStatus& led_status) override { - input_engine->SetLeds(identifier, led_status); + Common::Input::DriverResult SetLED(const Common::Input::LedStatus& led_status) override { + return input_engine->SetLeds(identifier, led_status); } - Common::Input::VibrationError SetVibration( + Common::Input::DriverResult SetVibration( const Common::Input::VibrationStatus& vibration_status) override { return input_engine->SetVibration(identifier, vibration_status); } @@ -819,11 +819,12 @@ public: return input_engine->IsVibrationEnabled(identifier); } - Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override { + Common::Input::DriverResult SetPollingMode(Common::Input::PollingMode polling_mode) override { return input_engine->SetPollingMode(identifier, polling_mode); } - Common::Input::CameraError SetCameraFormat(Common::Input::CameraFormat camera_format) override { + Common::Input::DriverResult SetCameraFormat( + Common::Input::CameraFormat camera_format) override { return input_engine->SetCameraFormat(identifier, camera_format); } -- cgit v1.2.3 From 5cb437703fa441a08db295f8a916caedc3a581f2 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 26 Dec 2022 12:49:49 -0600 Subject: yuzu: Add ring controller test button --- src/core/hid/emulated_controller.cpp | 10 +- src/core/hid/emulated_controller.h | 4 +- src/core/hle/service/nfc/nfc_device.cpp | 3 +- src/core/hle/service/nfp/nfp_device.cpp | 3 +- src/input_common/drivers/virtual_amiibo.cpp | 9 +- src/input_common/helpers/joycon_driver.cpp | 38 ++- src/input_common/helpers/joycon_driver.h | 2 +- src/yuzu/configuration/configure_ringcon.cpp | 69 +++++ src/yuzu/configuration/configure_ringcon.h | 10 + src/yuzu/configuration/configure_ringcon.ui | 396 +++++++++++++++++---------- 10 files changed, 370 insertions(+), 174 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 62da5be6c..915ffa490 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -1200,7 +1200,8 @@ bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { return output_devices[device_index]->IsVibrationEnabled(); } -bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) { +Common::Input::DriverResult EmulatedController::SetPollingMode( + Common::Input::PollingMode polling_mode) { LOG_INFO(Service_HID, "Set polling mode {}", polling_mode); auto& output_device = output_devices[static_cast(DeviceIndex::Right)]; auto& nfc_output_device = output_devices[3]; @@ -1208,8 +1209,11 @@ bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); const auto mapped_nfc_result = output_device->SetPollingMode(polling_mode); - return virtual_nfc_result == Common::Input::DriverResult::Success || - mapped_nfc_result == Common::Input::DriverResult::Success; + if (virtual_nfc_result == Common::Input::DriverResult::Success) { + return virtual_nfc_result; + } + + return mapped_nfc_result; } bool EmulatedController::SetCameraFormat( diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index c517aa5d7..fb931fc0a 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -363,9 +363,9 @@ public: /** * Sets the desired data to be polled from a controller * @param polling_mode type of input desired buttons, gyro, nfc, ir, etc. - * @return true if SetPollingMode was successfull + * @return driver result from this command */ - bool SetPollingMode(Common::Input::PollingMode polling_mode); + Common::Input::DriverResult SetPollingMode(Common::Input::PollingMode polling_mode); /** * Sets the desired camera format to be polled from a controller diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp index 78578f723..c9815edbc 100644 --- a/src/core/hle/service/nfc/nfc_device.cpp +++ b/src/core/hle/service/nfc/nfc_device.cpp @@ -130,7 +130,8 @@ Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) { return WrongDeviceState; } - if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) { + if (npad_device->SetPollingMode(Common::Input::PollingMode::NFC) != + Common::Input::DriverResult::Success) { LOG_ERROR(Service_NFC, "Nfc not supported"); return NfcDisabled; } diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index c860fd1a1..7b8013961 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -152,7 +152,8 @@ Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { return WrongDeviceState; } - if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) { + if (npad_device->SetPollingMode(Common::Input::PollingMode::NFC) != + Common::Input::DriverResult::Success) { LOG_ERROR(Service_NFP, "Nfc not supported"); return NfcDisabled; } diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp index 29e129d3c..4a0268a4d 100644 --- a/src/input_common/drivers/virtual_amiibo.cpp +++ b/src/input_common/drivers/virtual_amiibo.cpp @@ -27,17 +27,18 @@ Common::Input::DriverResult VirtualAmiibo::SetPollingMode( const Common::Input::PollingMode polling_mode_) { polling_mode = polling_mode_; - if (polling_mode == Common::Input::PollingMode::NFC) { + switch (polling_mode) { + case Common::Input::PollingMode::NFC: if (state == State::Initialized) { state = State::WaitingForAmiibo; } - } else { + return Common::Input::DriverResult::Success; + default: if (state == State::AmiiboIsOpen) { CloseAmiibo(); } + return Common::Input::DriverResult::NotSupported; } - - return Common::Input::DriverResult::Success; } Common::Input::NfcState VirtualAmiibo::SupportsNfc( diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index b00b6110b..8217ba7f6 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -238,7 +238,7 @@ void JoyconDriver::OnNewData(std::span buffer) { } } -void JoyconDriver::SetPollingMode() { +DriverResult JoyconDriver::SetPollingMode() { disable_input_thread = true; rumble_protocol->EnableRumble(vibration_enabled && supported_features.vibration); @@ -263,7 +263,7 @@ void JoyconDriver::SetPollingMode() { } if (result == DriverResult::Success) { disable_input_thread = false; - return; + return result; } nfc_protocol->DisableNfc(); LOG_ERROR(Input, "Error enabling NFC"); @@ -282,7 +282,7 @@ void JoyconDriver::SetPollingMode() { if (result == DriverResult::Success) { ring_connected = true; disable_input_thread = false; - return; + return result; } ring_connected = false; ring_protocol->DisableRingCon(); @@ -293,7 +293,7 @@ void JoyconDriver::SetPollingMode() { const auto result = generic_protocol->EnablePassiveMode(); if (result == DriverResult::Success) { disable_input_thread = false; - return; + return result; } LOG_ERROR(Input, "Error enabling passive mode"); } @@ -305,6 +305,7 @@ void JoyconDriver::SetPollingMode() { } disable_input_thread = false; + return result; } JoyconDriver::SupportedFeatures JoyconDriver::GetSupportedFeatures() { @@ -380,8 +381,7 @@ DriverResult JoyconDriver::SetPasiveMode() { hidbus_enabled = false; nfc_enabled = false; passive_enabled = true; - SetPollingMode(); - return DriverResult::Success; + return SetPollingMode(); } DriverResult JoyconDriver::SetActiveMode() { @@ -390,28 +390,42 @@ DriverResult JoyconDriver::SetActiveMode() { hidbus_enabled = false; nfc_enabled = false; passive_enabled = false; - SetPollingMode(); - return DriverResult::Success; + return SetPollingMode(); } DriverResult JoyconDriver::SetNfcMode() { std::scoped_lock lock{mutex}; + + if (!supported_features.nfc) { + return DriverResult::NotSupported; + } + motion_enabled = true; hidbus_enabled = false; nfc_enabled = true; passive_enabled = false; - SetPollingMode(); - return DriverResult::Success; + return SetPollingMode(); } DriverResult JoyconDriver::SetRingConMode() { std::scoped_lock lock{mutex}; + + if (!supported_features.hidbus) { + return DriverResult::NotSupported; + } + motion_enabled = true; hidbus_enabled = true; nfc_enabled = false; passive_enabled = false; - SetPollingMode(); - return DriverResult::Success; + + const auto result = SetPollingMode(); + + if (!ring_connected) { + return DriverResult::NoDeviceDetected; + } + + return result; } bool JoyconDriver::IsConnected() const { diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index bf38a3009..5ff15c784 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h @@ -73,7 +73,7 @@ private: void OnNewData(std::span buffer); /// Updates device configuration to enable or disable features - void SetPollingMode(); + DriverResult SetPollingMode(); /// Returns true if input thread is valid and doesn't need to be stopped bool IsInputThreadValid() const; diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index 0cfe3b60e..697c36fb4 100644 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ b/src/yuzu/configuration/configure_ringcon.cpp @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" @@ -130,6 +132,13 @@ ConfigureRingController::ConfigureRingController(QWidget* parent, emulated_controller->SaveCurrentConfig(); emulated_controller->EnableConfiguration(); + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }, + .is_npad_service = false, + }; + callback_key = emulated_controller->SetCallback(engine_callback); + is_controller_set = true; + LoadConfiguration(); for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { @@ -187,6 +196,9 @@ ConfigureRingController::ConfigureRingController(QWidget* parent, connect(ui->restore_defaults_button, &QPushButton::clicked, this, &ConfigureRingController::RestoreDefaults); + connect(ui->enable_ring_controller_button, &QPushButton::clicked, this, + &ConfigureRingController::EnableRingController); + timeout_timer->setSingleShot(true); connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); @@ -202,7 +214,13 @@ ConfigureRingController::ConfigureRingController(QWidget* parent, } ConfigureRingController::~ConfigureRingController() { + emulated_controller->SetPollingMode(Common::Input::PollingMode::Active); emulated_controller->DisableConfiguration(); + + if (is_controller_set) { + emulated_controller->DeleteCallback(callback_key); + is_controller_set = false; + } }; void ConfigureRingController::changeEvent(QEvent* event) { @@ -256,6 +274,57 @@ void ConfigureRingController::RestoreDefaults() { UpdateUI(); } +void ConfigureRingController::EnableRingController() { + const auto dialog_title = tr("Error enabling ring input"); + + is_ring_enabled = false; + ui->ring_controller_sensor_value->setText(tr("Not connected")); + + if (!Settings::values.enable_joycon_driver) { + QMessageBox::warning(this, dialog_title, tr("Direct Joycon driver is not enabled")); + return; + } + + ui->enable_ring_controller_button->setEnabled(false); + ui->enable_ring_controller_button->setText(tr("Configuring")); + // SetPollingMode is blocking. Allow to update the button status before calling the command + repaint(); + + const auto result = emulated_controller->SetPollingMode(Common::Input::PollingMode::Ring); + switch (result) { + case Common::Input::DriverResult::Success: + is_ring_enabled = true; + break; + case Common::Input::DriverResult::NotSupported: + QMessageBox::warning(this, dialog_title, + tr("The current mapped device doesn't support the ring controller")); + break; + case Common::Input::DriverResult::NoDeviceDetected: + QMessageBox::warning(this, dialog_title, + tr("The current mapped device doesn't have a ring attached")); + break; + default: + QMessageBox::warning(this, dialog_title, + tr("Unexpected driver result %1").arg(static_cast(result))); + break; + } + ui->enable_ring_controller_button->setEnabled(true); + ui->enable_ring_controller_button->setText(tr("Enable")); +} + +void ConfigureRingController::ControllerUpdate(Core::HID::ControllerTriggerType type) { + if (!is_ring_enabled) { + return; + } + if (type != Core::HID::ControllerTriggerType::RingController) { + return; + } + + const auto value = emulated_controller->GetRingSensorValues(); + const auto tex_value = QString::fromStdString(fmt::format("{:.3f}", value.raw_value)); + ui->ring_controller_sensor_value->setText(tex_value); +} + void ConfigureRingController::HandleClick( QPushButton* button, std::function new_input_setter, InputCommon::Polling::InputType type) { diff --git a/src/yuzu/configuration/configure_ringcon.h b/src/yuzu/configuration/configure_ringcon.h index 6e693e0dd..b23c27906 100644 --- a/src/yuzu/configuration/configure_ringcon.h +++ b/src/yuzu/configuration/configure_ringcon.h @@ -42,6 +42,12 @@ private: /// Restore all buttons to their default values. void RestoreDefaults(); + /// Sets current polling mode to ring input + void EnableRingController(); + + // Handles emulated controller events + void ControllerUpdate(Core::HID::ControllerTriggerType type); + /// Called when the button was pressed. void HandleClick(QPushButton* button, std::function new_input_setter, @@ -80,5 +86,9 @@ private: InputCommon::InputSubsystem* input_subsystem; Core::HID::EmulatedController* emulated_controller; + bool is_ring_enabled{}; + bool is_controller_set{}; + int callback_key; + std::unique_ptr ui; }; diff --git a/src/yuzu/configuration/configure_ringcon.ui b/src/yuzu/configuration/configure_ringcon.ui index 9ec634dd4..514dff372 100644 --- a/src/yuzu/configuration/configure_ringcon.ui +++ b/src/yuzu/configuration/configure_ringcon.ui @@ -6,8 +6,8 @@ 0 0 - 298 - 339 + 315 + 400 @@ -46,187 +46,283 @@ - - - - Ring Sensor Parameters - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - 0 - - - QLayout::SetDefaultConstraint - - - 3 - - - 6 - - - 3 - - - 0 - - - + + + + Virtual Ring Sensor Parameters + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + - 3 + 0 - - - - Pull - - - Qt::AlignCenter + + QLayout::SetDefaultConstraint + + + 3 + + + 6 + + + 3 + + + 0 + + + + + 3 - - - 3 + + + + Pull - - 3 - - - 3 + + Qt::AlignCenter - - 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 70 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + Pull + + + + + + + + + + Push - - 3 + + Qt::AlignCenter - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - min-width: 68px; - - - Pull - - - - - + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 70 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + Push + + + + + + + - - - - Push + + + + 3 - - Qt::AlignCenter + + QLayout::SetDefaultConstraint - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - + + 0 + + + 10 + + + 0 + + + 3 + + + - - - - 68 - 0 - - - - - 68 - 16777215 - - - - min-width: 68px; - + - Push + Deadzone: 0% + + + Qt::AlignHCenter - + - - + + + + + + 100 + + + Qt::Horizontal + + + + - - - - + + + + + + + Direct Joycon Driver + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + - 3 + 0 - QLayout::SetDefaultConstraint + QLayout::SetDefaultConstraint - 0 + 3 - 10 + 6 - 0 + 3 - 3 + 10 - - - + + + 10 + + + 6 + + + 10 + + + 10 + + + 10 + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 76 + 20 + + + + + + + + Enable Ring Input + + + + + - Deadzone: 0% + Enable + + + + + + + Ring Sensor Value + + + + + + + Not connected - Qt::AlignHCenter + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - - - - - - 100 - - - Qt::Horizontal - - + - - - - - + + + @@ -273,6 +369,6 @@ rejected() ConfigureRingController reject() - + -- cgit v1.2.3 From 459fb2b21337bae60194a2a99ce68c87aaed522d Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Wed, 28 Dec 2022 15:21:12 -0600 Subject: input_common: Implement joycon ir camera --- src/core/hid/emulated_controller.cpp | 21 +- src/core/hid/emulated_controller.h | 5 +- src/core/hle/service/hid/irs.cpp | 11 + src/input_common/CMakeLists.txt | 2 + src/input_common/drivers/joycon.cpp | 29 +- src/input_common/drivers/joycon.h | 5 +- src/input_common/helpers/joycon_driver.cpp | 55 +++- src/input_common/helpers/joycon_driver.h | 4 + .../helpers/joycon_protocol/common_protocol.cpp | 13 + .../helpers/joycon_protocol/common_protocol.h | 7 + src/input_common/helpers/joycon_protocol/irs.cpp | 300 +++++++++++++++++++++ src/input_common/helpers/joycon_protocol/irs.h | 63 +++++ .../helpers/joycon_protocol/joycon_types.h | 107 +++++++- .../helpers/joycon_protocol/poller.cpp | 6 +- src/input_common/helpers/joycon_protocol/poller.h | 3 +- 15 files changed, 608 insertions(+), 23 deletions(-) create mode 100644 src/input_common/helpers/joycon_protocol/irs.cpp create mode 100644 src/input_common/helpers/joycon_protocol/irs.h (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 915ffa490..faf9e7c4e 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -145,7 +145,9 @@ void EmulatedController::LoadDevices() { battery_params[LeftIndex].Set("battery", true); battery_params[RightIndex].Set("battery", true); - camera_params = Common::ParamPackage{"engine:camera,camera:1"}; + camera_params[0] = right_joycon; + camera_params[0].Set("camera", true); + camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"}; ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; nfc_params[1] = right_joycon; @@ -153,7 +155,7 @@ void EmulatedController::LoadDevices() { output_params[LeftIndex] = left_joycon; output_params[RightIndex] = right_joycon; - output_params[2] = camera_params; + output_params[2] = camera_params[1]; output_params[3] = nfc_params[0]; output_params[LeftIndex].Set("output", true); output_params[RightIndex].Set("output", true); @@ -171,7 +173,7 @@ void EmulatedController::LoadDevices() { std::ranges::transform(battery_params, battery_devices.begin(), Common::Input::CreateInputDevice); std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice); - camera_devices = Common::Input::CreateInputDevice(camera_params); + std::ranges::transform(camera_params, camera_devices.begin(), Common::Input::CreateInputDevice); std::ranges::transform(ring_params, ring_analog_devices.begin(), Common::Input::CreateInputDevice); std::ranges::transform(nfc_params, nfc_devices.begin(), Common::Input::CreateInputDevice); @@ -362,12 +364,15 @@ void EmulatedController::ReloadInput() { motion_devices[index]->ForceUpdate(); } - if (camera_devices) { - camera_devices->SetCallback({ + for (std::size_t index = 0; index < camera_devices.size(); ++index) { + if (!camera_devices[index]) { + continue; + } + camera_devices[index]->SetCallback({ .on_change = [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); }, }); - camera_devices->ForceUpdate(); + camera_devices[index]->ForceUpdate(); } for (std::size_t index = 0; index < ring_analog_devices.size(); ++index) { @@ -477,7 +482,9 @@ void EmulatedController::UnloadInput() { for (auto& stick : virtual_stick_devices) { stick.reset(); } - camera_devices.reset(); + for (auto& camera : camera_devices) { + camera.reset(); + } for (auto& ring : ring_analog_devices) { ring.reset(); } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index fb931fc0a..edebfc15c 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -39,7 +39,8 @@ using ColorDevices = std::array, max_emulated_controllers>; using BatteryDevices = std::array, max_emulated_controllers>; -using CameraDevices = std::unique_ptr; +using CameraDevices = + std::array, max_emulated_controllers>; using RingAnalogDevices = std::array, max_emulated_controllers>; using NfcDevices = @@ -52,7 +53,7 @@ using ControllerMotionParams = std::array; using ColorParams = std::array; using BatteryParams = std::array; -using CameraParams = Common::ParamPackage; +using CameraParams = std::array; using RingAnalogParams = std::array; using NfcParams = std::array; using OutputParams = std::array; diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 6a3453457..3c1fa2274 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -74,6 +74,8 @@ void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); + npad_device->SetPollingMode(Common::Input::PollingMode::Active); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -108,6 +110,7 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { auto result = IsIrCameraHandleValid(parameters.camera_handle); if (result.IsSuccess()) { // TODO: Stop Image processor + npad_device->SetPollingMode(Common::Input::PollingMode::Active); result = ResultSuccess; } @@ -139,6 +142,7 @@ void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor(parameters.camera_handle, device); auto& image_transfer_processor = GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); + npad_device->SetPollingMode(Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -170,6 +174,7 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); + npad_device->SetPollingMode(Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -219,6 +224,7 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); image_transfer_processor.SetTransferMemoryPointer(transfer_memory); + npad_device->SetPollingMode(Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -294,6 +300,7 @@ void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); + npad_device->SetPollingMode(Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -343,6 +350,7 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor(camera_handle, device); auto& image_transfer_processor = GetProcessor(camera_handle); image_transfer_processor.SetConfig(processor_config); + npad_device->SetPollingMode(Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -453,6 +461,7 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); image_transfer_processor.SetTransferMemoryPointer(transfer_memory); + npad_device->SetPollingMode(Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -479,6 +488,7 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor(camera_handle, device); auto& image_transfer_processor = GetProcessor(camera_handle); image_transfer_processor.SetConfig(processor_config); + npad_device->SetPollingMode(Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -504,6 +514,7 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { auto result = IsIrCameraHandleValid(parameters.camera_handle); if (result.IsSuccess()) { // TODO: Stop image processor async + npad_device->SetPollingMode(Common::Input::PollingMode::IR); result = ResultSuccess; } diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 9c901af2a..e3b627e4f 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -64,6 +64,8 @@ if (ENABLE_SDL2) helpers/joycon_protocol/generic_functions.cpp helpers/joycon_protocol/generic_functions.h helpers/joycon_protocol/joycon_types.h + helpers/joycon_protocol/irs.cpp + helpers/joycon_protocol/irs.h helpers/joycon_protocol/nfc.cpp helpers/joycon_protocol/nfc.h helpers/joycon_protocol/poller.cpp diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index cf54f1b53..6c03e0953 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp @@ -191,6 +191,10 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) { .on_amiibo_data = {[this, port](const std::vector& amiibo_data) { OnAmiiboUpdate(port, amiibo_data); }}, + .on_camera_data = {[this, port](const std::vector& camera_data, + Joycon::IrsResolution format) { + OnCameraUpdate(port, camera_data, format); + }}, }; handle->InitializeDevice(); @@ -265,9 +269,14 @@ Common::Input::DriverResult Joycons::SetLeds(const PadIdentifier& identifier, handle->SetLedConfig(static_cast(led_config))); } -Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier_, +Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier, Common::Input::CameraFormat camera_format) { - return Common::Input::DriverResult::NotSupported; + auto handle = GetHandle(identifier); + if (handle == nullptr) { + return Common::Input::DriverResult::InvalidHandle; + } + return static_cast(handle->SetIrsConfig( + Joycon::IrsMode::ImageTransfer, static_cast(camera_format))); }; Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) const { @@ -288,18 +297,16 @@ Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identif } switch (polling_mode) { - case Common::Input::PollingMode::NFC: - return static_cast(handle->SetNfcMode()); - break; case Common::Input::PollingMode::Active: return static_cast(handle->SetActiveMode()); - break; case Common::Input::PollingMode::Pasive: return static_cast(handle->SetPasiveMode()); - break; + case Common::Input::PollingMode::IR: + return static_cast(handle->SetIrMode()); + case Common::Input::PollingMode::NFC: + return static_cast(handle->SetNfcMode()); case Common::Input::PollingMode::Ring: return static_cast(handle->SetRingConMode()); - break; default: return Common::Input::DriverResult::NotSupported; } @@ -390,6 +397,12 @@ void Joycons::OnAmiiboUpdate(std::size_t port, const std::vector& amiibo_dat SetNfc(identifier, {nfc_state, amiibo_data}); } +void Joycons::OnCameraUpdate(std::size_t port, const std::vector& camera_data, + Joycon::IrsResolution format) { + const auto identifier = GetIdentifier(port, Joycon::ControllerType::Right); + SetCamera(identifier, {static_cast(format), camera_data}); +} + std::shared_ptr Joycons::GetHandle(PadIdentifier identifier) const { auto is_handle_active = [&](std::shared_ptr device) { if (!device) { diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h index 1a04c19fd..f180b7478 100644 --- a/src/input_common/drivers/joycon.h +++ b/src/input_common/drivers/joycon.h @@ -17,6 +17,7 @@ struct Color; struct MotionData; enum class ControllerType; enum class DriverResult; +enum class IrsResolution; class JoyconDriver; } // namespace InputCommon::Joycon @@ -35,7 +36,7 @@ public: Common::Input::DriverResult SetLeds(const PadIdentifier& identifier, const Common::Input::LedStatus& led_status) override; - Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier_, + Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier, Common::Input::CameraFormat camera_format) override; Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override; @@ -81,6 +82,8 @@ private: const Joycon::MotionData& value); void OnRingConUpdate(f32 ring_data); void OnAmiiboUpdate(std::size_t port, const std::vector& amiibo_data); + void OnCameraUpdate(std::size_t port, const std::vector& camera_data, + Joycon::IrsResolution format); /// Returns a JoyconHandle corresponding to a PadIdentifier std::shared_ptr GetHandle(PadIdentifier identifier) const; diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index 8217ba7f6..040832a4b 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -7,6 +7,7 @@ #include "input_common/helpers/joycon_driver.h" #include "input_common/helpers/joycon_protocol/calibration.h" #include "input_common/helpers/joycon_protocol/generic_functions.h" +#include "input_common/helpers/joycon_protocol/irs.h" #include "input_common/helpers/joycon_protocol/nfc.h" #include "input_common/helpers/joycon_protocol/poller.h" #include "input_common/helpers/joycon_protocol/ringcon.h" @@ -78,6 +79,7 @@ DriverResult JoyconDriver::InitializeDevice() { // Initialize HW Protocols calibration_protocol = std::make_unique(hidapi_handle); generic_protocol = std::make_unique(hidapi_handle); + irs_protocol = std::make_unique(hidapi_handle); nfc_protocol = std::make_unique(hidapi_handle); ring_protocol = std::make_unique(hidapi_handle); rumble_protocol = std::make_unique(hidapi_handle); @@ -200,10 +202,15 @@ void JoyconDriver::OnNewData(std::span buffer) { .min_value = ring_calibration.min_value, }; + if (irs_protocol->IsEnabled()) { + irs_protocol->RequestImage(buffer); + joycon_poller->UpdateCamera(irs_protocol->GetImage(), irs_protocol->GetIrsFormat()); + } + if (nfc_protocol->IsEnabled()) { if (amiibo_detected) { if (!nfc_protocol->HasAmiibo()) { - joycon_poller->updateAmiibo({}); + joycon_poller->UpdateAmiibo({}); amiibo_detected = false; return; } @@ -213,7 +220,7 @@ void JoyconDriver::OnNewData(std::span buffer) { std::vector data(0x21C); const auto result = nfc_protocol->ScanAmiibo(data); if (result == DriverResult::Success) { - joycon_poller->updateAmiibo(data); + joycon_poller->UpdateAmiibo(data); amiibo_detected = true; } } @@ -251,6 +258,20 @@ DriverResult JoyconDriver::SetPollingMode() { generic_protocol->EnableImu(false); } + if (irs_protocol->IsEnabled()) { + irs_protocol->DisableIrs(); + } + + if (irs_enabled && supported_features.irs) { + auto result = irs_protocol->EnableIrs(); + if (result == DriverResult::Success) { + disable_input_thread = false; + return result; + } + irs_protocol->DisableIrs(); + LOG_ERROR(Input, "Error enabling IRS"); + } + if (nfc_protocol->IsEnabled()) { amiibo_detected = false; nfc_protocol->DisableNfc(); @@ -375,12 +396,24 @@ DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { return generic_protocol->SetLedPattern(led_pattern); } +DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) { + std::scoped_lock lock{mutex}; + if (disable_input_thread) { + return DriverResult::HandleInUse; + } + disable_input_thread = true; + const auto result = irs_protocol->SetIrsConfig(mode_, format_); + disable_input_thread = false; + return result; +} + DriverResult JoyconDriver::SetPasiveMode() { std::scoped_lock lock{mutex}; motion_enabled = false; hidbus_enabled = false; nfc_enabled = false; passive_enabled = true; + irs_enabled = false; return SetPollingMode(); } @@ -390,6 +423,22 @@ DriverResult JoyconDriver::SetActiveMode() { hidbus_enabled = false; nfc_enabled = false; passive_enabled = false; + irs_enabled = false; + return SetPollingMode(); +} + +DriverResult JoyconDriver::SetIrMode() { + std::scoped_lock lock{mutex}; + + if (!supported_features.irs) { + return DriverResult::NotSupported; + } + + motion_enabled = false; + hidbus_enabled = false; + nfc_enabled = false; + passive_enabled = false; + irs_enabled = true; return SetPollingMode(); } @@ -404,6 +453,7 @@ DriverResult JoyconDriver::SetNfcMode() { hidbus_enabled = false; nfc_enabled = true; passive_enabled = false; + irs_enabled = false; return SetPollingMode(); } @@ -418,6 +468,7 @@ DriverResult JoyconDriver::SetRingConMode() { hidbus_enabled = true; nfc_enabled = false; passive_enabled = false; + irs_enabled = false; const auto result = SetPollingMode(); diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index 5ff15c784..61ecf4a6c 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h @@ -13,6 +13,7 @@ namespace InputCommon::Joycon { class CalibrationProtocol; class GenericProtocol; +class IrsProtocol; class NfcProtocol; class JoyconPoller; class RingConProtocol; @@ -41,8 +42,10 @@ public: DriverResult SetVibration(const VibrationValue& vibration); DriverResult SetLedConfig(u8 led_pattern); + DriverResult SetIrsConfig(IrsMode mode_, IrsResolution format_); DriverResult SetPasiveMode(); DriverResult SetActiveMode(); + DriverResult SetIrMode(); DriverResult SetNfcMode(); DriverResult SetRingConMode(); @@ -87,6 +90,7 @@ private: // Protocol Features std::unique_ptr calibration_protocol; std::unique_ptr generic_protocol; + std::unique_ptr irs_protocol; std::unique_ptr nfc_protocol; std::unique_ptr joycon_poller; std::unique_ptr ring_protocol; diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index a4d08fdaf..a329db107 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp @@ -120,6 +120,19 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span buffer) { + std::vector local_buffer(MaxResponseSize); + + local_buffer[0] = static_cast(OutputReport::MCU_DATA); + local_buffer[1] = GetCounter(); + local_buffer[10] = static_cast(sc); + for (std::size_t i = 0; i < buffer.size(); ++i) { + local_buffer[11 + i] = buffer[i]; + } + + return SendData(local_buffer); +} + DriverResult JoyconCommonProtocol::SendVibrationReport(std::span buffer) { std::vector local_buffer(MaxResponseSize); diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.h b/src/input_common/helpers/joycon_protocol/common_protocol.h index a65e4aa76..2a3feaf59 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.h +++ b/src/input_common/helpers/joycon_protocol/common_protocol.h @@ -74,6 +74,13 @@ public: */ DriverResult SendSubCommand(SubCommand sc, std::span buffer, std::vector& output); + /** + * Sends a mcu command to the device + * @param sc sub command to be send + * @param buffer data to be send + */ + DriverResult SendMcuCommand(SubCommand sc, std::span buffer); + /** * Sends vibration data to the joycon * @param buffer data to be send diff --git a/src/input_common/helpers/joycon_protocol/irs.cpp b/src/input_common/helpers/joycon_protocol/irs.cpp new file mode 100644 index 000000000..9dfa503c2 --- /dev/null +++ b/src/input_common/helpers/joycon_protocol/irs.cpp @@ -0,0 +1,300 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "common/logging/log.h" +#include "input_common/helpers/joycon_protocol/irs.h" + +namespace InputCommon::Joycon { + +IrsProtocol::IrsProtocol(std::shared_ptr handle) + : JoyconCommonProtocol(std::move(handle)) {} + +DriverResult IrsProtocol::EnableIrs() { + LOG_INFO(Input, "Enable IRS"); + DriverResult result{DriverResult::Success}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); + } + if (result == DriverResult::Success) { + result = EnableMCU(true); + } + if (result == DriverResult::Success) { + result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); + } + if (result == DriverResult::Success) { + const MCUConfig config{ + .command = MCUCommand::ConfigureMCU, + .sub_command = MCUSubCommand::SetMCUMode, + .mode = MCUMode::IR, + .crc = {}, + }; + + result = ConfigureMCU(config); + } + if (result == DriverResult::Success) { + result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::IR); + } + if (result == DriverResult::Success) { + result = ConfigureIrs(); + } + if (result == DriverResult::Success) { + result = WriteRegistersStep1(); + } + if (result == DriverResult::Success) { + result = WriteRegistersStep2(); + } + + is_enabled = true; + + SetNonBlocking(); + return result; +} + +DriverResult IrsProtocol::DisableIrs() { + LOG_DEBUG(Input, "Disable IRS"); + DriverResult result{DriverResult::Success}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = EnableMCU(false); + } + + is_enabled = false; + + SetNonBlocking(); + return result; +} + +DriverResult IrsProtocol::SetIrsConfig(IrsMode mode, IrsResolution format) { + irs_mode = mode; + switch (format) { + case IrsResolution::Size320x240: + resolution_code = IrsResolutionCode::Size320x240; + fragments = IrsFragments::Size320x240; + resolution = IrsResolution::Size320x240; + break; + case IrsResolution::Size160x120: + resolution_code = IrsResolutionCode::Size160x120; + fragments = IrsFragments::Size160x120; + resolution = IrsResolution::Size160x120; + break; + case IrsResolution::Size80x60: + resolution_code = IrsResolutionCode::Size80x60; + fragments = IrsFragments::Size80x60; + resolution = IrsResolution::Size80x60; + break; + case IrsResolution::Size20x15: + resolution_code = IrsResolutionCode::Size20x15; + fragments = IrsFragments::Size20x15; + resolution = IrsResolution::Size20x15; + break; + case IrsResolution::Size40x30: + default: + resolution_code = IrsResolutionCode::Size40x30; + fragments = IrsFragments::Size40x30; + resolution = IrsResolution::Size40x30; + break; + } + + // Restart feature + if (is_enabled) { + DisableIrs(); + return EnableIrs(); + } + + return DriverResult::Success; +} + +DriverResult IrsProtocol::RequestImage(std::span buffer) { + const u8 next_packet_fragment = + static_cast((packet_fragment + 1) % (static_cast(fragments) + 1)); + + if (buffer[0] == 0x31 && buffer[49] == 0x03) { + u8 new_packet_fragment = buffer[52]; + if (new_packet_fragment == next_packet_fragment) { + packet_fragment = next_packet_fragment; + memcpy(buf_image.data() + (300 * packet_fragment), buffer.data() + 59, 300); + + return RequestFrame(packet_fragment); + } + + if (new_packet_fragment == packet_fragment) { + return RequestFrame(packet_fragment); + } + + return ResendFrame(next_packet_fragment); + } + + return RequestFrame(packet_fragment); +} + +DriverResult IrsProtocol::ConfigureIrs() { + LOG_DEBUG(Input, "Configure IRS"); + constexpr std::size_t max_tries = 28; + std::vector output; + std::size_t tries = 0; + + const IrsConfigure irs_configuration{ + .command = MCUCommand::ConfigureIR, + .sub_command = MCUSubCommand::SetDeviceMode, + .irs_mode = IrsMode::ImageTransfer, + .number_of_fragments = fragments, + .mcu_major_version = 0x0500, + .mcu_minor_version = 0x1800, + .crc = {}, + }; + buf_image.resize((static_cast(fragments) + 1) * 300); + + std::vector request_data(sizeof(IrsConfigure)); + memcpy(request_data.data(), &irs_configuration, sizeof(IrsConfigure)); + request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); + do { + const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); + + if (result != DriverResult::Success) { + return result; + } + if (tries++ >= max_tries) { + return DriverResult::WrongReply; + } + } while (output[15] != 0x0b); + + return DriverResult::Success; +} + +DriverResult IrsProtocol::WriteRegistersStep1() { + LOG_DEBUG(Input, "WriteRegistersStep1"); + DriverResult result{DriverResult::Success}; + constexpr std::size_t max_tries = 28; + std::vector output; + std::size_t tries = 0; + + const IrsWriteRegisters irs_registers{ + .command = MCUCommand::ConfigureIR, + .sub_command = MCUSubCommand::WriteDeviceRegisters, + .number_of_registers = 0x9, + .registers = + { + IrsRegister{IrRegistersAddress::Resolution, static_cast(resolution_code)}, + {IrRegistersAddress::ExposureLSB, static_cast(exposure & 0xff)}, + {IrRegistersAddress::ExposureMSB, static_cast(exposure >> 8)}, + {IrRegistersAddress::ExposureTime, 0x00}, + {IrRegistersAddress::Leds, static_cast(leds)}, + {IrRegistersAddress::DigitalGainLSB, static_cast((digital_gain & 0x0f) << 4)}, + {IrRegistersAddress::DigitalGainMSB, static_cast((digital_gain & 0xf0) >> 4)}, + {IrRegistersAddress::LedFilter, static_cast(led_filter)}, + {IrRegistersAddress::WhitePixelThreshold, 0xc8}, + }, + .crc = {}, + }; + + std::vector request_data(sizeof(IrsWriteRegisters)); + memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters)); + request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); + + std::array mcu_request{0x02}; + mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); + mcu_request[37] = 0xFF; + + if (result != DriverResult::Success) { + return result; + } + + do { + result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); + + // First time we need to set the report mode + if (result == DriverResult::Success && tries == 0) { + result = SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request); + } + if (result == DriverResult::Success && tries == 0) { + GetSubCommandResponse(SubCommand::SET_MCU_CONFIG, output); + } + + if (result != DriverResult::Success) { + return result; + } + if (tries++ >= max_tries) { + return DriverResult::WrongReply; + } + } while (!(output[15] == 0x13 && output[17] == 0x07) && output[15] != 0x23); + + return DriverResult::Success; +} + +DriverResult IrsProtocol::WriteRegistersStep2() { + LOG_DEBUG(Input, "WriteRegistersStep2"); + constexpr std::size_t max_tries = 28; + std::vector output; + std::size_t tries = 0; + + const IrsWriteRegisters irs_registers{ + .command = MCUCommand::ConfigureIR, + .sub_command = MCUSubCommand::WriteDeviceRegisters, + .number_of_registers = 0x8, + .registers = + { + IrsRegister{IrRegistersAddress::LedIntensitiyMSB, + static_cast(led_intensity >> 8)}, + {IrRegistersAddress::LedIntensitiyLSB, static_cast(led_intensity & 0xff)}, + {IrRegistersAddress::ImageFlip, static_cast(image_flip)}, + {IrRegistersAddress::DenoiseSmoothing, static_cast((denoise >> 16) & 0xff)}, + {IrRegistersAddress::DenoiseEdge, static_cast((denoise >> 8) & 0xff)}, + {IrRegistersAddress::DenoiseColor, static_cast(denoise & 0xff)}, + {IrRegistersAddress::UpdateTime, 0x2d}, + {IrRegistersAddress::FinalizeConfig, 0x01}, + }, + .crc = {}, + }; + + std::vector request_data(sizeof(IrsWriteRegisters)); + memcpy(request_data.data(), &irs_registers, sizeof(IrsWriteRegisters)); + request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); + do { + const auto result = SendSubCommand(SubCommand::SET_MCU_CONFIG, request_data, output); + + if (result != DriverResult::Success) { + return result; + } + if (tries++ >= max_tries) { + return DriverResult::WrongReply; + } + } while (output[15] != 0x13 && output[15] != 0x23); + + return DriverResult::Success; +} + +DriverResult IrsProtocol::RequestFrame(u8 frame) { + std::array mcu_request{}; + mcu_request[3] = frame; + mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); + mcu_request[37] = 0xFF; + return SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request); +} + +DriverResult IrsProtocol::ResendFrame(u8 frame) { + std::array mcu_request{}; + mcu_request[1] = 0x1; + mcu_request[2] = frame; + mcu_request[3] = 0x0; + mcu_request[36] = CalculateMCU_CRC8(mcu_request.data(), 36); + mcu_request[37] = 0xFF; + return SendMcuCommand(SubCommand::SET_REPORT_MODE, mcu_request); +} + +std::vector IrsProtocol::GetImage() const { + return buf_image; +} + +IrsResolution IrsProtocol::GetIrsFormat() const { + return resolution; +} + +bool IrsProtocol::IsEnabled() const { + return is_enabled; +} + +} // namespace InputCommon::Joycon diff --git a/src/input_common/helpers/joycon_protocol/irs.h b/src/input_common/helpers/joycon_protocol/irs.h new file mode 100644 index 000000000..76dfa02ea --- /dev/null +++ b/src/input_common/helpers/joycon_protocol/irs.h @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// Based on dkms-hid-nintendo implementation, CTCaer joycon toolkit and dekuNukem reverse +// engineering https://github.com/nicman23/dkms-hid-nintendo/blob/master/src/hid-nintendo.c +// https://github.com/CTCaer/jc_toolkit +// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering + +#pragma once + +#include + +#include "input_common/helpers/joycon_protocol/common_protocol.h" +#include "input_common/helpers/joycon_protocol/joycon_types.h" + +namespace InputCommon::Joycon { + +class IrsProtocol final : private JoyconCommonProtocol { +public: + explicit IrsProtocol(std::shared_ptr handle); + + DriverResult EnableIrs(); + + DriverResult DisableIrs(); + + DriverResult SetIrsConfig(IrsMode mode, IrsResolution format); + + DriverResult RequestImage(std::span buffer); + + std::vector GetImage() const; + + IrsResolution GetIrsFormat() const; + + bool IsEnabled() const; + +private: + DriverResult ConfigureIrs(); + + DriverResult WriteRegistersStep1(); + DriverResult WriteRegistersStep2(); + + DriverResult RequestFrame(u8 frame); + DriverResult ResendFrame(u8 frame); + + IrsMode irs_mode{IrsMode::ImageTransfer}; + IrsResolution resolution{IrsResolution::Size40x30}; + IrsResolutionCode resolution_code{IrsResolutionCode::Size40x30}; + IrsFragments fragments{IrsFragments::Size40x30}; + IrLeds leds{IrLeds::BrightAndDim}; + IrExLedFilter led_filter{IrExLedFilter::Enabled}; + IrImageFlip image_flip{IrImageFlip::Normal}; + u8 digital_gain{0x01}; + u16 exposure{0x2490}; + u16 led_intensity{0x0f10}; + u32 denoise{0x012344}; + + u8 packet_fragment{}; + std::vector buf_image; // 8bpp greyscale image. + + bool is_enabled{}; +}; + +} // namespace InputCommon::Joycon diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index 36c00a8d7..273c8d07d 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h @@ -18,7 +18,7 @@ namespace InputCommon::Joycon { constexpr u32 MaxErrorCount = 50; -constexpr u32 MaxBufferSize = 60; +constexpr u32 MaxBufferSize = 368; constexpr u32 MaxResponseSize = 49; constexpr u32 MaxSubCommandResponseSize = 64; constexpr std::array DefaultVibrationBuffer{0x0, 0x1, 0x40, 0x40, 0x0, 0x1, 0x40, 0x40}; @@ -273,6 +273,80 @@ enum class NFCTagType : u8 { Ntag215 = 0x01, }; +enum class IrsMode : u8 { + None = 0x02, + Moment = 0x03, + Dpd = 0x04, + Clustering = 0x06, + ImageTransfer = 0x07, + Silhouette = 0x08, + TeraImage = 0x09, + SilhouetteTeraImage = 0x0A, +}; + +enum class IrsResolution { + Size320x240, + Size160x120, + Size80x60, + Size40x30, + Size20x15, + None, +}; + +enum class IrsResolutionCode : u8 { + Size320x240 = 0x00, // Full pixel array + Size160x120 = 0x50, // Sensor Binning [2 X 2] + Size80x60 = 0x64, // Sensor Binning [4 x 2] and Skipping [1 x 2] + Size40x30 = 0x69, // Sensor Binning [4 x 2] and Skipping [2 x 4] + Size20x15 = 0x6A, // Sensor Binning [4 x 2] and Skipping [4 x 4] +}; + +// Size of image divided by 300 +enum class IrsFragments : u8 { + Size20x15 = 0x00, + Size40x30 = 0x03, + Size80x60 = 0x0f, + Size160x120 = 0x3f, + Size320x240 = 0xFF, +}; + +enum class IrLeds : u8 { + BrightAndDim = 0x00, + Bright = 0x20, + Dim = 0x10, + None = 0x30, +}; + +enum class IrExLedFilter : u8 { + Disabled = 0x00, + Enabled = 0x03, +}; + +enum class IrImageFlip : u8 { + Normal = 0x00, + Inverted = 0x02, +}; + +enum class IrRegistersAddress : u16 { + UpdateTime = 0x0400, + FinalizeConfig = 0x0700, + LedFilter = 0x0e00, + Leds = 0x1000, + LedIntensitiyMSB = 0x1100, + LedIntensitiyLSB = 0x1200, + ImageFlip = 0x2d00, + Resolution = 0x2e00, + DigitalGainLSB = 0x2e01, + DigitalGainMSB = 0x2f01, + ExposureLSB = 0x3001, + ExposureMSB = 0x3101, + ExposureTime = 0x3201, + WhitePixelThreshold = 0x4301, + DenoiseSmoothing = 0x6701, + DenoiseEdge = 0x6801, + DenoiseColor = 0x6901, +}; + enum class DriverResult { Success, WrongReply, @@ -456,6 +530,36 @@ struct NFCRequestState { }; static_assert(sizeof(NFCRequestState) == 0x26, "NFCRequestState is an invalid size"); +struct IrsConfigure { + MCUCommand command; + MCUSubCommand sub_command; + IrsMode irs_mode; + IrsFragments number_of_fragments; + u16 mcu_major_version; + u16 mcu_minor_version; + INSERT_PADDING_BYTES(0x1D); + u8 crc; +}; +static_assert(sizeof(IrsConfigure) == 0x26, "IrsConfigure is an invalid size"); + +#pragma pack(push, 1) +struct IrsRegister { + IrRegistersAddress address; + u8 value; +}; +static_assert(sizeof(IrsRegister) == 0x3, "IrsRegister is an invalid size"); + +struct IrsWriteRegisters { + MCUCommand command; + MCUSubCommand sub_command; + u8 number_of_registers; + std::array registers; + INSERT_PADDING_BYTES(0x7); + u8 crc; +}; +static_assert(sizeof(IrsWriteRegisters) == 0x26, "IrsWriteRegisters is an invalid size"); +#pragma pack(pop) + struct FirmwareVersion { u8 major; u8 minor; @@ -490,6 +594,7 @@ struct JoyconCallbacks { std::function on_motion_data; std::function on_ring_data; std::function&)> on_amiibo_data; + std::function&, IrsResolution)> on_camera_data; }; } // namespace InputCommon::Joycon diff --git a/src/input_common/helpers/joycon_protocol/poller.cpp b/src/input_common/helpers/joycon_protocol/poller.cpp index fd05d98f3..940b20b7f 100644 --- a/src/input_common/helpers/joycon_protocol/poller.cpp +++ b/src/input_common/helpers/joycon_protocol/poller.cpp @@ -74,10 +74,14 @@ void JoyconPoller::UpdateColor(const Color& color) { callbacks.on_color_data(color); } -void JoyconPoller::updateAmiibo(const std::vector& amiibo_data) { +void JoyconPoller::UpdateAmiibo(const std::vector& amiibo_data) { callbacks.on_amiibo_data(amiibo_data); } +void JoyconPoller::UpdateCamera(const std::vector& camera_data, IrsResolution format) { + callbacks.on_camera_data(camera_data, format); +} + void JoyconPoller::UpdateRing(s16 value, const RingStatus& ring_status) { float normalized_value = static_cast(value - ring_status.default_value); if (normalized_value > 0) { diff --git a/src/input_common/helpers/joycon_protocol/poller.h b/src/input_common/helpers/joycon_protocol/poller.h index c40fc7bca..354d41dad 100644 --- a/src/input_common/helpers/joycon_protocol/poller.h +++ b/src/input_common/helpers/joycon_protocol/poller.h @@ -36,7 +36,8 @@ public: void UpdateColor(const Color& color); void UpdateRing(s16 value, const RingStatus& ring_status); - void updateAmiibo(const std::vector& amiibo_data); + void UpdateAmiibo(const std::vector& amiibo_data); + void UpdateCamera(const std::vector& amiibo_data, IrsResolution format); private: void UpdateActiveLeftPadInput(const InputReportActive& input, -- cgit v1.2.3 From d05ea2f3ebdf62e328d2edbfc5b9bc01e3453569 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 2 Jan 2023 22:11:03 -0600 Subject: input_common: Fix issue where ring and irs are enabled at the same time --- src/core/hle/service/hid/irs.cpp | 4 +-- src/input_common/helpers/joycon_driver.cpp | 30 ++++++++++++++-------- src/input_common/helpers/joycon_driver.h | 1 + .../helpers/joycon_protocol/common_protocol.cpp | 4 +-- 4 files changed, 24 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 3c1fa2274..1a6fa2a44 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -74,8 +74,6 @@ void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); - npad_device->SetPollingMode(Common::Input::PollingMode::Active); - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -514,7 +512,7 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { auto result = IsIrCameraHandleValid(parameters.camera_handle); if (result.IsSuccess()) { // TODO: Stop image processor async - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Common::Input::PollingMode::Active); result = ResultSuccess; } diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index 040832a4b..e8aef028a 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -262,6 +262,16 @@ DriverResult JoyconDriver::SetPollingMode() { irs_protocol->DisableIrs(); } + if (nfc_protocol->IsEnabled()) { + amiibo_detected = false; + nfc_protocol->DisableNfc(); + } + + if (ring_protocol->IsEnabled()) { + ring_connected = false; + ring_protocol->DisableRingCon(); + } + if (irs_enabled && supported_features.irs) { auto result = irs_protocol->EnableIrs(); if (result == DriverResult::Success) { @@ -272,11 +282,6 @@ DriverResult JoyconDriver::SetPollingMode() { LOG_ERROR(Input, "Error enabling IRS"); } - if (nfc_protocol->IsEnabled()) { - amiibo_detected = false; - nfc_protocol->DisableNfc(); - } - if (nfc_enabled && supported_features.nfc) { auto result = nfc_protocol->EnableNfc(); if (result == DriverResult::Success) { @@ -290,11 +295,6 @@ DriverResult JoyconDriver::SetPollingMode() { LOG_ERROR(Input, "Error enabling NFC"); } - if (ring_protocol->IsEnabled()) { - ring_connected = false; - ring_protocol->DisableRingCon(); - } - if (hidbus_enabled && supported_features.hidbus) { auto result = ring_protocol->EnableRingCon(); if (result == DriverResult::Success) { @@ -418,6 +418,12 @@ DriverResult JoyconDriver::SetPasiveMode() { } DriverResult JoyconDriver::SetActiveMode() { + if (is_ring_disabled_by_irs) { + is_ring_disabled_by_irs = false; + SetActiveMode(); + return SetRingConMode(); + } + std::scoped_lock lock{mutex}; motion_enabled = true; hidbus_enabled = false; @@ -434,6 +440,10 @@ DriverResult JoyconDriver::SetIrMode() { return DriverResult::NotSupported; } + if (ring_connected) { + is_ring_disabled_by_irs = true; + } + motion_enabled = false; hidbus_enabled = false; nfc_enabled = false; diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index 61ecf4a6c..e8e65e133 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h @@ -107,6 +107,7 @@ private: bool starlink_connected{}; bool ring_connected{}; bool amiibo_detected{}; + bool is_ring_disabled_by_irs{}; // Harware configuration u8 leds{}; diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index a329db107..153a3908c 100644 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp @@ -74,8 +74,8 @@ DriverResult JoyconCommonProtocol::SendData(std::span buffer) { } DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, std::vector& output) { - constexpr int timeout_mili = 100; - constexpr int MaxTries = 10; + constexpr int timeout_mili = 66; + constexpr int MaxTries = 15; int tries = 0; output.resize(MaxSubCommandResponseSize); -- cgit v1.2.3 From 4a307a7b3aa3afea7d62674f6cf40b76f3ffb5e3 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Fri, 13 Jan 2023 13:39:33 -0600 Subject: core: hid: Only set the polling mode to the correct side --- src/core/hid/emulated_controller.cpp | 28 +++++++++++++++++++-------- src/core/hid/emulated_controller.h | 4 +++- src/core/hle/service/hid/controllers/npad.cpp | 14 +++++++++++++- src/core/hle/service/hid/hidbus/ringcon.cpp | 6 ++++-- src/core/hle/service/hid/irs.cpp | 27 +++++++++++++++++--------- src/core/hle/service/nfc/nfc_device.cpp | 6 ++++-- src/core/hle/service/nfp/nfp_device.cpp | 6 ++++-- src/yuzu/configuration/configure_ringcon.cpp | 6 ++++-- 8 files changed, 70 insertions(+), 27 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index faf9e7c4e..f83abad05 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -1208,19 +1208,31 @@ bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { } Common::Input::DriverResult EmulatedController::SetPollingMode( - Common::Input::PollingMode polling_mode) { - LOG_INFO(Service_HID, "Set polling mode {}", polling_mode); - auto& output_device = output_devices[static_cast(DeviceIndex::Right)]; + EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) { + LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index); + + auto& left_output_device = output_devices[static_cast(DeviceIndex::Left)]; + auto& right_output_device = output_devices[static_cast(DeviceIndex::Right)]; auto& nfc_output_device = output_devices[3]; - const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); - const auto mapped_nfc_result = output_device->SetPollingMode(polling_mode); + if (device_index == EmulatedDeviceIndex::LeftIndex) { + return left_output_device->SetPollingMode(polling_mode); + } - if (virtual_nfc_result == Common::Input::DriverResult::Success) { - return virtual_nfc_result; + if (device_index == EmulatedDeviceIndex::RightIndex) { + const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); + const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode); + + if (virtual_nfc_result == Common::Input::DriverResult::Success) { + return virtual_nfc_result; + } + return mapped_nfc_result; } - return mapped_nfc_result; + left_output_device->SetPollingMode(polling_mode); + right_output_device->SetPollingMode(polling_mode); + nfc_output_device->SetPollingMode(polling_mode); + return Common::Input::DriverResult::Success; } bool EmulatedController::SetCameraFormat( diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index edebfc15c..3ac77b2b5 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -363,10 +363,12 @@ public: /** * Sets the desired data to be polled from a controller + * @param device_index index of the controller to set the polling mode * @param polling_mode type of input desired buttons, gyro, nfc, ir, etc. * @return driver result from this command */ - Common::Input::DriverResult SetPollingMode(Common::Input::PollingMode polling_mode); + Common::Input::DriverResult SetPollingMode(EmulatedDeviceIndex device_index, + Common::Input::PollingMode polling_mode); /** * Sets the desired camera format to be polled from a controller diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index fe5bf94d2..5713f1288 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -337,7 +337,19 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { controller.is_connected = true; controller.device->Connect(); controller.device->SetLedPattern(); - controller.device->SetPollingMode(Common::Input::PollingMode::Active); + if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) { + if (controller.is_dual_left_connected) { + controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex, + Common::Input::PollingMode::Active); + } + if (controller.is_dual_right_connected) { + controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); + } + } else { + controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, + Common::Input::PollingMode::Active); + } SignalStyleSetChangedEvent(npad_id); WriteEmptyEntry(controller.shared_memory); } diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index af776d506..78ed47014 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -18,12 +18,14 @@ RingController::RingController(Core::HID::HIDCore& hid_core_, RingController::~RingController() = default; void RingController::OnInit() { - input->SetPollingMode(Common::Input::PollingMode::Ring); + input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Ring); return; } void RingController::OnRelease() { - input->SetPollingMode(Common::Input::PollingMode::Active); + input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); return; }; diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 1a6fa2a44..52f402c56 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -108,7 +108,8 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { auto result = IsIrCameraHandleValid(parameters.camera_handle); if (result.IsSuccess()) { // TODO: Stop Image processor - npad_device->SetPollingMode(Common::Input::PollingMode::Active); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); result = ResultSuccess; } @@ -140,7 +141,8 @@ void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor(parameters.camera_handle, device); auto& image_transfer_processor = GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -172,7 +174,8 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -222,7 +225,8 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); image_transfer_processor.SetTransferMemoryPointer(transfer_memory); - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -298,7 +302,8 @@ void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { auto& image_transfer_processor = GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -348,7 +353,8 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor(camera_handle, device); auto& image_transfer_processor = GetProcessor(camera_handle); image_transfer_processor.SetConfig(processor_config); - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -459,7 +465,8 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { GetProcessor(parameters.camera_handle); image_transfer_processor.SetConfig(parameters.processor_config); image_transfer_processor.SetTransferMemoryPointer(transfer_memory); - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -486,7 +493,8 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { MakeProcessor(camera_handle, device); auto& image_transfer_processor = GetProcessor(camera_handle); image_transfer_processor.SetConfig(processor_config); - npad_device->SetPollingMode(Common::Input::PollingMode::IR); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::IR); } IPC::ResponseBuilder rb{ctx, 2}; @@ -512,7 +520,8 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { auto result = IsIrCameraHandleValid(parameters.camera_handle); if (result.IsSuccess()) { // TODO: Stop image processor async - npad_device->SetPollingMode(Common::Input::PollingMode::Active); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); result = ResultSuccess; } diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp index c9815edbc..9a3234e8c 100644 --- a/src/core/hle/service/nfc/nfc_device.cpp +++ b/src/core/hle/service/nfc/nfc_device.cpp @@ -130,7 +130,8 @@ Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) { return WrongDeviceState; } - if (npad_device->SetPollingMode(Common::Input::PollingMode::NFC) != + if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::NFC) != Common::Input::DriverResult::Success) { LOG_ERROR(Service_NFC, "Nfc not supported"); return NfcDisabled; @@ -142,7 +143,8 @@ Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) { } Result NfcDevice::StopDetection() { - npad_device->SetPollingMode(Common::Input::PollingMode::Active); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); if (device_state == NFP::DeviceState::Initialized) { return ResultSuccess; diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index 7b8013961..e67a76f55 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -152,7 +152,8 @@ Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { return WrongDeviceState; } - if (npad_device->SetPollingMode(Common::Input::PollingMode::NFC) != + if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::NFC) != Common::Input::DriverResult::Success) { LOG_ERROR(Service_NFP, "Nfc not supported"); return NfcDisabled; @@ -164,7 +165,8 @@ Result NfpDevice::StartDetection(TagProtocol allowed_protocol) { } Result NfpDevice::StopDetection() { - npad_device->SetPollingMode(Common::Input::PollingMode::Active); + npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); if (device_state == DeviceState::Initialized) { return ResultSuccess; diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index 697c36fb4..1275f10c8 100644 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ b/src/yuzu/configuration/configure_ringcon.cpp @@ -214,7 +214,8 @@ ConfigureRingController::ConfigureRingController(QWidget* parent, } ConfigureRingController::~ConfigureRingController() { - emulated_controller->SetPollingMode(Common::Input::PollingMode::Active); + emulated_controller->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, + Common::Input::PollingMode::Active); emulated_controller->DisableConfiguration(); if (is_controller_set) { @@ -290,7 +291,8 @@ void ConfigureRingController::EnableRingController() { // SetPollingMode is blocking. Allow to update the button status before calling the command repaint(); - const auto result = emulated_controller->SetPollingMode(Common::Input::PollingMode::Ring); + const auto result = emulated_controller->SetPollingMode( + Core::HID::EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Ring); switch (result) { case Common::Input::DriverResult::Success: is_ring_enabled = true; -- cgit v1.2.3 From d9ee7c32975bb8d840cf93a086d6b4be39d7bfd2 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 19 Jan 2023 20:20:19 -0600 Subject: core: hid: Make use of SCOPE_EXIT and SCOPE_GUARD where applicable --- src/core/hid/emulated_controller.cpp | 105 +++++++++++++---------------------- 1 file changed, 38 insertions(+), 67 deletions(-) (limited to 'src/core') diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index f83abad05..0e06468da 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "common/polyfill_ranges.h" #include "common/thread.h" @@ -834,17 +835,21 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, if (index >= controller.stick_values.size()) { return; } - std::unique_lock lock{mutex}; + auto trigger_guard = + SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); }); + std::scoped_lock lock{mutex}; 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) { const bool is_tas = uuid == TAS_UUID; if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) { + trigger_guard.Cancel(); return; } if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) { + trigger_guard.Cancel(); return; } } @@ -855,8 +860,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, if (is_configuring) { controller.analog_stick_state.left = {}; controller.analog_stick_state.right = {}; - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Stick, false); return; } @@ -881,9 +884,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); break; } - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Stick, true); } void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback, @@ -891,7 +891,9 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac if (index >= controller.trigger_values.size()) { return; } - std::unique_lock lock{mutex}; + auto trigger_guard = + SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); }); + std::scoped_lock lock{mutex}; const auto trigger_value = TransformToTrigger(callback); // Only read trigger values that have the same uuid or are pressed once @@ -907,13 +909,12 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac if (is_configuring) { controller.gc_trigger_state.left = 0; controller.gc_trigger_state.right = 0; - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Trigger, false); return; } // Only GC controllers have analog triggers if (npad_type != NpadStyleIndex::GameCube) { + trigger_guard.Cancel(); return; } @@ -930,9 +931,6 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac controller.npad_button_state.zr.Assign(trigger.pressed.value); break; } - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Trigger, true); } void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback, @@ -940,7 +938,8 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback if (index >= controller.motion_values.size()) { return; } - std::unique_lock lock{mutex}; + SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); }); + std::scoped_lock lock{mutex}; auto& raw_status = controller.motion_values[index].raw_status; auto& emulated = controller.motion_values[index].emulated; @@ -961,8 +960,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback force_update_motion = raw_status.force_update; if (is_configuring) { - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Motion, false); return; } @@ -972,9 +969,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback motion.rotation = emulated.GetRotations(); motion.orientation = emulated.GetOrientation(); motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Motion, true); } void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback, @@ -982,16 +976,17 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback if (index >= controller.color_values.size()) { return; } - std::unique_lock lock{mutex}; + auto trigger_guard = + SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); }); + std::scoped_lock lock{mutex}; controller.color_values[index] = TransformToColor(callback); if (is_configuring) { - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Color, false); return; } if (controller.color_values[index].body == 0) { + trigger_guard.Cancel(); return; } @@ -1024,9 +1019,6 @@ void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback break; } } - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Color, true); } void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, @@ -1034,12 +1026,11 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac if (index >= controller.battery_values.size()) { return; } - std::unique_lock lock{mutex}; + SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); }); + std::scoped_lock lock{mutex}; controller.battery_values[index] = TransformToBattery(callback); if (is_configuring) { - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Battery, false); return; } @@ -1095,18 +1086,14 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac }; break; } - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Battery, true); } void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) { - std::unique_lock lock{mutex}; + SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); }); + std::scoped_lock lock{mutex}; controller.camera_values = TransformToCamera(callback); if (is_configuring) { - lock.unlock(); - TriggerOnChange(ControllerTriggerType::IrSensor, false); return; } @@ -1114,36 +1101,28 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback controller.camera_state.format = static_cast(controller.camera_values.format); controller.camera_state.data = controller.camera_values.data; - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::IrSensor, true); } void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) { - std::unique_lock lock{mutex}; + SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); }); + std::scoped_lock lock{mutex}; const auto force_value = TransformToStick(callback); controller.ring_analog_value = force_value.x; if (is_configuring) { - lock.unlock(); - TriggerOnChange(ControllerTriggerType::RingController, false); return; } controller.ring_analog_state.force = force_value.x.value; - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::RingController, true); } void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { - std::unique_lock lock{mutex}; + SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); }); + std::scoped_lock lock{mutex}; controller.nfc_values = TransformToNfc(callback); if (is_configuring) { - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Nfc, false); return; } @@ -1151,9 +1130,6 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { controller.nfc_values.state, controller.nfc_values.data, }; - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Nfc, true); } bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { @@ -1412,39 +1388,35 @@ void EmulatedController::Connect(bool use_temporary_value) { return; } - std::unique_lock lock{mutex}; + auto trigger_guard = + SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); }); + std::scoped_lock lock{mutex}; if (is_configuring) { tmp_is_connected = true; - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Connected, false); return; } if (is_connected) { + trigger_guard.Cancel(); return; } is_connected = true; - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Connected, true); } void EmulatedController::Disconnect() { - std::unique_lock lock{mutex}; + auto trigger_guard = + SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); }); + std::scoped_lock lock{mutex}; if (is_configuring) { tmp_is_connected = false; - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Disconnected, false); return; } if (!is_connected) { + trigger_guard.Cancel(); return; } is_connected = false; - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Disconnected, true); } bool EmulatedController::IsConnected(bool get_temporary_value) const { @@ -1469,19 +1441,21 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c } void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { - std::unique_lock lock{mutex}; + auto trigger_guard = + SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); }); + std::scoped_lock lock{mutex}; if (is_configuring) { if (tmp_npad_type == npad_type_) { + trigger_guard.Cancel(); return; } tmp_npad_type = npad_type_; - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Type, false); return; } if (npad_type == npad_type_) { + trigger_guard.Cancel(); return; } if (is_connected) { @@ -1489,9 +1463,6 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { NpadIdTypeToIndex(npad_id_type)); } npad_type = npad_type_; - - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Type, true); } LedPattern EmulatedController::GetLedPattern() const { @@ -1589,7 +1560,7 @@ DebugPadButton EmulatedController::GetDebugPadButtons() const { } AnalogSticks EmulatedController::GetSticks() const { - std::unique_lock lock{mutex}; + std::scoped_lock lock{mutex}; if (is_configuring) { return {}; -- cgit v1.2.3