summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/input.h27
-rw-r--r--src/input_common/CMakeLists.txt2
-rw-r--r--src/input_common/drivers/virtual_amiibo.cpp101
-rw-r--r--src/input_common/drivers/virtual_amiibo.h61
-rw-r--r--src/input_common/input_engine.cpp37
-rw-r--r--src/input_common/input_engine.h16
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
80enum 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
80enum class CameraError { 93enum 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
218struct 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
206enum class ButtonNames { 224enum 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
14namespace InputCommon {
15constexpr PadIdentifier identifier = {
16 .guid = Common::UUID{},
17 .port = 0,
18 .pad = 0,
19};
20
21VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move(input_engine_)) {}
22
23VirtualAmiibo::~VirtualAmiibo() {}
24
25Common::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
43Common::Input::NfcState VirtualAmiibo::SupportsNfc(
44 [[maybe_unused]] const PadIdentifier& identifier_) {
45 return Common::Input::NfcState::Success;
46}
47
48Common::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
66VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const {
67 return state;
68}
69
70VirtualAmiibo::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
94VirtualAmiibo::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
13namespace Common::FS {
14class IOFile;
15}
16
17namespace InputCommon {
18
19class VirtualAmiibo final : public InputEngine {
20public:
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
52private:
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
105void 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
105bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const { 116bool 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
203Common::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
192void InputEngine::ResetButtonState() { 215void 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
381void 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
358bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier, 395bool 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
47namespace std { 48namespace 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,