| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include <cstring>
- #include <fmt/format.h>
- #include "common/fs/file.h"
- #include "common/fs/fs.h"
- #include "common/fs/path_util.h"
- #include "common/logging/log.h"
- #include "common/settings.h"
- #include "input_common/drivers/virtual_amiibo.h"
- namespace InputCommon {
- constexpr PadIdentifier identifier = {
- .guid = Common::UUID{},
- .port = 0,
- .pad = 0,
- };
- VirtualAmiibo::VirtualAmiibo(std::string input_engine_) : InputEngine(std::move(input_engine_)) {}
- VirtualAmiibo::~VirtualAmiibo() = default;
- Common::Input::DriverResult VirtualAmiibo::SetPollingMode(
- [[maybe_unused]] const PadIdentifier& identifier_,
- const Common::Input::PollingMode polling_mode_) {
- polling_mode = polling_mode_;
- 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;
- }
- }
- 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) {
- const Common::FS::IOFile nfc_file{file_path, Common::FS::FileAccessMode::ReadWrite,
- Common::FS::FileType::BinaryFile};
- if (!nfc_file.IsOpen()) {
- LOG_ERROR(Core, "Amiibo is already on use");
- return Common::Input::NfcState::WriteFailed;
- }
- if (!nfc_file.Write(data)) {
- LOG_ERROR(Service_NFP, "Error writing to file");
- return Common::Input::NfcState::WriteFailed;
- }
- nfc_data = data;
- 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;
- }
- VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) {
- const Common::FS::IOFile nfc_file{filename, Common::FS::FileAccessMode::Read,
- Common::FS::FileType::BinaryFile};
- std::vector<u8> data{};
- if (!nfc_file.IsOpen()) {
- return Info::UnableToLoad;
- }
- switch (nfc_file.GetSize()) {
- case AmiiboSize:
- case AmiiboSizeWithoutPassword:
- case AmiiboSizeWithSignature:
- data.resize(AmiiboSize);
- if (nfc_file.Read(data) < AmiiboSizeWithoutPassword) {
- return Info::NotAnAmiibo;
- }
- break;
- case MifareSize:
- data.resize(MifareSize);
- if (nfc_file.Read(data) < MifareSize) {
- return Info::NotAnAmiibo;
- }
- break;
- default:
- return Info::NotAnAmiibo;
- }
- file_path = filename;
- 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::TagNearby) {
- SetNfc(identifier, status);
- return Info::Success;
- }
- return LoadAmiibo(file_path);
- }
- VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() {
- 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;
- }
- std::string VirtualAmiibo::GetLastFilePath() const {
- return file_path;
- }
- } // namespace InputCommon
|