citra-emu
/
citra-canary
Archived
1
0
Fork 0

service: nfc: Keep tag alive while it's being used (#6687)

This commit is contained in:
Narr the Reg 2023-07-12 15:01:08 -06:00 committed by GitHub
parent d702915624
commit 8eebb83c2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 10 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);