service: nfc: Keep tag alive while it's being used (#6687)
This commit is contained in:
parent
d702915624
commit
8eebb83c2c
|
@ -175,6 +175,8 @@ void Module::Interface::Mount(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
ResultCode result = RESULT_SUCCESS;
|
ResultCode result = RESULT_SUCCESS;
|
||||||
switch (nfc->nfc_mode) {
|
switch (nfc->nfc_mode) {
|
||||||
case CommunicationMode::Ntag:
|
case CommunicationMode::Ntag:
|
||||||
|
@ -310,6 +312,8 @@ void Module::Interface::GetTagInfo2(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
||||||
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(26, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(26, 0);
|
||||||
|
@ -330,6 +334,8 @@ void Module::Interface::GetTagInfo(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
||||||
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(12, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(12, 0);
|
||||||
|
@ -360,6 +366,8 @@ void Module::Interface::OpenApplicationArea(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called, access_id={}", access_id);
|
LOG_INFO(Service_NFC, "called, access_id={}", access_id);
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultInvalidOperation);
|
rb.Push(ResultInvalidOperation);
|
||||||
|
@ -397,6 +405,8 @@ void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultInvalidOperation);
|
rb.Push(ResultInvalidOperation);
|
||||||
|
@ -436,6 +446,8 @@ void Module::Interface::GetNfpRegisterInfo(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultInvalidOperation);
|
rb.Push(ResultInvalidOperation);
|
||||||
|
@ -455,6 +467,8 @@ void Module::Interface::GetNfpCommonInfo(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultInvalidOperation);
|
rb.Push(ResultInvalidOperation);
|
||||||
|
@ -515,6 +529,8 @@ void Module::Interface::GetIdentificationBlock(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultInvalidOperation);
|
rb.Push(ResultInvalidOperation);
|
||||||
|
@ -548,6 +564,8 @@ void Module::Interface::GetAdminInfo(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_NFC, "called");
|
LOG_INFO(Service_NFC, "called");
|
||||||
|
|
||||||
|
nfc->device->RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultInvalidOperation);
|
rb.Push(ResultInvalidOperation);
|
||||||
|
|
|
@ -38,10 +38,7 @@ void NfcDevice::serialize(Archive& ar, const unsigned int) {
|
||||||
}
|
}
|
||||||
SERIALIZE_IMPL(NfcDevice)
|
SERIALIZE_IMPL(NfcDevice)
|
||||||
|
|
||||||
/// The interval at which the amiibo will be removed automatically 1.5s
|
NfcDevice::NfcDevice(Core::System& system_) : system{system_} {
|
||||||
static constexpr u64 amiibo_removal_interval_us = 268 * 1000 * 1000;
|
|
||||||
|
|
||||||
NfcDevice::NfcDevice(Core::System& system) {
|
|
||||||
tag_in_range_event =
|
tag_in_range_event =
|
||||||
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NFC::tag_in_range_event");
|
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NFC::tag_in_range_event");
|
||||||
tag_out_of_range_event =
|
tag_out_of_range_event =
|
||||||
|
@ -88,8 +85,7 @@ bool NfcDevice::LoadAmiibo(std::string filename) {
|
||||||
tag_out_of_range_event->Clear();
|
tag_out_of_range_event->Clear();
|
||||||
tag_in_range_event->Signal();
|
tag_in_range_event->Signal();
|
||||||
|
|
||||||
Core::System::GetInstance().CoreTiming().ScheduleEvent(amiibo_removal_interval_us,
|
RescheduleTagRemoveEvent();
|
||||||
remove_amiibo_event);
|
|
||||||
|
|
||||||
// Fallback for plain amiibos
|
// Fallback for plain amiibos
|
||||||
if (is_plain_amiibo) {
|
if (is_plain_amiibo) {
|
||||||
|
@ -270,6 +266,9 @@ ResultCode NfcDevice::Flush() {
|
||||||
return connection_result;
|
return connection_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the tag will not be removed in the middle of a write
|
||||||
|
RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
auto& settings = tag.file.settings;
|
auto& settings = tag.file.settings;
|
||||||
|
|
||||||
const auto& current_date = GetAmiiboDate();
|
const auto& current_date = GetAmiiboDate();
|
||||||
|
@ -888,8 +887,7 @@ ResultCode NfcDevice::RecreateApplicationArea(u32 access_id, std::span<const u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 application_id{};
|
u64 application_id{};
|
||||||
if (Core::System::GetInstance().GetAppLoader().ReadProgramId(application_id) ==
|
if (system.GetAppLoader().ReadProgramId(application_id) == Loader::ResultStatus::Success) {
|
||||||
Loader::ResultStatus::Success) {
|
|
||||||
tag.file.application_id_byte =
|
tag.file.application_id_byte =
|
||||||
static_cast<u8>(application_id >> application_id_version_offset & 0xf);
|
static_cast<u8>(application_id >> application_id_version_offset & 0xf);
|
||||||
tag.file.application_id =
|
tag.file.application_id =
|
||||||
|
@ -1008,7 +1006,7 @@ void NfcDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t NfcDevice::GetCurrentTime() const {
|
time_t NfcDevice::GetCurrentTime() const {
|
||||||
auto& share_page = Core::System::GetInstance().Kernel().GetSharedPageHandler();
|
auto& share_page = system.Kernel().GetSharedPageHandler();
|
||||||
const auto console_time = share_page.GetSharedPage().date_time_1.date_time / 1000;
|
const auto console_time = share_page.GetSharedPage().date_time_1.date_time / 1000;
|
||||||
|
|
||||||
// 3DS console time uses Jan 1 1900 as internal epoch,
|
// 3DS console time uses Jan 1 1900 as internal epoch,
|
||||||
|
@ -1111,4 +1109,18 @@ void NfcDevice::BuildAmiiboWithoutKeys() {
|
||||||
settings.settings.appdata_initialized.Assign(0);
|
settings.settings.appdata_initialized.Assign(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NfcDevice::RescheduleTagRemoveEvent() {
|
||||||
|
/// The interval at which the amiibo will be removed automatically 1.5s
|
||||||
|
static constexpr u64 amiibo_removal_interval = nsToCycles(1500 * 1000 * 1000);
|
||||||
|
|
||||||
|
system.CoreTiming().UnscheduleEvent(remove_amiibo_event, 0);
|
||||||
|
|
||||||
|
if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted &&
|
||||||
|
device_state != DeviceState::TagPartiallyMounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
system.CoreTiming().ScheduleEvent(amiibo_removal_interval, remove_amiibo_event);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::NFC
|
} // namespace Service::NFC
|
||||||
|
|
|
@ -21,7 +21,7 @@ class KReadableEvent;
|
||||||
namespace Service::NFC {
|
namespace Service::NFC {
|
||||||
class NfcDevice {
|
class NfcDevice {
|
||||||
public:
|
public:
|
||||||
NfcDevice(Core::System& system);
|
NfcDevice(Core::System& system_);
|
||||||
~NfcDevice();
|
~NfcDevice();
|
||||||
|
|
||||||
bool LoadAmiibo(std::string filename);
|
bool LoadAmiibo(std::string filename);
|
||||||
|
@ -71,6 +71,10 @@ public:
|
||||||
std::shared_ptr<Kernel::Event> GetActivateEvent() const;
|
std::shared_ptr<Kernel::Event> GetActivateEvent() const;
|
||||||
std::shared_ptr<Kernel::Event> GetDeactivateEvent() const;
|
std::shared_ptr<Kernel::Event> GetDeactivateEvent() const;
|
||||||
|
|
||||||
|
/// Automatically removes the nfc tag after x ammount of time.
|
||||||
|
/// If called multiple times the counter will be restarted.
|
||||||
|
void RescheduleTagRemoveEvent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
time_t GetCurrentTime() const;
|
time_t GetCurrentTime() const;
|
||||||
void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name);
|
void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name);
|
||||||
|
@ -100,6 +104,7 @@ private:
|
||||||
|
|
||||||
SerializableAmiiboFile tag{};
|
SerializableAmiiboFile tag{};
|
||||||
SerializableEncryptedAmiiboFile encrypted_tag{};
|
SerializableEncryptedAmiiboFile encrypted_tag{};
|
||||||
|
Core::System& system;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int);
|
void serialize(Archive& ar, const unsigned int);
|
||||||
|
|
Reference in New Issue