| |
| |
|
|
| #include "common/input.h" |
| #include "common/logging/log.h" |
| #include "input_common/helpers/joycon_protocol/ringcon.h" |
|
|
| namespace InputCommon::Joycon { |
|
|
| RingConProtocol::RingConProtocol(std::shared_ptr<JoyconHandle> handle) |
| : JoyconCommonProtocol(std::move(handle)) {} |
|
|
| Common::Input::DriverResult RingConProtocol::EnableRingCon() { |
| LOG_DEBUG(Input, "Enable Ringcon"); |
| ScopedSetBlocking sb(this); |
| Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
|
|
| if (result == Common::Input::DriverResult::Success) { |
| result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); |
| } |
| if (result == Common::Input::DriverResult::Success) { |
| result = EnableMCU(true); |
| } |
| if (result == Common::Input::DriverResult::Success) { |
| const MCUConfig config{ |
| .command = MCUCommand::ConfigureMCU, |
| .sub_command = MCUSubCommand::SetDeviceMode, |
| .mode = MCUMode::Standby, |
| .crc = {}, |
| }; |
| result = ConfigureMCU(config); |
| } |
|
|
| return result; |
| } |
|
|
| Common::Input::DriverResult RingConProtocol::DisableRingCon() { |
| LOG_DEBUG(Input, "Disable RingCon"); |
| ScopedSetBlocking sb(this); |
| Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
|
|
| if (result == Common::Input::DriverResult::Success) { |
| result = EnableMCU(false); |
| } |
|
|
| is_enabled = false; |
|
|
| return result; |
| } |
|
|
| Common::Input::DriverResult RingConProtocol::StartRingconPolling() { |
| LOG_DEBUG(Input, "Enable Ringcon"); |
| ScopedSetBlocking sb(this); |
| Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| bool is_connected = false; |
|
|
| if (result == Common::Input::DriverResult::Success) { |
| result = IsRingConnected(is_connected); |
| } |
| if (result == Common::Input::DriverResult::Success && is_connected) { |
| LOG_INFO(Input, "Ringcon detected"); |
| result = ConfigureRing(); |
| } |
| if (result == Common::Input::DriverResult::Success) { |
| is_enabled = true; |
| } |
|
|
| return result; |
| } |
|
|
| Common::Input::DriverResult RingConProtocol::IsRingConnected(bool& is_connected) { |
| LOG_DEBUG(Input, "IsRingConnected"); |
| constexpr std::size_t max_tries = 42; |
| SubCommandResponse output{}; |
| std::size_t tries = 0; |
| is_connected = false; |
|
|
| do { |
| const auto result = SendSubCommand(SubCommand::GET_EXTERNAL_DEVICE_INFO, {}, output); |
|
|
| if (result != Common::Input::DriverResult::Success && |
| result != Common::Input::DriverResult::Timeout) { |
| return result; |
| } |
|
|
| if (tries++ >= max_tries) { |
| return Common::Input::DriverResult::NoDeviceDetected; |
| } |
| } while (output.external_device_id != ExternalDeviceId::RingController); |
|
|
| is_connected = true; |
| return Common::Input::DriverResult::Success; |
| } |
|
|
| Common::Input::DriverResult RingConProtocol::ConfigureRing() { |
| LOG_DEBUG(Input, "ConfigureRing"); |
|
|
| static constexpr std::array<u8, 37> 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}; |
|
|
| const Common::Input::DriverResult result = |
| SendSubCommand(SubCommand::SET_EXTERNAL_FORMAT_CONFIG, ring_config); |
|
|
| if (result != Common::Input::DriverResult::Success) { |
| return result; |
| } |
|
|
| static constexpr std::array<u8, 4> ringcon_data{0x04, 0x01, 0x01, 0x02}; |
| return SendSubCommand(SubCommand::ENABLE_EXTERNAL_POLLING, ringcon_data); |
| } |
|
|
| bool RingConProtocol::IsEnabled() const { |
| return is_enabled; |
| } |
|
|
| } |
|
|