From 751d36e7392b0b1637f17988cfc1ef0d7cd95753 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 20 Dec 2022 19:10:42 -0600 Subject: input_common: Add support for joycon ring controller --- .../helpers/joycon_protocol/ringcon.cpp | 132 +++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/input_common/helpers/joycon_protocol/ringcon.cpp (limited to 'src/input_common/helpers/joycon_protocol/ringcon.cpp') diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp new file mode 100644 index 000000000..2d137b85d --- /dev/null +++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "input_common/helpers/joycon_protocol/ringcon.h" + +namespace InputCommon::Joycon { + +RingConProtocol::RingConProtocol(std::shared_ptr handle) + : JoyconCommonProtocol(handle) {} + +DriverResult RingConProtocol::EnableRingCon() { + LOG_DEBUG(Input, "Enable Ringcon"); + DriverResult result{DriverResult::Success}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); + } + if (result == DriverResult::Success) { + result = EnableMCU(true); + } + if (result == DriverResult::Success) { + const MCUConfig config{ + .command = MCUCommand::ConfigureMCU, + .sub_command = MCUSubCommand::SetDeviceMode, + .mode = MCUMode::Standby, + .crc = {}, + }; + result = ConfigureMCU(config); + } + + SetNonBlocking(); + return result; +} + +DriverResult RingConProtocol::DisableRingCon() { + LOG_DEBUG(Input, "Disable RingCon"); + DriverResult result{DriverResult::Success}; + SetBlocking(); + + if (result == DriverResult::Success) { + result = EnableMCU(false); + } + + is_enabled = false; + + SetNonBlocking(); + return result; +} + +DriverResult RingConProtocol::StartRingconPolling() { + LOG_DEBUG(Input, "Enable Ringcon"); + bool is_connected = false; + 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); + } + if (result == DriverResult::Success && is_connected) { + LOG_INFO(Input, "Ringcon detected"); + result = ConfigureRing(); + } + if (result == DriverResult::Success) { + is_enabled = true; + } + + SetNonBlocking(); + return result; +} + +DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { + LOG_DEBUG(Input, "IsRingConnected"); + constexpr std::size_t max_tries = 28; + std::vector output; + std::size_t tries = 0; + is_connected = false; + + do { + std::vector empty_data(0); + const auto result = SendSubCommand(SubCommand::UNKNOWN_RINGCON, empty_data, output); + + if (result != DriverResult::Success) { + return result; + } + + if (tries++ >= max_tries) { + return DriverResult::NoDeviceDetected; + } + } while (output[14] != 0x59 || output[16] != 0x20); + + is_connected = true; + return DriverResult::Success; +} + +DriverResult RingConProtocol::ConfigureRing() { + LOG_DEBUG(Input, "ConfigureRing"); + constexpr std::size_t max_tries = 28; + DriverResult result{DriverResult::Success}; + std::vector output; + std::size_t tries = 0; + + 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) { + return result; + } + if (tries++ >= max_tries) { + return DriverResult::NoDeviceDetected; + } + } while (output[14] != 0x5C); + + std::vector ringcon_data{0x04, 0x01, 0x01, 0x02}; + result = SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data, output); + + return result; +} + +bool RingConProtocol::IsEnabled() { + return is_enabled; +} + +} // namespace InputCommon::Joycon -- 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/input_common/helpers/joycon_protocol/ringcon.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/input_common/helpers/joycon_protocol/ringcon.cpp') 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/input_common/helpers/joycon_protocol/ringcon.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/input_common/helpers/joycon_protocol/ringcon.cpp') 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; } -- cgit v1.2.3 From 340f15d1fa79594dbe12a6e19140ba012751b533 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 13 Jan 2023 23:29:05 -0600 Subject: input_common: Address byte review --- .../helpers/joycon_protocol/ringcon.cpp | 36 ++++++++-------------- 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'src/input_common/helpers/joycon_protocol/ringcon.cpp') diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp index 8adad57dd..12f81309e 100644 --- a/src/input_common/helpers/joycon_protocol/ringcon.cpp +++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp @@ -11,8 +11,8 @@ RingConProtocol::RingConProtocol(std::shared_ptr handle) DriverResult RingConProtocol::EnableRingCon() { LOG_DEBUG(Input, "Enable Ringcon"); + ScopedSetBlocking sb(this); DriverResult result{DriverResult::Success}; - SetBlocking(); if (result == DriverResult::Success) { result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); @@ -30,14 +30,13 @@ DriverResult RingConProtocol::EnableRingCon() { result = ConfigureMCU(config); } - SetNonBlocking(); return result; } DriverResult RingConProtocol::DisableRingCon() { LOG_DEBUG(Input, "Disable RingCon"); + ScopedSetBlocking sb(this); DriverResult result{DriverResult::Success}; - SetBlocking(); if (result == DriverResult::Success) { result = EnableMCU(false); @@ -45,15 +44,14 @@ DriverResult RingConProtocol::DisableRingCon() { is_enabled = false; - SetNonBlocking(); return result; } DriverResult RingConProtocol::StartRingconPolling() { LOG_DEBUG(Input, "Enable Ringcon"); - bool is_connected = false; + ScopedSetBlocking sb(this); DriverResult result{DriverResult::Success}; - SetBlocking(); + bool is_connected = false; if (result == DriverResult::Success) { result = IsRingConnected(is_connected); @@ -66,13 +64,13 @@ DriverResult RingConProtocol::StartRingconPolling() { is_enabled = true; } - SetNonBlocking(); return result; } DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { LOG_DEBUG(Input, "IsRingConnected"); constexpr std::size_t max_tries = 28; + constexpr u8 ring_controller_id = 0x20; std::vector output; std::size_t tries = 0; is_connected = false; @@ -88,7 +86,7 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { if (tries++ >= max_tries) { return DriverResult::NoDeviceDetected; } - } while (output[14] != 0x59 || output[16] != 0x20); + } while (output[16] != ring_controller_id); is_connected = true; return DriverResult::Success; @@ -96,30 +94,20 @@ DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { DriverResult RingConProtocol::ConfigureRing() { LOG_DEBUG(Input, "ConfigureRing"); - constexpr std::size_t max_tries = 28; - DriverResult result{DriverResult::Success}; - 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 { - result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config, output); - if (result != DriverResult::Success) { - return result; - } - if (tries++ >= max_tries) { - return DriverResult::NoDeviceDetected; - } - } while (output[14] != 0x5C); + const DriverResult result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config); - static constexpr std::array ringcon_data{0x04, 0x01, 0x01, 0x02}; - result = SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data, output); + if (result != DriverResult::Success) { + return result; + } - return result; + static constexpr std::array ringcon_data{0x04, 0x01, 0x01, 0x02}; + return SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data); } bool RingConProtocol::IsEnabled() const { -- cgit v1.2.3