diff options
Diffstat (limited to 'src/input_common/helpers/joycon_protocol/nfc.cpp')
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/nfc.cpp | 531 |
1 files changed, 457 insertions, 74 deletions
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index f7058c4a7..09953394b 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <thread> | 4 | #include "common/input.h" |
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "input_common/helpers/joycon_protocol/nfc.h" | 6 | #include "input_common/helpers/joycon_protocol/nfc.h" |
| 7 | 7 | ||
| @@ -10,21 +10,21 @@ namespace InputCommon::Joycon { | |||
| 10 | NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle) | 10 | NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle) |
| 11 | : JoyconCommonProtocol(std::move(handle)) {} | 11 | : JoyconCommonProtocol(std::move(handle)) {} |
| 12 | 12 | ||
| 13 | DriverResult NfcProtocol::EnableNfc() { | 13 | Common::Input::DriverResult NfcProtocol::EnableNfc() { |
| 14 | LOG_INFO(Input, "Enable NFC"); | 14 | LOG_INFO(Input, "Enable NFC"); |
| 15 | ScopedSetBlocking sb(this); | 15 | ScopedSetBlocking sb(this); |
| 16 | DriverResult result{DriverResult::Success}; | 16 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 17 | 17 | ||
| 18 | if (result == DriverResult::Success) { | 18 | if (result == Common::Input::DriverResult::Success) { |
| 19 | result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); | 19 | result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); |
| 20 | } | 20 | } |
| 21 | if (result == DriverResult::Success) { | 21 | if (result == Common::Input::DriverResult::Success) { |
| 22 | result = EnableMCU(true); | 22 | result = EnableMCU(true); |
| 23 | } | 23 | } |
| 24 | if (result == DriverResult::Success) { | 24 | if (result == Common::Input::DriverResult::Success) { |
| 25 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); | 25 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::Standby); |
| 26 | } | 26 | } |
| 27 | if (result == DriverResult::Success) { | 27 | if (result == Common::Input::DriverResult::Success) { |
| 28 | const MCUConfig config{ | 28 | const MCUConfig config{ |
| 29 | .command = MCUCommand::ConfigureMCU, | 29 | .command = MCUCommand::ConfigureMCU, |
| 30 | .sub_command = MCUSubCommand::SetMCUMode, | 30 | .sub_command = MCUSubCommand::SetMCUMode, |
| @@ -34,123 +34,240 @@ DriverResult NfcProtocol::EnableNfc() { | |||
| 34 | 34 | ||
| 35 | result = ConfigureMCU(config); | 35 | result = ConfigureMCU(config); |
| 36 | } | 36 | } |
| 37 | if (result == DriverResult::Success) { | 37 | if (result == Common::Input::DriverResult::Success) { |
| 38 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); | 38 | result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); |
| 39 | } | 39 | } |
| 40 | if (result == DriverResult::Success) { | 40 | if (result == Common::Input::DriverResult::Success) { |
| 41 | result = WaitUntilNfcIs(NFCStatus::Ready); | 41 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 42 | } | 42 | } |
| 43 | if (result == Common::Input::DriverResult::Success) { | ||
| 44 | MCUCommandResponse output{}; | ||
| 45 | result = SendStopPollingRequest(output); | ||
| 46 | } | ||
| 47 | if (result == Common::Input::DriverResult::Success) { | ||
| 48 | result = WaitUntilNfcIs(NFCStatus::Ready); | ||
| 49 | } | ||
| 50 | if (result == Common::Input::DriverResult::Success) { | ||
| 51 | is_enabled = true; | ||
| 52 | } | ||
| 43 | 53 | ||
| 44 | return result; | 54 | return result; |
| 45 | } | 55 | } |
| 46 | 56 | ||
| 47 | DriverResult NfcProtocol::DisableNfc() { | 57 | Common::Input::DriverResult NfcProtocol::DisableNfc() { |
| 48 | LOG_DEBUG(Input, "Disable NFC"); | 58 | LOG_DEBUG(Input, "Disable NFC"); |
| 49 | ScopedSetBlocking sb(this); | 59 | ScopedSetBlocking sb(this); |
| 50 | DriverResult result{DriverResult::Success}; | 60 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 51 | 61 | ||
| 52 | if (result == DriverResult::Success) { | 62 | if (result == Common::Input::DriverResult::Success) { |
| 53 | result = EnableMCU(false); | 63 | result = EnableMCU(false); |
| 54 | } | 64 | } |
| 55 | 65 | ||
| 56 | is_enabled = false; | 66 | is_enabled = false; |
| 67 | is_polling = false; | ||
| 57 | 68 | ||
| 58 | return result; | 69 | return result; |
| 59 | } | 70 | } |
| 60 | 71 | ||
| 61 | DriverResult NfcProtocol::StartNFCPollingMode() { | 72 | Common::Input::DriverResult NfcProtocol::StartNFCPollingMode() { |
| 62 | LOG_DEBUG(Input, "Start NFC pooling Mode"); | 73 | LOG_DEBUG(Input, "Start NFC polling Mode"); |
| 63 | ScopedSetBlocking sb(this); | 74 | ScopedSetBlocking sb(this); |
| 64 | DriverResult result{DriverResult::Success}; | 75 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 65 | 76 | ||
| 66 | if (result == DriverResult::Success) { | 77 | if (result == Common::Input::DriverResult::Success) { |
| 67 | MCUCommandResponse output{}; | 78 | MCUCommandResponse output{}; |
| 68 | result = SendStopPollingRequest(output); | 79 | result = SendStartPollingRequest(output); |
| 69 | } | 80 | } |
| 70 | if (result == DriverResult::Success) { | 81 | if (result == Common::Input::DriverResult::Success) { |
| 71 | result = WaitUntilNfcIs(NFCStatus::Ready); | 82 | result = WaitUntilNfcIs(NFCStatus::Polling); |
| 83 | } | ||
| 84 | if (result == Common::Input::DriverResult::Success) { | ||
| 85 | is_polling = true; | ||
| 72 | } | 86 | } |
| 73 | if (result == DriverResult::Success) { | 87 | |
| 88 | return result; | ||
| 89 | } | ||
| 90 | |||
| 91 | Common::Input::DriverResult NfcProtocol::StopNFCPollingMode() { | ||
| 92 | LOG_DEBUG(Input, "Stop NFC polling Mode"); | ||
| 93 | ScopedSetBlocking sb(this); | ||
| 94 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; | ||
| 95 | |||
| 96 | if (result == Common::Input::DriverResult::Success) { | ||
| 74 | MCUCommandResponse output{}; | 97 | MCUCommandResponse output{}; |
| 75 | result = SendStartPollingRequest(output); | 98 | result = SendStopPollingRequest(output); |
| 76 | } | 99 | } |
| 77 | if (result == DriverResult::Success) { | 100 | if (result == Common::Input::DriverResult::Success) { |
| 78 | result = WaitUntilNfcIs(NFCStatus::Polling); | 101 | result = WaitUntilNfcIs(NFCStatus::WriteReady); |
| 79 | } | 102 | } |
| 80 | if (result == DriverResult::Success) { | 103 | if (result == Common::Input::DriverResult::Success) { |
| 81 | is_enabled = true; | 104 | is_polling = false; |
| 82 | } | 105 | } |
| 83 | 106 | ||
| 84 | return result; | 107 | return result; |
| 85 | } | 108 | } |
| 86 | 109 | ||
| 87 | DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { | 110 | Common::Input::DriverResult NfcProtocol::GetTagInfo(Joycon::TagInfo& tag_info) { |
| 88 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { | 111 | if (update_counter++ < AMIIBO_UPDATE_DELAY) { |
| 89 | return DriverResult::Delayed; | 112 | return Common::Input::DriverResult::Delayed; |
| 90 | } | 113 | } |
| 91 | update_counter = 0; | 114 | update_counter = 0; |
| 92 | 115 | ||
| 93 | LOG_DEBUG(Input, "Scan for amiibos"); | 116 | LOG_DEBUG(Input, "Scan for amiibos"); |
| 94 | ScopedSetBlocking sb(this); | 117 | ScopedSetBlocking sb(this); |
| 95 | DriverResult result{DriverResult::Success}; | 118 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 96 | TagFoundData tag_data{}; | 119 | TagFoundData tag_data{}; |
| 97 | 120 | ||
| 98 | if (result == DriverResult::Success) { | 121 | if (result == Common::Input::DriverResult::Success) { |
| 99 | result = IsTagInRange(tag_data); | 122 | result = IsTagInRange(tag_data); |
| 100 | } | 123 | } |
| 101 | 124 | ||
| 102 | if (result == DriverResult::Success) { | 125 | if (result == Common::Input::DriverResult::Success) { |
| 126 | tag_info = { | ||
| 127 | .uuid_length = tag_data.uuid_size, | ||
| 128 | .protocol = 1, | ||
| 129 | .tag_type = tag_data.type, | ||
| 130 | .uuid = {}, | ||
| 131 | }; | ||
| 132 | |||
| 133 | memcpy(tag_info.uuid.data(), tag_data.uuid.data(), tag_data.uuid_size); | ||
| 134 | |||
| 135 | // Investigate why mifare type is not correct | ||
| 136 | if (tag_info.tag_type == 144) { | ||
| 137 | tag_info.tag_type = 1U << 6; | ||
| 138 | } | ||
| 139 | |||
| 103 | std::string uuid_string; | 140 | std::string uuid_string; |
| 104 | for (auto& content : tag_data.uuid) { | 141 | for (auto& content : tag_data.uuid) { |
| 105 | uuid_string += fmt::format(" {:02x}", content); | 142 | uuid_string += fmt::format(" {:02x}", content); |
| 106 | } | 143 | } |
| 107 | LOG_INFO(Input, "Tag detected, type={}, uuid={}", tag_data.type, uuid_string); | 144 | LOG_INFO(Input, "Tag detected, type={}, uuid={}", tag_data.type, uuid_string); |
| 145 | } | ||
| 146 | |||
| 147 | return result; | ||
| 148 | } | ||
| 149 | |||
| 150 | Common::Input::DriverResult NfcProtocol::ReadAmiibo(std::vector<u8>& data) { | ||
| 151 | LOG_DEBUG(Input, "Scan for amiibos"); | ||
| 152 | ScopedSetBlocking sb(this); | ||
| 153 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; | ||
| 154 | TagFoundData tag_data{}; | ||
| 155 | |||
| 156 | if (result == Common::Input::DriverResult::Success) { | ||
| 157 | result = IsTagInRange(tag_data, 7); | ||
| 158 | } | ||
| 159 | |||
| 160 | if (result == Common::Input::DriverResult::Success) { | ||
| 108 | result = GetAmiiboData(data); | 161 | result = GetAmiiboData(data); |
| 109 | } | 162 | } |
| 110 | 163 | ||
| 111 | return result; | 164 | return result; |
| 112 | } | 165 | } |
| 113 | 166 | ||
| 114 | DriverResult NfcProtocol::WriteAmiibo(std::span<const u8> data) { | 167 | Common::Input::DriverResult NfcProtocol::WriteAmiibo(std::span<const u8> data) { |
| 115 | LOG_DEBUG(Input, "Write amiibo"); | 168 | LOG_DEBUG(Input, "Write amiibo"); |
| 116 | ScopedSetBlocking sb(this); | 169 | ScopedSetBlocking sb(this); |
| 117 | DriverResult result{DriverResult::Success}; | 170 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 118 | TagUUID tag_uuid = GetTagUUID(data); | 171 | TagUUID tag_uuid = GetTagUUID(data); |
| 119 | TagFoundData tag_data{}; | 172 | TagFoundData tag_data{}; |
| 120 | 173 | ||
| 121 | if (result == DriverResult::Success) { | 174 | if (result == Common::Input::DriverResult::Success) { |
| 122 | result = IsTagInRange(tag_data, 7); | 175 | result = IsTagInRange(tag_data, 7); |
| 123 | } | 176 | } |
| 124 | if (result == DriverResult::Success) { | 177 | if (result == Common::Input::DriverResult::Success) { |
| 125 | if (tag_data.uuid != tag_uuid) { | 178 | if (tag_data.uuid != tag_uuid) { |
| 126 | result = DriverResult::InvalidParameters; | 179 | result = Common::Input::DriverResult::InvalidParameters; |
| 127 | } | 180 | } |
| 128 | } | 181 | } |
| 129 | if (result == DriverResult::Success) { | 182 | if (result == Common::Input::DriverResult::Success) { |
| 130 | MCUCommandResponse output{}; | 183 | MCUCommandResponse output{}; |
| 131 | result = SendStopPollingRequest(output); | 184 | result = SendStopPollingRequest(output); |
| 132 | } | 185 | } |
| 133 | if (result == DriverResult::Success) { | 186 | if (result == Common::Input::DriverResult::Success) { |
| 134 | result = WaitUntilNfcIs(NFCStatus::Ready); | 187 | result = WaitUntilNfcIs(NFCStatus::Ready); |
| 135 | } | 188 | } |
| 136 | if (result == DriverResult::Success) { | 189 | if (result == Common::Input::DriverResult::Success) { |
| 137 | MCUCommandResponse output{}; | 190 | MCUCommandResponse output{}; |
| 138 | result = SendStartPollingRequest(output, true); | 191 | result = SendStartPollingRequest(output, true); |
| 139 | } | 192 | } |
| 140 | if (result == DriverResult::Success) { | 193 | if (result == Common::Input::DriverResult::Success) { |
| 141 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | 194 | result = WaitUntilNfcIs(NFCStatus::WriteReady); |
| 142 | } | 195 | } |
| 143 | if (result == DriverResult::Success) { | 196 | if (result == Common::Input::DriverResult::Success) { |
| 144 | result = WriteAmiiboData(tag_uuid, data); | 197 | result = WriteAmiiboData(tag_uuid, data); |
| 145 | } | 198 | } |
| 146 | if (result == DriverResult::Success) { | 199 | if (result == Common::Input::DriverResult::Success) { |
| 147 | result = WaitUntilNfcIs(NFCStatus::WriteDone); | 200 | result = WaitUntilNfcIs(NFCStatus::WriteDone); |
| 148 | } | 201 | } |
| 149 | if (result == DriverResult::Success) { | 202 | if (result == Common::Input::DriverResult::Success) { |
| 203 | MCUCommandResponse output{}; | ||
| 204 | result = SendStopPollingRequest(output); | ||
| 205 | } | ||
| 206 | |||
| 207 | return result; | ||
| 208 | } | ||
| 209 | |||
| 210 | Common::Input::DriverResult NfcProtocol::ReadMifare(std::span<const MifareReadChunk> read_request, | ||
| 211 | std::span<MifareReadData> out_data) { | ||
| 212 | LOG_DEBUG(Input, "Read mifare"); | ||
| 213 | ScopedSetBlocking sb(this); | ||
| 214 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; | ||
| 215 | TagFoundData tag_data{}; | ||
| 216 | MifareUUID tag_uuid{}; | ||
| 217 | |||
| 218 | if (result == Common::Input::DriverResult::Success) { | ||
| 219 | result = IsTagInRange(tag_data, 7); | ||
| 220 | } | ||
| 221 | if (result == Common::Input::DriverResult::Success) { | ||
| 222 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); | ||
| 223 | result = GetMifareData(tag_uuid, read_request, out_data); | ||
| 224 | } | ||
| 225 | if (result == Common::Input::DriverResult::Success) { | ||
| 150 | MCUCommandResponse output{}; | 226 | MCUCommandResponse output{}; |
| 151 | result = SendStopPollingRequest(output); | 227 | result = SendStopPollingRequest(output); |
| 152 | } | 228 | } |
| 229 | if (result == Common::Input::DriverResult::Success) { | ||
| 230 | result = WaitUntilNfcIs(NFCStatus::Ready); | ||
| 231 | } | ||
| 232 | if (result == Common::Input::DriverResult::Success) { | ||
| 233 | MCUCommandResponse output{}; | ||
| 234 | result = SendStartPollingRequest(output, true); | ||
| 235 | } | ||
| 236 | if (result == Common::Input::DriverResult::Success) { | ||
| 237 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | ||
| 238 | } | ||
| 239 | return result; | ||
| 240 | } | ||
| 241 | |||
| 242 | Common::Input::DriverResult NfcProtocol::WriteMifare( | ||
| 243 | std::span<const MifareWriteChunk> write_request) { | ||
| 244 | LOG_DEBUG(Input, "Write mifare"); | ||
| 245 | ScopedSetBlocking sb(this); | ||
| 246 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; | ||
| 247 | TagFoundData tag_data{}; | ||
| 248 | MifareUUID tag_uuid{}; | ||
| 153 | 249 | ||
| 250 | if (result == Common::Input::DriverResult::Success) { | ||
| 251 | result = IsTagInRange(tag_data, 7); | ||
| 252 | } | ||
| 253 | if (result == Common::Input::DriverResult::Success) { | ||
| 254 | memcpy(tag_uuid.data(), tag_data.uuid.data(), sizeof(MifareUUID)); | ||
| 255 | result = WriteMifareData(tag_uuid, write_request); | ||
| 256 | } | ||
| 257 | if (result == Common::Input::DriverResult::Success) { | ||
| 258 | MCUCommandResponse output{}; | ||
| 259 | result = SendStopPollingRequest(output); | ||
| 260 | } | ||
| 261 | if (result == Common::Input::DriverResult::Success) { | ||
| 262 | result = WaitUntilNfcIs(NFCStatus::Ready); | ||
| 263 | } | ||
| 264 | if (result == Common::Input::DriverResult::Success) { | ||
| 265 | MCUCommandResponse output{}; | ||
| 266 | result = SendStartPollingRequest(output, true); | ||
| 267 | } | ||
| 268 | if (result == Common::Input::DriverResult::Success) { | ||
| 269 | result = WaitUntilNfcIs(NFCStatus::WriteReady); | ||
| 270 | } | ||
| 154 | return result; | 271 | return result; |
| 155 | } | 272 | } |
| 156 | 273 | ||
| @@ -161,17 +278,17 @@ bool NfcProtocol::HasAmiibo() { | |||
| 161 | update_counter = 0; | 278 | update_counter = 0; |
| 162 | 279 | ||
| 163 | ScopedSetBlocking sb(this); | 280 | ScopedSetBlocking sb(this); |
| 164 | DriverResult result{DriverResult::Success}; | 281 | Common::Input::DriverResult result{Common::Input::DriverResult::Success}; |
| 165 | TagFoundData tag_data{}; | 282 | TagFoundData tag_data{}; |
| 166 | 283 | ||
| 167 | if (result == DriverResult::Success) { | 284 | if (result == Common::Input::DriverResult::Success) { |
| 168 | result = IsTagInRange(tag_data, 7); | 285 | result = IsTagInRange(tag_data, 7); |
| 169 | } | 286 | } |
| 170 | 287 | ||
| 171 | return result == DriverResult::Success; | 288 | return result == Common::Input::DriverResult::Success; |
| 172 | } | 289 | } |
| 173 | 290 | ||
| 174 | DriverResult NfcProtocol::WaitUntilNfcIs(NFCStatus status) { | 291 | Common::Input::DriverResult NfcProtocol::WaitUntilNfcIs(NFCStatus status) { |
| 175 | constexpr std::size_t timeout_limit = 10; | 292 | constexpr std::size_t timeout_limit = 10; |
| 176 | MCUCommandResponse output{}; | 293 | MCUCommandResponse output{}; |
| 177 | std::size_t tries = 0; | 294 | std::size_t tries = 0; |
| @@ -179,30 +296,31 @@ DriverResult NfcProtocol::WaitUntilNfcIs(NFCStatus status) { | |||
| 179 | do { | 296 | do { |
| 180 | auto result = SendNextPackageRequest(output, {}); | 297 | auto result = SendNextPackageRequest(output, {}); |
| 181 | 298 | ||
| 182 | if (result != DriverResult::Success) { | 299 | if (result != Common::Input::DriverResult::Success) { |
| 183 | return result; | 300 | return result; |
| 184 | } | 301 | } |
| 185 | if (tries++ > timeout_limit) { | 302 | if (tries++ > timeout_limit) { |
| 186 | return DriverResult::Timeout; | 303 | return Common::Input::DriverResult::Timeout; |
| 187 | } | 304 | } |
| 188 | } while (output.mcu_report != MCUReport::NFCState || | 305 | } while (output.mcu_report != MCUReport::NFCState || |
| 189 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || | 306 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || |
| 190 | output.mcu_data[5] != 0x31 || output.mcu_data[6] != static_cast<u8>(status)); | 307 | output.mcu_data[5] != 0x31 || output.mcu_data[6] != static_cast<u8>(status)); |
| 191 | 308 | ||
| 192 | return DriverResult::Success; | 309 | return Common::Input::DriverResult::Success; |
| 193 | } | 310 | } |
| 194 | 311 | ||
| 195 | DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, std::size_t timeout_limit) { | 312 | Common::Input::DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, |
| 313 | std::size_t timeout_limit) { | ||
| 196 | MCUCommandResponse output{}; | 314 | MCUCommandResponse output{}; |
| 197 | std::size_t tries = 0; | 315 | std::size_t tries = 0; |
| 198 | 316 | ||
| 199 | do { | 317 | do { |
| 200 | const auto result = SendNextPackageRequest(output, {}); | 318 | const auto result = SendNextPackageRequest(output, {}); |
| 201 | if (result != DriverResult::Success) { | 319 | if (result != Common::Input::DriverResult::Success) { |
| 202 | return result; | 320 | return result; |
| 203 | } | 321 | } |
| 204 | if (tries++ > timeout_limit) { | 322 | if (tries++ > timeout_limit) { |
| 205 | return DriverResult::Timeout; | 323 | return Common::Input::DriverResult::Timeout; |
| 206 | } | 324 | } |
| 207 | } while (output.mcu_report != MCUReport::NFCState || | 325 | } while (output.mcu_report != MCUReport::NFCState || |
| 208 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || | 326 | (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || |
| @@ -212,10 +330,10 @@ DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, std::size_t timeout_l | |||
| 212 | data.uuid_size = std::min(output.mcu_data[14], static_cast<u8>(sizeof(TagUUID))); | 330 | data.uuid_size = std::min(output.mcu_data[14], static_cast<u8>(sizeof(TagUUID))); |
| 213 | memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size()); | 331 | memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size()); |
| 214 | 332 | ||
| 215 | return DriverResult::Success; | 333 | return Common::Input::DriverResult::Success; |
| 216 | } | 334 | } |
| 217 | 335 | ||
| 218 | DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | 336 | Common::Input::DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { |
| 219 | constexpr std::size_t timeout_limit = 60; | 337 | constexpr std::size_t timeout_limit = 60; |
| 220 | MCUCommandResponse output{}; | 338 | MCUCommandResponse output{}; |
| 221 | std::size_t tries = 0; | 339 | std::size_t tries = 0; |
| @@ -224,7 +342,7 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 224 | std::size_t ntag_buffer_pos = 0; | 342 | std::size_t ntag_buffer_pos = 0; |
| 225 | auto result = SendReadAmiiboRequest(output, NFCPages::Block135); | 343 | auto result = SendReadAmiiboRequest(output, NFCPages::Block135); |
| 226 | 344 | ||
| 227 | if (result != DriverResult::Success) { | 345 | if (result != Common::Input::DriverResult::Success) { |
| 228 | return result; | 346 | return result; |
| 229 | } | 347 | } |
| 230 | 348 | ||
| @@ -233,14 +351,14 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 233 | result = SendNextPackageRequest(output, package_index); | 351 | result = SendNextPackageRequest(output, package_index); |
| 234 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 352 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 235 | 353 | ||
| 236 | if (result != DriverResult::Success) { | 354 | if (result != Common::Input::DriverResult::Success) { |
| 237 | return result; | 355 | return result; |
| 238 | } | 356 | } |
| 239 | 357 | ||
| 240 | if ((output.mcu_report == MCUReport::NFCReadData || | 358 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 241 | output.mcu_report == MCUReport::NFCState) && | 359 | output.mcu_report == MCUReport::NFCState) && |
| 242 | nfc_status == NFCStatus::TagLost) { | 360 | nfc_status == NFCStatus::TagLost) { |
| 243 | return DriverResult::ErrorReadingData; | 361 | return Common::Input::DriverResult::ErrorReadingData; |
| 244 | } | 362 | } |
| 245 | 363 | ||
| 246 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { | 364 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { |
| @@ -259,14 +377,15 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { | |||
| 259 | 377 | ||
| 260 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { | 378 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) { |
| 261 | LOG_INFO(Input, "Finished reading amiibo"); | 379 | LOG_INFO(Input, "Finished reading amiibo"); |
| 262 | return DriverResult::Success; | 380 | return Common::Input::DriverResult::Success; |
| 263 | } | 381 | } |
| 264 | } | 382 | } |
| 265 | 383 | ||
| 266 | return DriverResult::Timeout; | 384 | return Common::Input::DriverResult::Timeout; |
| 267 | } | 385 | } |
| 268 | 386 | ||
| 269 | DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<const u8> data) { | 387 | Common::Input::DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, |
| 388 | std::span<const u8> data) { | ||
| 270 | constexpr std::size_t timeout_limit = 60; | 389 | constexpr std::size_t timeout_limit = 60; |
| 271 | const auto nfc_data = MakeAmiiboWritePackage(tag_uuid, data); | 390 | const auto nfc_data = MakeAmiiboWritePackage(tag_uuid, data); |
| 272 | const std::vector<u8> nfc_buffer_data = SerializeWritePackage(nfc_data); | 391 | const std::vector<u8> nfc_buffer_data = SerializeWritePackage(nfc_data); |
| @@ -281,7 +400,7 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 281 | 400 | ||
| 282 | auto result = SendWriteAmiiboRequest(output, tag_uuid); | 401 | auto result = SendWriteAmiiboRequest(output, tag_uuid); |
| 283 | 402 | ||
| 284 | if (result != DriverResult::Success) { | 403 | if (result != Common::Input::DriverResult::Success) { |
| 285 | return result; | 404 | return result; |
| 286 | } | 405 | } |
| 287 | 406 | ||
| @@ -290,14 +409,14 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 290 | result = SendNextPackageRequest(output, package_index); | 409 | result = SendNextPackageRequest(output, package_index); |
| 291 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | 410 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); |
| 292 | 411 | ||
| 293 | if (result != DriverResult::Success) { | 412 | if (result != Common::Input::DriverResult::Success) { |
| 294 | return result; | 413 | return result; |
| 295 | } | 414 | } |
| 296 | 415 | ||
| 297 | if ((output.mcu_report == MCUReport::NFCReadData || | 416 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 298 | output.mcu_report == MCUReport::NFCState) && | 417 | output.mcu_report == MCUReport::NFCState) && |
| 299 | nfc_status == NFCStatus::TagLost) { | 418 | nfc_status == NFCStatus::TagLost) { |
| 300 | return DriverResult::ErrorReadingData; | 419 | return Common::Input::DriverResult::ErrorReadingData; |
| 301 | } | 420 | } |
| 302 | 421 | ||
| 303 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { | 422 | if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07) { |
| @@ -326,7 +445,131 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 326 | if ((output.mcu_report == MCUReport::NFCReadData || | 445 | if ((output.mcu_report == MCUReport::NFCReadData || |
| 327 | output.mcu_report == MCUReport::NFCState) && | 446 | output.mcu_report == MCUReport::NFCState) && |
| 328 | nfc_status == NFCStatus::TagLost) { | 447 | nfc_status == NFCStatus::TagLost) { |
| 329 | return DriverResult::ErrorReadingData; | 448 | return Common::Input::DriverResult::ErrorReadingData; |
| 449 | } | ||
| 450 | |||
| 451 | // Increase position when data is confirmed by the joycon | ||
| 452 | if (output.mcu_report == MCUReport::NFCState && | ||
| 453 | (output.mcu_data[1] << 8) + output.mcu_data[0] == 0x0500 && | ||
| 454 | output.mcu_data[3] == block_id) { | ||
| 455 | block_id++; | ||
| 456 | current_position = next_position; | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | return result; | ||
| 461 | } | ||
| 462 | |||
| 463 | Common::Input::DriverResult NfcProtocol::GetMifareData( | ||
| 464 | const MifareUUID& tag_uuid, std::span<const MifareReadChunk> read_request, | ||
| 465 | std::span<MifareReadData> out_data) { | ||
| 466 | constexpr std::size_t timeout_limit = 60; | ||
| 467 | const auto nfc_data = MakeMifareReadPackage(tag_uuid, read_request); | ||
| 468 | const std::vector<u8> nfc_buffer_data = SerializeMifareReadPackage(nfc_data); | ||
| 469 | std::span<const u8> buffer(nfc_buffer_data); | ||
| 470 | Common::Input::DriverResult result = Common::Input::DriverResult::Success; | ||
| 471 | MCUCommandResponse output{}; | ||
| 472 | u8 block_id = 1; | ||
| 473 | u8 package_index = 0; | ||
| 474 | std::size_t tries = 0; | ||
| 475 | std::size_t current_position = 0; | ||
| 476 | |||
| 477 | LOG_INFO(Input, "Reading Mifare data"); | ||
| 478 | |||
| 479 | // Send data request. Nfc buffer size is 31, Send the data in smaller packages | ||
| 480 | while (current_position < buffer.size() && tries++ < timeout_limit) { | ||
| 481 | const std::size_t next_position = | ||
| 482 | std::min(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); | ||
| 483 | const std::size_t block_size = next_position - current_position; | ||
| 484 | const bool is_last_packet = block_size < sizeof(NFCRequestState::raw_data); | ||
| 485 | |||
| 486 | SendReadDataMifareRequest(output, block_id, is_last_packet, | ||
| 487 | buffer.subspan(current_position, block_size)); | ||
| 488 | |||
| 489 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 490 | |||
| 491 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 492 | return Common::Input::DriverResult::ErrorReadingData; | ||
| 493 | } | ||
| 494 | |||
| 495 | // Increase position when data is confirmed by the joycon | ||
| 496 | if (output.mcu_report == MCUReport::NFCState && | ||
| 497 | (output.mcu_data[1] << 8) + output.mcu_data[0] == 0x0500 && | ||
| 498 | output.mcu_data[3] == block_id) { | ||
| 499 | block_id++; | ||
| 500 | current_position = next_position; | ||
| 501 | } | ||
| 502 | } | ||
| 503 | |||
| 504 | if (result != Common::Input::DriverResult::Success) { | ||
| 505 | return result; | ||
| 506 | } | ||
| 507 | |||
| 508 | // Wait for reply and save the output data | ||
| 509 | while (tries++ < timeout_limit) { | ||
| 510 | result = SendNextPackageRequest(output, package_index); | ||
| 511 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 512 | |||
| 513 | if (result != Common::Input::DriverResult::Success) { | ||
| 514 | return result; | ||
| 515 | } | ||
| 516 | |||
| 517 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 518 | return Common::Input::DriverResult::ErrorReadingData; | ||
| 519 | } | ||
| 520 | |||
| 521 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { | ||
| 522 | constexpr std::size_t DATA_LENGHT = 0x10 + 1; | ||
| 523 | constexpr std::size_t DATA_START = 11; | ||
| 524 | const u8 number_of_elements = output.mcu_data[10]; | ||
| 525 | for (std::size_t i = 0; i < number_of_elements; i++) { | ||
| 526 | out_data[i].sector = output.mcu_data[DATA_START + (i * DATA_LENGHT)]; | ||
| 527 | memcpy(out_data[i].data.data(), | ||
| 528 | output.mcu_data.data() + DATA_START + 1 + (i * DATA_LENGHT), | ||
| 529 | sizeof(MifareReadData::data)); | ||
| 530 | } | ||
| 531 | package_index++; | ||
| 532 | continue; | ||
| 533 | } | ||
| 534 | |||
| 535 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::MifareDone) { | ||
| 536 | LOG_INFO(Input, "Finished reading mifare"); | ||
| 537 | break; | ||
| 538 | } | ||
| 539 | } | ||
| 540 | |||
| 541 | return result; | ||
| 542 | } | ||
| 543 | |||
| 544 | Common::Input::DriverResult NfcProtocol::WriteMifareData( | ||
| 545 | const MifareUUID& tag_uuid, std::span<const MifareWriteChunk> write_request) { | ||
| 546 | constexpr std::size_t timeout_limit = 60; | ||
| 547 | const auto nfc_data = MakeMifareWritePackage(tag_uuid, write_request); | ||
| 548 | const std::vector<u8> nfc_buffer_data = SerializeMifareWritePackage(nfc_data); | ||
| 549 | std::span<const u8> buffer(nfc_buffer_data); | ||
| 550 | Common::Input::DriverResult result = Common::Input::DriverResult::Success; | ||
| 551 | MCUCommandResponse output{}; | ||
| 552 | u8 block_id = 1; | ||
| 553 | u8 package_index = 0; | ||
| 554 | std::size_t tries = 0; | ||
| 555 | std::size_t current_position = 0; | ||
| 556 | |||
| 557 | LOG_INFO(Input, "Writing Mifare data"); | ||
| 558 | |||
| 559 | // Send data request. Nfc buffer size is 31, Send the data in smaller packages | ||
| 560 | while (current_position < buffer.size() && tries++ < timeout_limit) { | ||
| 561 | const std::size_t next_position = | ||
| 562 | std::min(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); | ||
| 563 | const std::size_t block_size = next_position - current_position; | ||
| 564 | const bool is_last_packet = block_size < sizeof(NFCRequestState::raw_data); | ||
| 565 | |||
| 566 | SendReadDataMifareRequest(output, block_id, is_last_packet, | ||
| 567 | buffer.subspan(current_position, block_size)); | ||
| 568 | |||
| 569 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 570 | |||
| 571 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 572 | return Common::Input::DriverResult::ErrorReadingData; | ||
| 330 | } | 573 | } |
| 331 | 574 | ||
| 332 | // Increase position when data is confirmed by the joycon | 575 | // Increase position when data is confirmed by the joycon |
| @@ -338,11 +581,39 @@ DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid, std::span<con | |||
| 338 | } | 581 | } |
| 339 | } | 582 | } |
| 340 | 583 | ||
| 584 | if (result != Common::Input::DriverResult::Success) { | ||
| 585 | return result; | ||
| 586 | } | ||
| 587 | |||
| 588 | // Wait for reply and ignore the output data | ||
| 589 | while (tries++ < timeout_limit) { | ||
| 590 | result = SendNextPackageRequest(output, package_index); | ||
| 591 | const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); | ||
| 592 | |||
| 593 | if (result != Common::Input::DriverResult::Success) { | ||
| 594 | return result; | ||
| 595 | } | ||
| 596 | |||
| 597 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::TagLost) { | ||
| 598 | return Common::Input::DriverResult::ErrorReadingData; | ||
| 599 | } | ||
| 600 | |||
| 601 | if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) { | ||
| 602 | package_index++; | ||
| 603 | continue; | ||
| 604 | } | ||
| 605 | |||
| 606 | if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::MifareDone) { | ||
| 607 | LOG_INFO(Input, "Finished writing mifare"); | ||
| 608 | break; | ||
| 609 | } | ||
| 610 | } | ||
| 611 | |||
| 341 | return result; | 612 | return result; |
| 342 | } | 613 | } |
| 343 | 614 | ||
| 344 | DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, | 615 | Common::Input::DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, |
| 345 | bool is_second_attempt) { | 616 | bool is_second_attempt) { |
| 346 | NFCRequestState request{ | 617 | NFCRequestState request{ |
| 347 | .command_argument = NFCCommand::StartPolling, | 618 | .command_argument = NFCCommand::StartPolling, |
| 348 | .block_id = {}, | 619 | .block_id = {}, |
| @@ -367,7 +638,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output, | |||
| 367 | output); | 638 | output); |
| 368 | } | 639 | } |
| 369 | 640 | ||
| 370 | DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { | 641 | Common::Input::DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { |
| 371 | NFCRequestState request{ | 642 | NFCRequestState request{ |
| 372 | .command_argument = NFCCommand::StopPolling, | 643 | .command_argument = NFCCommand::StopPolling, |
| 373 | .block_id = {}, | 644 | .block_id = {}, |
| @@ -385,7 +656,8 @@ DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) { | |||
| 385 | output); | 656 | output); |
| 386 | } | 657 | } |
| 387 | 658 | ||
| 388 | DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id) { | 659 | Common::Input::DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, |
| 660 | u8 packet_id) { | ||
| 389 | NFCRequestState request{ | 661 | NFCRequestState request{ |
| 390 | .command_argument = NFCCommand::StartWaitingRecieve, | 662 | .command_argument = NFCCommand::StartWaitingRecieve, |
| 391 | .block_id = {}, | 663 | .block_id = {}, |
| @@ -403,7 +675,8 @@ DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, u8 | |||
| 403 | output); | 675 | output); |
| 404 | } | 676 | } |
| 405 | 677 | ||
| 406 | DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages) { | 678 | Common::Input::DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, |
| 679 | NFCPages ntag_pages) { | ||
| 407 | NFCRequestState request{ | 680 | NFCRequestState request{ |
| 408 | .command_argument = NFCCommand::ReadNtag, | 681 | .command_argument = NFCCommand::ReadNtag, |
| 409 | .block_id = {}, | 682 | .block_id = {}, |
| @@ -428,8 +701,8 @@ DriverResult NfcProtocol::SendReadAmiiboRequest(MCUCommandResponse& output, NFCP | |||
| 428 | output); | 701 | output); |
| 429 | } | 702 | } |
| 430 | 703 | ||
| 431 | DriverResult NfcProtocol::SendWriteAmiiboRequest(MCUCommandResponse& output, | 704 | Common::Input::DriverResult NfcProtocol::SendWriteAmiiboRequest(MCUCommandResponse& output, |
| 432 | const TagUUID& tag_uuid) { | 705 | const TagUUID& tag_uuid) { |
| 433 | NFCRequestState request{ | 706 | NFCRequestState request{ |
| 434 | .command_argument = NFCCommand::ReadNtag, | 707 | .command_argument = NFCCommand::ReadNtag, |
| 435 | .block_id = {}, | 708 | .block_id = {}, |
| @@ -454,9 +727,10 @@ DriverResult NfcProtocol::SendWriteAmiiboRequest(MCUCommandResponse& output, | |||
| 454 | output); | 727 | output); |
| 455 | } | 728 | } |
| 456 | 729 | ||
| 457 | DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandResponse& output, u8 block_id, | 730 | Common::Input::DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandResponse& output, |
| 458 | bool is_last_packet, | 731 | u8 block_id, |
| 459 | std::span<const u8> data) { | 732 | bool is_last_packet, |
| 733 | std::span<const u8> data) { | ||
| 460 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); | 734 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); |
| 461 | NFCRequestState request{ | 735 | NFCRequestState request{ |
| 462 | .command_argument = NFCCommand::WriteNtag, | 736 | .command_argument = NFCCommand::WriteNtag, |
| @@ -477,6 +751,29 @@ DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandResponse& output, | |||
| 477 | output); | 751 | output); |
| 478 | } | 752 | } |
| 479 | 753 | ||
| 754 | Common::Input::DriverResult NfcProtocol::SendReadDataMifareRequest(MCUCommandResponse& output, | ||
| 755 | u8 block_id, bool is_last_packet, | ||
| 756 | std::span<const u8> data) { | ||
| 757 | const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); | ||
| 758 | NFCRequestState request{ | ||
| 759 | .command_argument = NFCCommand::Mifare, | ||
| 760 | .block_id = block_id, | ||
| 761 | .packet_id = {}, | ||
| 762 | .packet_flag = | ||
| 763 | is_last_packet ? MCUPacketFlag::LastCommandPacket : MCUPacketFlag::MorePacketsRemaining, | ||
| 764 | .data_length = static_cast<u8>(data_size), | ||
| 765 | .raw_data = {}, | ||
| 766 | .crc = {}, | ||
| 767 | }; | ||
| 768 | memcpy(request.raw_data.data(), data.data(), data_size); | ||
| 769 | |||
| 770 | std::array<u8, sizeof(NFCRequestState)> request_data{}; | ||
| 771 | memcpy(request_data.data(), &request, sizeof(NFCRequestState)); | ||
| 772 | request_data[36] = CalculateMCU_CRC8(request_data.data(), 36); | ||
| 773 | return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, MCUSubCommand::ReadDeviceMode, request_data, | ||
| 774 | output); | ||
| 775 | } | ||
| 776 | |||
| 480 | std::vector<u8> NfcProtocol::SerializeWritePackage(const NFCWritePackage& package) const { | 777 | std::vector<u8> NfcProtocol::SerializeWritePackage(const NFCWritePackage& package) const { |
| 481 | const std::size_t header_size = | 778 | const std::size_t header_size = |
| 482 | sizeof(NFCWriteCommandData) + sizeof(NFCWritePackage::number_of_chunks); | 779 | sizeof(NFCWriteCommandData) + sizeof(NFCWritePackage::number_of_chunks); |
| @@ -498,6 +795,48 @@ std::vector<u8> NfcProtocol::SerializeWritePackage(const NFCWritePackage& packag | |||
| 498 | return serialized_data; | 795 | return serialized_data; |
| 499 | } | 796 | } |
| 500 | 797 | ||
| 798 | std::vector<u8> NfcProtocol::SerializeMifareReadPackage(const MifareReadPackage& package) const { | ||
| 799 | const std::size_t header_size = sizeof(MifareCommandData); | ||
| 800 | std::vector<u8> serialized_data(header_size); | ||
| 801 | std::size_t start_index = 0; | ||
| 802 | |||
| 803 | memcpy(serialized_data.data(), &package, header_size); | ||
| 804 | start_index += header_size; | ||
| 805 | |||
| 806 | for (const auto& data_chunk : package.data_chunks) { | ||
| 807 | const std::size_t chunk_size = sizeof(MifareReadChunk); | ||
| 808 | if (data_chunk.command == MifareCmd::None) { | ||
| 809 | continue; | ||
| 810 | } | ||
| 811 | serialized_data.resize(start_index + chunk_size); | ||
| 812 | memcpy(serialized_data.data() + start_index, &data_chunk, chunk_size); | ||
| 813 | start_index += chunk_size; | ||
| 814 | } | ||
| 815 | |||
| 816 | return serialized_data; | ||
| 817 | } | ||
| 818 | |||
| 819 | std::vector<u8> NfcProtocol::SerializeMifareWritePackage(const MifareWritePackage& package) const { | ||
| 820 | const std::size_t header_size = sizeof(MifareCommandData); | ||
| 821 | std::vector<u8> serialized_data(header_size); | ||
| 822 | std::size_t start_index = 0; | ||
| 823 | |||
| 824 | memcpy(serialized_data.data(), &package, header_size); | ||
| 825 | start_index += header_size; | ||
| 826 | |||
| 827 | for (const auto& data_chunk : package.data_chunks) { | ||
| 828 | const std::size_t chunk_size = sizeof(MifareWriteChunk); | ||
| 829 | if (data_chunk.command == MifareCmd::None) { | ||
| 830 | continue; | ||
| 831 | } | ||
| 832 | serialized_data.resize(start_index + chunk_size); | ||
| 833 | memcpy(serialized_data.data() + start_index, &data_chunk, chunk_size); | ||
| 834 | start_index += chunk_size; | ||
| 835 | } | ||
| 836 | |||
| 837 | return serialized_data; | ||
| 838 | } | ||
| 839 | |||
| 501 | NFCWritePackage NfcProtocol::MakeAmiiboWritePackage(const TagUUID& tag_uuid, | 840 | NFCWritePackage NfcProtocol::MakeAmiiboWritePackage(const TagUUID& tag_uuid, |
| 502 | std::span<const u8> data) const { | 841 | std::span<const u8> data) const { |
| 503 | return { | 842 | return { |
| @@ -527,6 +866,46 @@ NFCWritePackage NfcProtocol::MakeAmiiboWritePackage(const TagUUID& tag_uuid, | |||
| 527 | }; | 866 | }; |
| 528 | } | 867 | } |
| 529 | 868 | ||
| 869 | MifareReadPackage NfcProtocol::MakeMifareReadPackage( | ||
| 870 | const MifareUUID& tag_uuid, std::span<const MifareReadChunk> read_request) const { | ||
| 871 | MifareReadPackage package{ | ||
| 872 | .command_data{ | ||
| 873 | .unknown1 = 0xd0, | ||
| 874 | .unknown2 = 0x07, | ||
| 875 | .number_of_short_bytes = static_cast<u8>( | ||
| 876 | ((read_request.size() * sizeof(MifareReadChunk)) + sizeof(MifareUUID)) / 2), | ||
| 877 | .uid = tag_uuid, | ||
| 878 | }, | ||
| 879 | .data_chunks = {}, | ||
| 880 | }; | ||
| 881 | |||
| 882 | for (std::size_t i = 0; i < read_request.size() && i < package.data_chunks.size(); ++i) { | ||
| 883 | package.data_chunks[i] = read_request[i]; | ||
| 884 | } | ||
| 885 | |||
| 886 | return package; | ||
| 887 | } | ||
| 888 | |||
| 889 | MifareWritePackage NfcProtocol::MakeMifareWritePackage( | ||
| 890 | const MifareUUID& tag_uuid, std::span<const MifareWriteChunk> read_request) const { | ||
| 891 | MifareWritePackage package{ | ||
| 892 | .command_data{ | ||
| 893 | .unknown1 = 0xd0, | ||
| 894 | .unknown2 = 0x07, | ||
| 895 | .number_of_short_bytes = static_cast<u8>( | ||
| 896 | ((read_request.size() * sizeof(MifareReadChunk)) + sizeof(MifareUUID) + 2) / 2), | ||
| 897 | .uid = tag_uuid, | ||
| 898 | }, | ||
| 899 | .data_chunks = {}, | ||
| 900 | }; | ||
| 901 | |||
| 902 | for (std::size_t i = 0; i < read_request.size() && i < package.data_chunks.size(); ++i) { | ||
| 903 | package.data_chunks[i] = read_request[i]; | ||
| 904 | } | ||
| 905 | |||
| 906 | return package; | ||
| 907 | } | ||
| 908 | |||
| 530 | NFCDataChunk NfcProtocol::MakeAmiiboChunk(u8 page, u8 size, std::span<const u8> data) const { | 909 | NFCDataChunk NfcProtocol::MakeAmiiboChunk(u8 page, u8 size, std::span<const u8> data) const { |
| 531 | constexpr u8 NFC_PAGE_SIZE = 4; | 910 | constexpr u8 NFC_PAGE_SIZE = 4; |
| 532 | 911 | ||
| @@ -606,4 +985,8 @@ bool NfcProtocol::IsEnabled() const { | |||
| 606 | return is_enabled; | 985 | return is_enabled; |
| 607 | } | 986 | } |
| 608 | 987 | ||
| 988 | bool NfcProtocol::IsPolling() const { | ||
| 989 | return is_polling; | ||
| 990 | } | ||
| 991 | |||
| 609 | } // namespace InputCommon::Joycon | 992 | } // namespace InputCommon::Joycon |