diff options
| author | 2022-09-24 19:46:49 -0500 | |
|---|---|---|
| committer | 2022-10-02 12:32:26 -0500 | |
| commit | e8d71712e7054748e7e18de9362de1f5a394b46b (patch) | |
| tree | 263779f72b874d81513f1292bb413a2cf170f32d /src | |
| parent | Merge pull request #8934 from german77/palma_release (diff) | |
| download | yuzu-e8d71712e7054748e7e18de9362de1f5a394b46b.tar.gz yuzu-e8d71712e7054748e7e18de9362de1f5a394b46b.tar.xz yuzu-e8d71712e7054748e7e18de9362de1f5a394b46b.zip | |
input_common: Create virtual amiibo driver
Diffstat (limited to '')
| -rw-r--r-- | src/common/input.h | 27 | ||||
| -rw-r--r-- | src/input_common/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/input_common/drivers/virtual_amiibo.cpp | 101 | ||||
| -rw-r--r-- | src/input_common/drivers/virtual_amiibo.h | 61 | ||||
| -rw-r--r-- | src/input_common/input_engine.cpp | 37 | ||||
| -rw-r--r-- | src/input_common/input_engine.h | 16 |
6 files changed, 244 insertions, 0 deletions
diff --git a/src/common/input.h b/src/common/input.h index 825b0d650..8365cc36e 100644 --- a/src/common/input.h +++ b/src/common/input.h | |||
| @@ -76,6 +76,19 @@ enum class PollingError { | |||
| 76 | Unknown, | 76 | Unknown, |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | // Nfc reply from the controller | ||
| 80 | enum class NfcState { | ||
| 81 | Success, | ||
| 82 | NewAmiibo, | ||
| 83 | WaitingForAmiibo, | ||
| 84 | AmiiboRemoved, | ||
| 85 | NotAnAmiibo, | ||
| 86 | NotSupported, | ||
| 87 | WrongDeviceState, | ||
| 88 | WriteFailed, | ||
| 89 | Unknown, | ||
| 90 | }; | ||
| 91 | |||
| 79 | // Ir camera reply from the controller | 92 | // Ir camera reply from the controller |
| 80 | enum class CameraError { | 93 | enum class CameraError { |
| 81 | None, | 94 | None, |
| @@ -202,6 +215,11 @@ struct CameraStatus { | |||
| 202 | std::vector<u8> data{}; | 215 | std::vector<u8> data{}; |
| 203 | }; | 216 | }; |
| 204 | 217 | ||
| 218 | struct NfcStatus { | ||
| 219 | NfcState state{}; | ||
| 220 | std::vector<u8> data{}; | ||
| 221 | }; | ||
| 222 | |||
| 205 | // List of buttons to be passed to Qt that can be translated | 223 | // List of buttons to be passed to Qt that can be translated |
| 206 | enum class ButtonNames { | 224 | enum class ButtonNames { |
| 207 | Undefined, | 225 | Undefined, |
| @@ -260,6 +278,7 @@ struct CallbackStatus { | |||
| 260 | BatteryStatus battery_status{}; | 278 | BatteryStatus battery_status{}; |
| 261 | VibrationStatus vibration_status{}; | 279 | VibrationStatus vibration_status{}; |
| 262 | CameraStatus camera_status{}; | 280 | CameraStatus camera_status{}; |
| 281 | NfcStatus nfc_status{}; | ||
| 263 | }; | 282 | }; |
| 264 | 283 | ||
| 265 | // Triggered once every input change | 284 | // Triggered once every input change |
| @@ -312,6 +331,14 @@ public: | |||
| 312 | virtual CameraError SetCameraFormat([[maybe_unused]] CameraFormat camera_format) { | 331 | virtual CameraError SetCameraFormat([[maybe_unused]] CameraFormat camera_format) { |
| 313 | return CameraError::NotSupported; | 332 | return CameraError::NotSupported; |
| 314 | } | 333 | } |
| 334 | |||
| 335 | virtual NfcState SupportsNfc() { | ||
| 336 | return NfcState::NotSupported; | ||
| 337 | } | ||
| 338 | |||
| 339 | virtual NfcState WriteNfcData([[maybe_unused]] const std::vector<u8>& data) { | ||
| 340 | return NfcState::NotSupported; | ||
| 341 | } | ||
| 315 | }; | 342 | }; |
| 316 | 343 | ||
| 317 | /// An abstract class template for a factory that can create input devices. | 344 | /// An abstract class template for a factory that can create input devices. |
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 4b91b88ce..2cf9eb97f 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -18,6 +18,8 @@ add_library(input_common STATIC | |||
| 18 | drivers/touch_screen.h | 18 | drivers/touch_screen.h |
| 19 | drivers/udp_client.cpp | 19 | drivers/udp_client.cpp |
| 20 | drivers/udp_client.h | 20 | drivers/udp_client.h |
| 21 | drivers/virtual_amiibo.cpp | ||
| 22 | drivers/virtual_amiibo.h | ||
| 21 | helpers/stick_from_buttons.cpp | 23 | helpers/stick_from_buttons.cpp |
| 22 | helpers/stick_from_buttons.h | 24 | helpers/stick_from_buttons.h |
| 23 | helpers/touch_from_buttons.cpp | 25 | helpers/touch_from_buttons.cpp |
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp new file mode 100644 index 000000000..8fadb1322 --- /dev/null +++ b/src/input_common/drivers/virtual_amiibo.cpp | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | #include <fmt/format.h> | ||
| 6 | |||
| 7 | #include "common/fs/file.h" | ||
| 8 | #include "common/fs/fs.h" | ||
| 9 | #include "common/fs/path_util.h" | ||
| 10 | #include "common/logging/log.h" | ||
| 11 | #include "common/settings.h" | ||
| 12 | #include "input_common/drivers/virtual_amiibo.h" | ||
| 13 | |||
| 14 | namespace InputCommon { | ||
| 15 | constexpr PadIdentifier identifier = { | ||
| 16 | .guid = Common::UUID{}, | ||
| 17 | .port = 0, | ||
| 18 | .pad = 0, | ||
| 19 | }; | ||
| 20 | |||
| 21 | VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move(input_engine_)) {} | ||
| 22 | |||
| 23 | VirtualAmiibo::~VirtualAmiibo() {} | ||
| 24 | |||
| 25 | Common::Input::PollingError VirtualAmiibo::SetPollingMode( | ||
| 26 | [[maybe_unused]] const PadIdentifier& identifier_, | ||
| 27 | const Common::Input::PollingMode polling_mode_) { | ||
| 28 | polling_mode = polling_mode_; | ||
| 29 | |||
| 30 | if (polling_mode == Common::Input::PollingMode::NFC) { | ||
| 31 | if (state == State::Initialized) { | ||
| 32 | state = State::WaitingForAmiibo; | ||
| 33 | } | ||
| 34 | } else { | ||
| 35 | if (state == State::AmiiboIsOpen) { | ||
| 36 | CloseAmiibo(); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | return Common::Input::PollingError::None; | ||
| 41 | } | ||
| 42 | |||
| 43 | Common::Input::NfcState VirtualAmiibo::SupportsNfc( | ||
| 44 | [[maybe_unused]] const PadIdentifier& identifier_) { | ||
| 45 | return Common::Input::NfcState::Success; | ||
| 46 | } | ||
| 47 | |||
| 48 | Common::Input::NfcState VirtualAmiibo::WriteNfcData( | ||
| 49 | [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { | ||
| 50 | const Common::FS::IOFile amiibo_file{file_path, Common::FS::FileAccessMode::ReadWrite, | ||
| 51 | Common::FS::FileType::BinaryFile}; | ||
| 52 | |||
| 53 | if (!amiibo_file.IsOpen()) { | ||
| 54 | LOG_ERROR(Core, "Amiibo is already on use"); | ||
| 55 | return Common::Input::NfcState::WriteFailed; | ||
| 56 | } | ||
| 57 | |||
| 58 | if (!amiibo_file.Write(data)) { | ||
| 59 | LOG_ERROR(Service_NFP, "Error writting to file"); | ||
| 60 | return Common::Input::NfcState::WriteFailed; | ||
| 61 | } | ||
| 62 | |||
| 63 | return Common::Input::NfcState::Success; | ||
| 64 | } | ||
| 65 | |||
| 66 | VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { | ||
| 67 | return state; | ||
| 68 | } | ||
| 69 | |||
| 70 | VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { | ||
| 71 | const Common::FS::IOFile amiibo_file{filename, Common::FS::FileAccessMode::Read, | ||
| 72 | Common::FS::FileType::BinaryFile}; | ||
| 73 | |||
| 74 | if (state != State::WaitingForAmiibo) { | ||
| 75 | return Info::WrongDeviceState; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (!amiibo_file.IsOpen()) { | ||
| 79 | return Info::UnableToLoad; | ||
| 80 | } | ||
| 81 | |||
| 82 | amiibo_data.resize(amiibo_size); | ||
| 83 | |||
| 84 | if (amiibo_file.Read(amiibo_data) < amiibo_size_without_password) { | ||
| 85 | return Info::NotAnAmiibo; | ||
| 86 | } | ||
| 87 | |||
| 88 | file_path = filename; | ||
| 89 | state = State::AmiiboIsOpen; | ||
| 90 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); | ||
| 91 | return Info::Success; | ||
| 92 | } | ||
| 93 | |||
| 94 | VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { | ||
| 95 | state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo | ||
| 96 | : State::Initialized; | ||
| 97 | SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}}); | ||
| 98 | return Info::Success; | ||
| 99 | } | ||
| 100 | |||
| 101 | } // namespace InputCommon | ||
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h new file mode 100644 index 000000000..5790e4a1f --- /dev/null +++ b/src/input_common/drivers/virtual_amiibo.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "input_common/input_engine.h" | ||
| 12 | |||
| 13 | namespace Common::FS { | ||
| 14 | class IOFile; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace InputCommon { | ||
| 18 | |||
| 19 | class VirtualAmiibo final : public InputEngine { | ||
| 20 | public: | ||
| 21 | enum class State { | ||
| 22 | Initialized, | ||
| 23 | WaitingForAmiibo, | ||
| 24 | AmiiboIsOpen, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum class Info { | ||
| 28 | Success, | ||
| 29 | UnableToLoad, | ||
| 30 | NotAnAmiibo, | ||
| 31 | WrongDeviceState, | ||
| 32 | Unknown, | ||
| 33 | }; | ||
| 34 | |||
| 35 | explicit VirtualAmiibo(std::string input_engine_); | ||
| 36 | ~VirtualAmiibo() override; | ||
| 37 | |||
| 38 | // Sets polling mode to a controller | ||
| 39 | Common::Input::PollingError SetPollingMode( | ||
| 40 | const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override; | ||
| 41 | |||
| 42 | Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) override; | ||
| 43 | |||
| 44 | Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_, | ||
| 45 | const std::vector<u8>& data) override; | ||
| 46 | |||
| 47 | State GetCurrentState() const; | ||
| 48 | |||
| 49 | Info LoadAmiibo(const std::string& amiibo_file); | ||
| 50 | Info CloseAmiibo(); | ||
| 51 | |||
| 52 | private: | ||
| 53 | static constexpr std::size_t amiibo_size = 0x21C; | ||
| 54 | static constexpr std::size_t amiibo_size_without_password = amiibo_size - 0x8; | ||
| 55 | |||
| 56 | std::string file_path{}; | ||
| 57 | State state{State::Initialized}; | ||
| 58 | std::vector<u8> amiibo_data; | ||
| 59 | Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive}; | ||
| 60 | }; | ||
| 61 | } // namespace InputCommon | ||
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 6ede0e4b0..61cfd0911 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp | |||
| @@ -102,6 +102,17 @@ void InputEngine::SetCamera(const PadIdentifier& identifier, | |||
| 102 | TriggerOnCameraChange(identifier, value); | 102 | TriggerOnCameraChange(identifier, value); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void InputEngine::SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value) { | ||
| 106 | { | ||
| 107 | std::scoped_lock lock{mutex}; | ||
| 108 | ControllerData& controller = controller_list.at(identifier); | ||
| 109 | if (!configuring) { | ||
| 110 | controller.nfc = value; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | TriggerOnNfcChange(identifier, value); | ||
| 114 | } | ||
| 115 | |||
| 105 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { | 116 | bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { |
| 106 | std::scoped_lock lock{mutex}; | 117 | std::scoped_lock lock{mutex}; |
| 107 | const auto controller_iter = controller_list.find(identifier); | 118 | const auto controller_iter = controller_list.find(identifier); |
| @@ -189,6 +200,18 @@ Common::Input::CameraStatus InputEngine::GetCamera(const PadIdentifier& identifi | |||
| 189 | return controller.camera; | 200 | return controller.camera; |
| 190 | } | 201 | } |
| 191 | 202 | ||
| 203 | Common::Input::NfcStatus InputEngine::GetNfc(const PadIdentifier& identifier) const { | ||
| 204 | std::scoped_lock lock{mutex}; | ||
| 205 | const auto controller_iter = controller_list.find(identifier); | ||
| 206 | if (controller_iter == controller_list.cend()) { | ||
| 207 | LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.RawString(), | ||
| 208 | identifier.pad, identifier.port); | ||
| 209 | return {}; | ||
| 210 | } | ||
| 211 | const ControllerData& controller = controller_iter->second; | ||
| 212 | return controller.nfc; | ||
| 213 | } | ||
| 214 | |||
| 192 | void InputEngine::ResetButtonState() { | 215 | void InputEngine::ResetButtonState() { |
| 193 | for (const auto& controller : controller_list) { | 216 | for (const auto& controller : controller_list) { |
| 194 | for (const auto& button : controller.second.buttons) { | 217 | for (const auto& button : controller.second.buttons) { |
| @@ -355,6 +378,20 @@ void InputEngine::TriggerOnCameraChange(const PadIdentifier& identifier, | |||
| 355 | } | 378 | } |
| 356 | } | 379 | } |
| 357 | 380 | ||
| 381 | void InputEngine::TriggerOnNfcChange(const PadIdentifier& identifier, | ||
| 382 | [[maybe_unused]] const Common::Input::NfcStatus& value) { | ||
| 383 | std::scoped_lock lock{mutex_callback}; | ||
| 384 | for (const auto& poller_pair : callback_list) { | ||
| 385 | const InputIdentifier& poller = poller_pair.second; | ||
| 386 | if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Nfc, 0)) { | ||
| 387 | continue; | ||
| 388 | } | ||
| 389 | if (poller.callback.on_change) { | ||
| 390 | poller.callback.on_change(); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 358 | bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, | 395 | bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, |
| 359 | const PadIdentifier& identifier, EngineInputType type, | 396 | const PadIdentifier& identifier, EngineInputType type, |
| 360 | int index) const { | 397 | int index) const { |
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index f6b3c4610..9b8470c6f 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h | |||
| @@ -42,6 +42,7 @@ enum class EngineInputType { | |||
| 42 | Camera, | 42 | Camera, |
| 43 | HatButton, | 43 | HatButton, |
| 44 | Motion, | 44 | Motion, |
| 45 | Nfc, | ||
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | namespace std { | 48 | namespace std { |
| @@ -127,6 +128,17 @@ public: | |||
| 127 | return Common::Input::CameraError::NotSupported; | 128 | return Common::Input::CameraError::NotSupported; |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 131 | // Request nfc data from a controller | ||
| 132 | virtual Common::Input::NfcState SupportsNfc([[maybe_unused]] const PadIdentifier& identifier) { | ||
| 133 | return Common::Input::NfcState::NotSupported; | ||
| 134 | } | ||
| 135 | |||
| 136 | // Writes data to an nfc tag | ||
| 137 | virtual Common::Input::NfcState WriteNfcData([[maybe_unused]] const PadIdentifier& identifier, | ||
| 138 | [[maybe_unused]] const std::vector<u8>& data) { | ||
| 139 | return Common::Input::NfcState::NotSupported; | ||
| 140 | } | ||
| 141 | |||
| 130 | // Returns the engine name | 142 | // Returns the engine name |
| 131 | [[nodiscard]] const std::string& GetEngineName() const; | 143 | [[nodiscard]] const std::string& GetEngineName() const; |
| 132 | 144 | ||
| @@ -183,6 +195,7 @@ public: | |||
| 183 | Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const; | 195 | Common::Input::BatteryLevel GetBattery(const PadIdentifier& identifier) const; |
| 184 | BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; | 196 | BasicMotion GetMotion(const PadIdentifier& identifier, int motion) const; |
| 185 | Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const; | 197 | Common::Input::CameraStatus GetCamera(const PadIdentifier& identifier) const; |
| 198 | Common::Input::NfcStatus GetNfc(const PadIdentifier& identifier) const; | ||
| 186 | 199 | ||
| 187 | int SetCallback(InputIdentifier input_identifier); | 200 | int SetCallback(InputIdentifier input_identifier); |
| 188 | void SetMappingCallback(MappingCallback callback); | 201 | void SetMappingCallback(MappingCallback callback); |
| @@ -195,6 +208,7 @@ protected: | |||
| 195 | void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value); | 208 | void SetBattery(const PadIdentifier& identifier, Common::Input::BatteryLevel value); |
| 196 | void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); | 209 | void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value); |
| 197 | void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value); | 210 | void SetCamera(const PadIdentifier& identifier, const Common::Input::CameraStatus& value); |
| 211 | void SetNfc(const PadIdentifier& identifier, const Common::Input::NfcStatus& value); | ||
| 198 | 212 | ||
| 199 | virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const { | 213 | virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const { |
| 200 | return "Unknown"; | 214 | return "Unknown"; |
| @@ -208,6 +222,7 @@ private: | |||
| 208 | std::unordered_map<int, BasicMotion> motions; | 222 | std::unordered_map<int, BasicMotion> motions; |
| 209 | Common::Input::BatteryLevel battery{}; | 223 | Common::Input::BatteryLevel battery{}; |
| 210 | Common::Input::CameraStatus camera{}; | 224 | Common::Input::CameraStatus camera{}; |
| 225 | Common::Input::NfcStatus nfc{}; | ||
| 211 | }; | 226 | }; |
| 212 | 227 | ||
| 213 | void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value); | 228 | void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value); |
| @@ -218,6 +233,7 @@ private: | |||
| 218 | const BasicMotion& value); | 233 | const BasicMotion& value); |
| 219 | void TriggerOnCameraChange(const PadIdentifier& identifier, | 234 | void TriggerOnCameraChange(const PadIdentifier& identifier, |
| 220 | const Common::Input::CameraStatus& value); | 235 | const Common::Input::CameraStatus& value); |
| 236 | void TriggerOnNfcChange(const PadIdentifier& identifier, const Common::Input::NfcStatus& value); | ||
| 221 | 237 | ||
| 222 | bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, | 238 | bool IsInputIdentifierEqual(const InputIdentifier& input_identifier, |
| 223 | const PadIdentifier& identifier, EngineInputType type, | 239 | const PadIdentifier& identifier, EngineInputType type, |