summaryrefslogtreecommitdiff
path: root/src/input_common/drivers/virtual_amiibo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/drivers/virtual_amiibo.cpp')
-rw-r--r--src/input_common/drivers/virtual_amiibo.cpp179
1 files changed, 154 insertions, 25 deletions
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp
index 63ffaca67..180eb53ef 100644
--- a/src/input_common/drivers/virtual_amiibo.cpp
+++ b/src/input_common/drivers/virtual_amiibo.cpp
@@ -22,28 +22,61 @@ VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move(
22 22
23VirtualAmiibo::~VirtualAmiibo() = default; 23VirtualAmiibo::~VirtualAmiibo() = default;
24 24
25Common::Input::PollingError VirtualAmiibo::SetPollingMode( 25Common::Input::DriverResult VirtualAmiibo::SetPollingMode(
26 [[maybe_unused]] const PadIdentifier& identifier_, 26 [[maybe_unused]] const PadIdentifier& identifier_,
27 const Common::Input::PollingMode polling_mode_) { 27 const Common::Input::PollingMode polling_mode_) {
28 polling_mode = polling_mode_; 28 polling_mode = polling_mode_;
29 29
30 if (polling_mode == Common::Input::PollingMode::NFC) { 30 switch (polling_mode) {
31 if (state == State::Initialized) { 31 case Common::Input::PollingMode::NFC:
32 state = State::WaitingForAmiibo; 32 state = State::Initialized;
33 } 33 return Common::Input::DriverResult::Success;
34 } else { 34 default:
35 if (state == State::AmiiboIsOpen) { 35 if (state == State::TagNearby) {
36 CloseAmiibo(); 36 CloseAmiibo();
37 } 37 }
38 state = State::Disabled;
39 return Common::Input::DriverResult::NotSupported;
38 } 40 }
39
40 return Common::Input::PollingError::None;
41} 41}
42 42
43Common::Input::NfcState VirtualAmiibo::SupportsNfc( 43Common::Input::NfcState VirtualAmiibo::SupportsNfc(
44 [[maybe_unused]] const PadIdentifier& identifier_) const { 44 [[maybe_unused]] const PadIdentifier& identifier_) const {
45 return Common::Input::NfcState::Success; 45 return Common::Input::NfcState::Success;
46} 46}
47Common::Input::NfcState VirtualAmiibo::StartNfcPolling(const PadIdentifier& identifier_) {
48 if (state != State::Initialized) {
49 return Common::Input::NfcState::WrongDeviceState;
50 }
51 state = State::WaitingForAmiibo;
52 return Common::Input::NfcState::Success;
53}
54
55Common::Input::NfcState VirtualAmiibo::StopNfcPolling(const PadIdentifier& identifier_) {
56 if (state == State::Disabled) {
57 return Common::Input::NfcState::WrongDeviceState;
58 }
59 if (state == State::TagNearby) {
60 CloseAmiibo();
61 }
62 state = State::Initialized;
63 return Common::Input::NfcState::Success;
64}
65
66Common::Input::NfcState VirtualAmiibo::ReadAmiiboData(const PadIdentifier& identifier_,
67 std::vector<u8>& out_data) {
68 if (state != State::TagNearby) {
69 return Common::Input::NfcState::WrongDeviceState;
70 }
71
72 if (status.tag_type != 1U << 1) {
73 return Common::Input::NfcState::InvalidTagType;
74 }
75
76 out_data.resize(nfc_data.size());
77 memcpy(out_data.data(), nfc_data.data(), nfc_data.size());
78 return Common::Input::NfcState::Success;
79}
47 80
48Common::Input::NfcState VirtualAmiibo::WriteNfcData( 81Common::Input::NfcState VirtualAmiibo::WriteNfcData(
49 [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { 82 [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) {
@@ -56,7 +89,7 @@ Common::Input::NfcState VirtualAmiibo::WriteNfcData(
56 } 89 }
57 90
58 if (!nfc_file.Write(data)) { 91 if (!nfc_file.Write(data)) {
59 LOG_ERROR(Service_NFP, "Error writting to file"); 92 LOG_ERROR(Service_NFP, "Error writing to file");
60 return Common::Input::NfcState::WriteFailed; 93 return Common::Input::NfcState::WriteFailed;
61 } 94 }
62 95
@@ -65,6 +98,69 @@ Common::Input::NfcState VirtualAmiibo::WriteNfcData(
65 return Common::Input::NfcState::Success; 98 return Common::Input::NfcState::Success;
66} 99}
67 100
101Common::Input::NfcState VirtualAmiibo::ReadMifareData(const PadIdentifier& identifier_,
102 const Common::Input::MifareRequest& request,
103 Common::Input::MifareRequest& out_data) {
104 if (state != State::TagNearby) {
105 return Common::Input::NfcState::WrongDeviceState;
106 }
107
108 if (status.tag_type != 1U << 6) {
109 return Common::Input::NfcState::InvalidTagType;
110 }
111
112 for (std::size_t i = 0; i < request.data.size(); i++) {
113 if (request.data[i].command == 0) {
114 continue;
115 }
116 out_data.data[i].command = request.data[i].command;
117 out_data.data[i].sector = request.data[i].sector;
118
119 const std::size_t sector_index =
120 request.data[i].sector * sizeof(Common::Input::MifareData::data);
121
122 if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) {
123 return Common::Input::NfcState::WriteFailed;
124 }
125
126 // Ignore the sector key as we don't support it
127 memcpy(out_data.data[i].data.data(), nfc_data.data() + sector_index,
128 sizeof(Common::Input::MifareData::data));
129 }
130
131 return Common::Input::NfcState::Success;
132}
133
134Common::Input::NfcState VirtualAmiibo::WriteMifareData(
135 const PadIdentifier& identifier_, const Common::Input::MifareRequest& request) {
136 if (state != State::TagNearby) {
137 return Common::Input::NfcState::WrongDeviceState;
138 }
139
140 if (status.tag_type != 1U << 6) {
141 return Common::Input::NfcState::InvalidTagType;
142 }
143
144 for (std::size_t i = 0; i < request.data.size(); i++) {
145 if (request.data[i].command == 0) {
146 continue;
147 }
148
149 const std::size_t sector_index =
150 request.data[i].sector * sizeof(Common::Input::MifareData::data);
151
152 if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) {
153 return Common::Input::NfcState::WriteFailed;
154 }
155
156 // Ignore the sector key as we don't support it
157 memcpy(nfc_data.data() + sector_index, request.data[i].data.data(),
158 sizeof(Common::Input::MifareData::data));
159 }
160
161 return Common::Input::NfcState::Success;
162}
163
68VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { 164VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const {
69 return state; 165 return state;
70} 166}
@@ -72,10 +168,7 @@ VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const {
72VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { 168VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) {
73 const Common::FS::IOFile nfc_file{filename, Common::FS::FileAccessMode::Read, 169 const Common::FS::IOFile nfc_file{filename, Common::FS::FileAccessMode::Read,
74 Common::FS::FileType::BinaryFile}; 170 Common::FS::FileType::BinaryFile};
75 171 std::vector<u8> data{};
76 if (state != State::WaitingForAmiibo) {
77 return Info::WrongDeviceState;
78 }
79 172
80 if (!nfc_file.IsOpen()) { 173 if (!nfc_file.IsOpen()) {
81 return Info::UnableToLoad; 174 return Info::UnableToLoad;
@@ -84,14 +177,15 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) {
84 switch (nfc_file.GetSize()) { 177 switch (nfc_file.GetSize()) {
85 case AmiiboSize: 178 case AmiiboSize:
86 case AmiiboSizeWithoutPassword: 179 case AmiiboSizeWithoutPassword:
87 nfc_data.resize(AmiiboSize); 180 case AmiiboSizeWithSignature:
88 if (nfc_file.Read(nfc_data) < AmiiboSizeWithoutPassword) { 181 data.resize(AmiiboSize);
182 if (nfc_file.Read(data) < AmiiboSizeWithoutPassword) {
89 return Info::NotAnAmiibo; 183 return Info::NotAnAmiibo;
90 } 184 }
91 break; 185 break;
92 case MifareSize: 186 case MifareSize:
93 nfc_data.resize(MifareSize); 187 data.resize(MifareSize);
94 if (nfc_file.Read(nfc_data) < MifareSize) { 188 if (nfc_file.Read(data) < MifareSize) {
95 return Info::NotAnAmiibo; 189 return Info::NotAnAmiibo;
96 } 190 }
97 break; 191 break;
@@ -100,14 +194,44 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) {
100 } 194 }
101 195
102 file_path = filename; 196 file_path = filename;
103 state = State::AmiiboIsOpen; 197 return LoadAmiibo(data);
104 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); 198}
199
200VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(std::span<u8> data) {
201 if (state != State::WaitingForAmiibo) {
202 return Info::WrongDeviceState;
203 }
204
205 switch (data.size_bytes()) {
206 case AmiiboSize:
207 case AmiiboSizeWithoutPassword:
208 case AmiiboSizeWithSignature:
209 nfc_data.resize(AmiiboSize);
210 status.tag_type = 1U << 1;
211 status.uuid_length = 7;
212 break;
213 case MifareSize:
214 nfc_data.resize(MifareSize);
215 status.tag_type = 1U << 6;
216 status.uuid_length = 4;
217 break;
218 default:
219 return Info::NotAnAmiibo;
220 }
221
222 status.uuid = {};
223 status.protocol = 1;
224 state = State::TagNearby;
225 status.state = Common::Input::NfcState::NewAmiibo,
226 memcpy(nfc_data.data(), data.data(), data.size_bytes());
227 memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length);
228 SetNfc(identifier, status);
105 return Info::Success; 229 return Info::Success;
106} 230}
107 231
108VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { 232VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
109 if (state == State::AmiiboIsOpen) { 233 if (state == State::TagNearby) {
110 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); 234 SetNfc(identifier, status);
111 return Info::Success; 235 return Info::Success;
112 } 236 }
113 237
@@ -115,9 +239,14 @@ VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
115} 239}
116 240
117VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { 241VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() {
118 state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo 242 if (state != State::TagNearby) {
119 : State::Initialized; 243 return Info::Success;
120 SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}}); 244 }
245
246 state = State::WaitingForAmiibo;
247 status.state = Common::Input::NfcState::AmiiboRemoved;
248 SetNfc(identifier, status);
249 status.tag_type = 0;
121 return Info::Success; 250 return Info::Success;
122} 251}
123 252