From 82996261c6e92652e29f64503c3c6ddd4a2c4d37 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Tue, 27 Dec 2022 08:58:30 +0100 Subject: [PATCH] early-access version 3258 --- README.md | 2 +- src/common/input.h | 46 +- src/core/hid/emulated_controller.cpp | 16 +- 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/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 | 11 +- src/input_common/drivers/virtual_amiibo.h | 2 +- src/input_common/helpers/joycon_driver.cpp | 64 +-- src/input_common/helpers/joycon_driver.h | 12 +- .../helpers/joycon_protocol/joycon_types.h | 1 + src/input_common/input_engine.h | 19 +- src/input_common/input_poller.cpp | 11 +- src/yuzu/configuration/configure_ringcon.cpp | 69 +++ src/yuzu/configuration/configure_ringcon.h | 10 + src/yuzu/configuration/configure_ringcon.ui | 420 +++++++++++------- 24 files changed, 480 insertions(+), 288 deletions(-) diff --git a/README.md b/README.md index 3c4237f7e..c5b24c747 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3256. +This is the source code for early-access 3258. ## Legal Notice diff --git a/src/common/input.h b/src/common/input.h index 72c0f6159..3f5040760 100755 --- 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, +// Different results that can happen from a device request +enum class DriverResult { + Success, + WrongReply, + Timeout, + UnsupportedControllerType, + HandleInUse, + ErrorReadingData, + ErrorWritingData, + NoDeviceDetected, + InvalidHandle, NotSupported, Disabled, - InvalidHandle, - Unknown, -}; - -// Polling mode reply from the controller -enum class PollingError { - None, - NotSupported, - InvalidHandle, 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, @@ -339,22 +331,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 e1ae1f250..b967cd479 100755 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -1176,7 +1176,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) { @@ -1198,7 +1198,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]; @@ -1206,8 +1207,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::PollingError::None || - mapped_nfc_result == Common::Input::PollingError::None; + if (virtual_nfc_result == Common::Input::DriverResult::Success) { + return virtual_nfc_result; + } + + return mapped_nfc_result; } bool EmulatedController::SetCameraFormat( @@ -1218,13 +1222,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/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index b406eef82..bee90562b 100755 --- 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 100755 --- 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 517ed0564..8aff01dff 100755 --- 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/camera.cpp b/src/input_common/drivers/camera.cpp index ba611fbfd..8982b8958 100755 --- 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 833ca0768..6a61c0ff0 100755 --- 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 3f6ca5f1b..493725631 100755 --- 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 d7e2fb1be..fd259f9fd 100755 --- 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 100755 --- 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 100755 --- 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 675054de6..36b37cc0d 100755 --- 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 104508520..bb032bc9a 100755 --- 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 ba9a478ee..a6c460bd2 100755 --- a/src/input_common/drivers/virtual_amiibo.cpp +++ b/src/input_common/drivers/virtual_amiibo.cpp @@ -22,22 +22,23 @@ 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_; - 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::PollingError::None; } Common::Input::NfcState VirtualAmiibo::SupportsNfc( diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h index 8d6b0d2b9..4d0073294 100755 --- 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..8217ba7f6 100755 --- 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 { @@ -459,23 +473,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 +501,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..5ff15c784 100755 --- 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 { @@ -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/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index de512fe63..36c00a8d7 100755 --- 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 612f845a6..1148b82fd 100755 --- 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 627f7476d..6daa96eeb 100755 --- 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); } diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index 6b5652857..bbc9b3b4f 100755 --- 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 6ee87c9f9..3347c9e6c 100755 --- 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 3a608ded6..b50c4a966 100755 --- 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 - - - - - Pull - - - Qt::AlignCenter - - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - min-width: 68px; - - - Pull - - - - - - - - - - Push - - - Qt::AlignCenter - - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - min-width: 68px; - - - Push - - - - - - - - - - - - 3 + 0 - QLayout::SetDefaultConstraint + QLayout::SetDefaultConstraint - 0 + 3 - 10 + 6 - 0 + 3 - 3 + 0 - - - - - Deadzone: 0% + + + 3 + + + + + Pull - Qt::AlignHCenter + Qt::AlignCenter - + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 70 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + Pull + + + + + - + + + + Push + + + Qt::AlignCenter + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 70 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + Push + + + + + + + - - - 100 + + + 3 - - Qt::Horizontal + + QLayout::SetDefaultConstraint - + + 0 + + + 10 + + + 0 + + + 3 + + + + + + + Deadzone: 0% + + + Qt::AlignHCenter + + + + + + + + + 100 + + + Qt::Horizontal + + + + - - - - - + + + + + + + Direct Joycon Driver + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + 0 + + + QLayout::SetDefaultConstraint + + + 3 + + + 6 + + + 3 + + + 10 + + + + + 10 + + + 6 + + + 10 + + + 10 + + + 10 + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 76 + 20 + + + + + + + + Enable Ring Input + + + + + + + Enable + + + + + + + Ring Sensor Value + + + + + + + Not connected + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + @@ -273,6 +369,6 @@ rejected() ConfigureRingController reject() - +