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");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
ResultCode result = RESULT_SUCCESS;
|
||||
switch (nfc->nfc_mode) {
|
||||
case CommunicationMode::Ntag:
|
||||
|
@ -310,6 +312,8 @@ void Module::Interface::GetTagInfo2(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
||||
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(26, 0);
|
||||
|
@ -330,6 +334,8 @@ void Module::Interface::GetTagInfo(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode == CommunicationMode::TrainTag) {
|
||||
LOG_ERROR(Service_NFC, "CommunicationMode {} not implemented", nfc->nfc_mode);
|
||||
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);
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultInvalidOperation);
|
||||
|
@ -397,6 +405,8 @@ void Module::Interface::ReadApplicationArea(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultInvalidOperation);
|
||||
|
@ -436,6 +446,8 @@ void Module::Interface::GetNfpRegisterInfo(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultInvalidOperation);
|
||||
|
@ -455,6 +467,8 @@ void Module::Interface::GetNfpCommonInfo(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultInvalidOperation);
|
||||
|
@ -515,6 +529,8 @@ void Module::Interface::GetIdentificationBlock(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultInvalidOperation);
|
||||
|
@ -548,6 +564,8 @@ void Module::Interface::GetAdminInfo(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
LOG_INFO(Service_NFC, "called");
|
||||
|
||||
nfc->device->RescheduleTagRemoveEvent();
|
||||
|
||||
if (nfc->nfc_mode != CommunicationMode::Amiibo) {
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(ResultInvalidOperation);
|
||||
|
|
|
@ -38,10 +38,7 @@ void NfcDevice::serialize(Archive& ar, const unsigned int) {
|
|||
}
|
||||
SERIALIZE_IMPL(NfcDevice)
|
||||
|
||||
/// The interval at which the amiibo will be removed automatically 1.5s
|
||||
static constexpr u64 amiibo_removal_interval_us = 268 * 1000 * 1000;
|
||||
|
||||
NfcDevice::NfcDevice(Core::System& system) {
|
||||
NfcDevice::NfcDevice(Core::System& system_) : system{system_} {
|
||||
tag_in_range_event =
|
||||
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NFC::tag_in_range_event");
|
||||
tag_out_of_range_event =
|
||||
|
@ -88,8 +85,7 @@ bool NfcDevice::LoadAmiibo(std::string filename) {
|
|||
tag_out_of_range_event->Clear();
|
||||
tag_in_range_event->Signal();
|
||||
|
||||
Core::System::GetInstance().CoreTiming().ScheduleEvent(amiibo_removal_interval_us,
|
||||
remove_amiibo_event);
|
||||
RescheduleTagRemoveEvent();
|
||||
|
||||
// Fallback for plain amiibos
|
||||
if (is_plain_amiibo) {
|
||||
|
@ -270,6 +266,9 @@ ResultCode NfcDevice::Flush() {
|
|||
return connection_result;
|
||||
}
|
||||
|
||||
// Ensure the tag will not be removed in the middle of a write
|
||||
RescheduleTagRemoveEvent();
|
||||
|
||||
auto& settings = tag.file.settings;
|
||||
|
||||
const auto& current_date = GetAmiiboDate();
|
||||
|
@ -888,8 +887,7 @@ ResultCode NfcDevice::RecreateApplicationArea(u32 access_id, std::span<const u8>
|
|||
}
|
||||
|
||||
u64 application_id{};
|
||||
if (Core::System::GetInstance().GetAppLoader().ReadProgramId(application_id) ==
|
||||
Loader::ResultStatus::Success) {
|
||||
if (system.GetAppLoader().ReadProgramId(application_id) == Loader::ResultStatus::Success) {
|
||||
tag.file.application_id_byte =
|
||||
static_cast<u8>(application_id >> application_id_version_offset & 0xf);
|
||||
tag.file.application_id =
|
||||
|
@ -1008,7 +1006,7 @@ void NfcDevice::SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
// 3DS console time uses Jan 1 1900 as internal epoch,
|
||||
|
@ -1111,4 +1109,18 @@ void NfcDevice::BuildAmiiboWithoutKeys() {
|
|||
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
|
||||
|
|
|
@ -21,7 +21,7 @@ class KReadableEvent;
|
|||
namespace Service::NFC {
|
||||
class NfcDevice {
|
||||
public:
|
||||
NfcDevice(Core::System& system);
|
||||
NfcDevice(Core::System& system_);
|
||||
~NfcDevice();
|
||||
|
||||
bool LoadAmiibo(std::string filename);
|
||||
|
@ -71,6 +71,10 @@ public:
|
|||
std::shared_ptr<Kernel::Event> GetActivateEvent() 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:
|
||||
time_t GetCurrentTime() const;
|
||||
void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name);
|
||||
|
@ -100,6 +104,7 @@ private:
|
|||
|
||||
SerializableAmiiboFile tag{};
|
||||
SerializableEncryptedAmiiboFile encrypted_tag{};
|
||||
Core::System& system;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int);
|
||||
|
|
Reference in New Issue