diff options
Diffstat (limited to '')
-rw-r--r-- | src/input_common/drivers/virtual_amiibo.cpp | 179 |
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( VirtualAmiibo::~VirtualAmiibo() = default; -Common::Input::PollingError VirtualAmiibo::SetPollingMode( +Common::Input::DriverResult VirtualAmiibo::SetPollingMode( [[maybe_unused]] const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) { polling_mode = polling_mode_; - if (polling_mode == Common::Input::PollingMode::NFC) { - if (state == State::Initialized) { - state = State::WaitingForAmiibo; - } - } else { - if (state == State::AmiiboIsOpen) { + switch (polling_mode) { + case Common::Input::PollingMode::NFC: + state = State::Initialized; + return Common::Input::DriverResult::Success; + default: + if (state == State::TagNearby) { CloseAmiibo(); } + state = State::Disabled; + return Common::Input::DriverResult::NotSupported; } - - return Common::Input::PollingError::None; } Common::Input::NfcState VirtualAmiibo::SupportsNfc( [[maybe_unused]] const PadIdentifier& identifier_) const { return Common::Input::NfcState::Success; } +Common::Input::NfcState VirtualAmiibo::StartNfcPolling(const PadIdentifier& identifier_) { + if (state != State::Initialized) { + return Common::Input::NfcState::WrongDeviceState; + } + state = State::WaitingForAmiibo; + return Common::Input::NfcState::Success; +} + +Common::Input::NfcState VirtualAmiibo::StopNfcPolling(const PadIdentifier& identifier_) { + if (state == State::Disabled) { + return Common::Input::NfcState::WrongDeviceState; + } + if (state == State::TagNearby) { + CloseAmiibo(); + } + state = State::Initialized; + return Common::Input::NfcState::Success; +} + +Common::Input::NfcState VirtualAmiibo::ReadAmiiboData(const PadIdentifier& identifier_, + std::vector<u8>& out_data) { + if (state != State::TagNearby) { + return Common::Input::NfcState::WrongDeviceState; + } + + if (status.tag_type != 1U << 1) { + return Common::Input::NfcState::InvalidTagType; + } + + out_data.resize(nfc_data.size()); + memcpy(out_data.data(), nfc_data.data(), nfc_data.size()); + return Common::Input::NfcState::Success; +} Common::Input::NfcState VirtualAmiibo::WriteNfcData( [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { @@ -56,7 +89,7 @@ Common::Input::NfcState VirtualAmiibo::WriteNfcData( } if (!nfc_file.Write(data)) { - LOG_ERROR(Service_NFP, "Error writting to file"); + LOG_ERROR(Service_NFP, "Error writing to file"); return Common::Input::NfcState::WriteFailed; } @@ -65,6 +98,69 @@ Common::Input::NfcState VirtualAmiibo::WriteNfcData( return Common::Input::NfcState::Success; } +Common::Input::NfcState VirtualAmiibo::ReadMifareData(const PadIdentifier& identifier_, + const Common::Input::MifareRequest& request, + Common::Input::MifareRequest& out_data) { + if (state != State::TagNearby) { + return Common::Input::NfcState::WrongDeviceState; + } + + if (status.tag_type != 1U << 6) { + return Common::Input::NfcState::InvalidTagType; + } + + for (std::size_t i = 0; i < request.data.size(); i++) { + if (request.data[i].command == 0) { + continue; + } + out_data.data[i].command = request.data[i].command; + out_data.data[i].sector = request.data[i].sector; + + const std::size_t sector_index = + request.data[i].sector * sizeof(Common::Input::MifareData::data); + + if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) { + return Common::Input::NfcState::WriteFailed; + } + + // Ignore the sector key as we don't support it + memcpy(out_data.data[i].data.data(), nfc_data.data() + sector_index, + sizeof(Common::Input::MifareData::data)); + } + + return Common::Input::NfcState::Success; +} + +Common::Input::NfcState VirtualAmiibo::WriteMifareData( + const PadIdentifier& identifier_, const Common::Input::MifareRequest& request) { + if (state != State::TagNearby) { + return Common::Input::NfcState::WrongDeviceState; + } + + if (status.tag_type != 1U << 6) { + return Common::Input::NfcState::InvalidTagType; + } + + for (std::size_t i = 0; i < request.data.size(); i++) { + if (request.data[i].command == 0) { + continue; + } + + const std::size_t sector_index = + request.data[i].sector * sizeof(Common::Input::MifareData::data); + + if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) { + return Common::Input::NfcState::WriteFailed; + } + + // Ignore the sector key as we don't support it + memcpy(nfc_data.data() + sector_index, request.data[i].data.data(), + sizeof(Common::Input::MifareData::data)); + } + + return Common::Input::NfcState::Success; +} + VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { return state; } @@ -72,10 +168,7 @@ VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { const Common::FS::IOFile nfc_file{filename, Common::FS::FileAccessMode::Read, Common::FS::FileType::BinaryFile}; - - if (state != State::WaitingForAmiibo) { - return Info::WrongDeviceState; - } + std::vector<u8> data{}; if (!nfc_file.IsOpen()) { return Info::UnableToLoad; @@ -84,14 +177,15 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { switch (nfc_file.GetSize()) { case AmiiboSize: case AmiiboSizeWithoutPassword: - nfc_data.resize(AmiiboSize); - if (nfc_file.Read(nfc_data) < AmiiboSizeWithoutPassword) { + case AmiiboSizeWithSignature: + data.resize(AmiiboSize); + if (nfc_file.Read(data) < AmiiboSizeWithoutPassword) { return Info::NotAnAmiibo; } break; case MifareSize: - nfc_data.resize(MifareSize); - if (nfc_file.Read(nfc_data) < MifareSize) { + data.resize(MifareSize); + if (nfc_file.Read(data) < MifareSize) { return Info::NotAnAmiibo; } break; @@ -100,14 +194,44 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { } file_path = filename; - state = State::AmiiboIsOpen; - SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); + return LoadAmiibo(data); +} + +VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(std::span<u8> data) { + if (state != State::WaitingForAmiibo) { + return Info::WrongDeviceState; + } + + switch (data.size_bytes()) { + case AmiiboSize: + case AmiiboSizeWithoutPassword: + case AmiiboSizeWithSignature: + nfc_data.resize(AmiiboSize); + status.tag_type = 1U << 1; + status.uuid_length = 7; + break; + case MifareSize: + nfc_data.resize(MifareSize); + status.tag_type = 1U << 6; + status.uuid_length = 4; + break; + default: + return Info::NotAnAmiibo; + } + + status.uuid = {}; + status.protocol = 1; + state = State::TagNearby; + status.state = Common::Input::NfcState::NewAmiibo, + memcpy(nfc_data.data(), data.data(), data.size_bytes()); + memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length); + SetNfc(identifier, status); return Info::Success; } VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { - if (state == State::AmiiboIsOpen) { - SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); + if (state == State::TagNearby) { + SetNfc(identifier, status); return Info::Success; } @@ -115,9 +239,14 @@ VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { } VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() { - state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo - : State::Initialized; - SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}}); + if (state != State::TagNearby) { + return Info::Success; + } + + state = State::WaitingForAmiibo; + status.state = Common::Input::NfcState::AmiiboRemoved; + SetNfc(identifier, status); + status.tag_type = 0; return Info::Success; } |