mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #10097 from german77/nfp_full
service: nfc: Merge device interfaces and create the device manager
This commit is contained in:
		@@ -555,21 +555,22 @@ add_library(core STATIC
 | 
				
			|||||||
    hle/service/mnpp/mnpp_app.h
 | 
					    hle/service/mnpp/mnpp_app.h
 | 
				
			||||||
    hle/service/ncm/ncm.cpp
 | 
					    hle/service/ncm/ncm.cpp
 | 
				
			||||||
    hle/service/ncm/ncm.h
 | 
					    hle/service/ncm/ncm.h
 | 
				
			||||||
    hle/service/nfc/mifare_user.cpp
 | 
					    hle/service/nfc/common/amiibo_crypto.cpp
 | 
				
			||||||
    hle/service/nfc/mifare_user.h
 | 
					    hle/service/nfc/common/amiibo_crypto.h
 | 
				
			||||||
 | 
					    hle/service/nfc/common/device.cpp
 | 
				
			||||||
 | 
					    hle/service/nfc/common/device.h
 | 
				
			||||||
 | 
					    hle/service/nfc/common/device_manager.cpp
 | 
				
			||||||
 | 
					    hle/service/nfc/common/device_manager.h
 | 
				
			||||||
 | 
					    hle/service/nfc/mifare_result.h
 | 
				
			||||||
 | 
					    hle/service/nfc/mifare_types.h
 | 
				
			||||||
    hle/service/nfc/nfc.cpp
 | 
					    hle/service/nfc/nfc.cpp
 | 
				
			||||||
    hle/service/nfc/nfc.h
 | 
					    hle/service/nfc/nfc.h
 | 
				
			||||||
    hle/service/nfc/nfc_device.cpp
 | 
					    hle/service/nfc/nfc_interface.cpp
 | 
				
			||||||
    hle/service/nfc/nfc_device.h
 | 
					    hle/service/nfc/nfc_interface.h
 | 
				
			||||||
    hle/service/nfc/nfc_result.h
 | 
					    hle/service/nfc/nfc_result.h
 | 
				
			||||||
    hle/service/nfc/nfc_user.cpp
 | 
					    hle/service/nfc/nfc_types.h
 | 
				
			||||||
    hle/service/nfc/nfc_user.h
 | 
					 | 
				
			||||||
    hle/service/nfp/amiibo_crypto.cpp
 | 
					 | 
				
			||||||
    hle/service/nfp/amiibo_crypto.h
 | 
					 | 
				
			||||||
    hle/service/nfp/nfp.cpp
 | 
					    hle/service/nfp/nfp.cpp
 | 
				
			||||||
    hle/service/nfp/nfp.h
 | 
					    hle/service/nfp/nfp.h
 | 
				
			||||||
    hle/service/nfp/nfp_device.cpp
 | 
					 | 
				
			||||||
    hle/service/nfp/nfp_device.h
 | 
					 | 
				
			||||||
    hle/service/nfp/nfp_interface.cpp
 | 
					    hle/service/nfp/nfp_interface.cpp
 | 
				
			||||||
    hle/service/nfp/nfp_interface.h
 | 
					    hle/service/nfp/nfp_interface.h
 | 
				
			||||||
    hle/service/nfp/nfp_result.h
 | 
					    hle/service/nfp/nfp_result.h
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ void DefaultCabinetApplet::Close() const {}
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void DefaultCabinetApplet::ShowCabinetApplet(
 | 
					void DefaultCabinetApplet::ShowCabinetApplet(
 | 
				
			||||||
    const CabinetCallback& callback, const CabinetParameters& parameters,
 | 
					    const CabinetCallback& callback, const CabinetParameters& parameters,
 | 
				
			||||||
    std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const {
 | 
					    std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const {
 | 
				
			||||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
					    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
				
			||||||
    callback(false, {});
 | 
					    callback(false, {});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,9 +7,9 @@
 | 
				
			|||||||
#include "core/frontend/applets/applet.h"
 | 
					#include "core/frontend/applets/applet.h"
 | 
				
			||||||
#include "core/hle/service/nfp/nfp_types.h"
 | 
					#include "core/hle/service/nfp/nfp_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP {
 | 
					namespace Service::NFC {
 | 
				
			||||||
class NfpDevice;
 | 
					class NfcDevice;
 | 
				
			||||||
} // namespace Service::NFP
 | 
					} // namespace Service::NFC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Core::Frontend {
 | 
					namespace Core::Frontend {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,14 +26,14 @@ public:
 | 
				
			|||||||
    virtual ~CabinetApplet();
 | 
					    virtual ~CabinetApplet();
 | 
				
			||||||
    virtual void ShowCabinetApplet(const CabinetCallback& callback,
 | 
					    virtual void ShowCabinetApplet(const CabinetCallback& callback,
 | 
				
			||||||
                                   const CabinetParameters& parameters,
 | 
					                                   const CabinetParameters& parameters,
 | 
				
			||||||
                                   std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const = 0;
 | 
					                                   std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DefaultCabinetApplet final : public CabinetApplet {
 | 
					class DefaultCabinetApplet final : public CabinetApplet {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    void Close() const override;
 | 
					    void Close() const override;
 | 
				
			||||||
    void ShowCabinetApplet(const CabinetCallback& callback, const CabinetParameters& parameters,
 | 
					    void ShowCabinetApplet(const CabinetCallback& callback, const CabinetParameters& parameters,
 | 
				
			||||||
                           std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override;
 | 
					                           std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const override;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Core::Frontend
 | 
					} // namespace Core::Frontend
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
#include "core/hle/service/am/am.h"
 | 
					#include "core/hle/service/am/am.h"
 | 
				
			||||||
#include "core/hle/service/am/applets/applet_cabinet.h"
 | 
					#include "core/hle/service/am/applets/applet_cabinet.h"
 | 
				
			||||||
#include "core/hle/service/mii/mii_manager.h"
 | 
					#include "core/hle/service/mii/mii_manager.h"
 | 
				
			||||||
#include "core/hle/service/nfp/nfp_device.h"
 | 
					#include "core/hle/service/nfc/common/device.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::AM::Applets {
 | 
					namespace Service::AM::Applets {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -72,10 +72,10 @@ void Cabinet::Execute() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // TODO: listen on all controllers
 | 
					    // TODO: listen on all controllers
 | 
				
			||||||
    if (nfp_device == nullptr) {
 | 
					    if (nfp_device == nullptr) {
 | 
				
			||||||
        nfp_device = std::make_shared<Service::NFP::NfpDevice>(
 | 
					        nfp_device = std::make_shared<Service::NFC::NfcDevice>(
 | 
				
			||||||
            system.HIDCore().GetFirstNpadId(), system, service_context, availability_change_event);
 | 
					            system.HIDCore().GetFirstNpadId(), system, service_context, availability_change_event);
 | 
				
			||||||
        nfp_device->Initialize();
 | 
					        nfp_device->Initialize();
 | 
				
			||||||
        nfp_device->StartDetection(Service::NFP::TagProtocol::All);
 | 
					        nfp_device->StartDetection(Service::NFC::NfcProtocol::All);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const Core::Frontend::CabinetParameters parameters{
 | 
					    const Core::Frontend::CabinetParameters parameters{
 | 
				
			||||||
@@ -106,20 +106,22 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
 | 
				
			|||||||
        Cancel();
 | 
					        Cancel();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound &&
 | 
					    if (nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagFound &&
 | 
				
			||||||
        nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) {
 | 
					        nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagMounted) {
 | 
				
			||||||
        Cancel();
 | 
					        Cancel();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (nfp_device->GetCurrentState() == Service::NFP::DeviceState::TagFound) {
 | 
					    if (nfp_device->GetCurrentState() == Service::NFC::DeviceState::TagFound) {
 | 
				
			||||||
        nfp_device->Mount(Service::NFP::MountTarget::All);
 | 
					        nfp_device->Mount(Service::NFP::ModelType::Amiibo, Service::NFP::MountTarget::All);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (applet_input_common.applet_mode) {
 | 
					    switch (applet_input_common.applet_mode) {
 | 
				
			||||||
    case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: {
 | 
					    case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: {
 | 
				
			||||||
        Service::NFP::AmiiboName name{};
 | 
					        Service::NFP::RegisterInfoPrivate register_info{};
 | 
				
			||||||
        std::memcpy(name.data(), amiibo_name.data(), std::min(amiibo_name.size(), name.size() - 1));
 | 
					        std::memcpy(register_info.amiibo_name.data(), amiibo_name.data(),
 | 
				
			||||||
        nfp_device->SetRegisterInfoPrivate(name);
 | 
					                    std::min(amiibo_name.size(), register_info.amiibo_name.size() - 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nfp_device->SetRegisterInfoPrivate(register_info);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case Service::NFP::CabinetMode::StartGameDataEraser:
 | 
					    case Service::NFP::CabinetMode::StartGameDataEraser:
 | 
				
			||||||
@@ -139,7 +141,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
 | 
				
			|||||||
    applet_output.device_handle = applet_input_common.device_handle;
 | 
					    applet_output.device_handle = applet_input_common.device_handle;
 | 
				
			||||||
    applet_output.result = CabinetResult::Cancel;
 | 
					    applet_output.result = CabinetResult::Cancel;
 | 
				
			||||||
    const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info);
 | 
					    const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info);
 | 
				
			||||||
    const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info);
 | 
					    const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info, false);
 | 
				
			||||||
    nfp_device->Finalize();
 | 
					    nfp_device->Finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (reg_result.IsSuccess()) {
 | 
					    if (reg_result.IsSuccess()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,8 +19,8 @@ namespace Core {
 | 
				
			|||||||
class System;
 | 
					class System;
 | 
				
			||||||
} // namespace Core
 | 
					} // namespace Core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP {
 | 
					namespace Service::NFC {
 | 
				
			||||||
class NfpDevice;
 | 
					class NfcDevice;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::AM::Applets {
 | 
					namespace Service::AM::Applets {
 | 
				
			||||||
@@ -96,7 +96,7 @@ private:
 | 
				
			|||||||
    Core::System& system;
 | 
					    Core::System& system;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool is_complete{false};
 | 
					    bool is_complete{false};
 | 
				
			||||||
    std::shared_ptr<Service::NFP::NfpDevice> nfp_device;
 | 
					    std::shared_ptr<Service::NFC::NfcDevice> nfp_device;
 | 
				
			||||||
    Kernel::KEvent* availability_change_event;
 | 
					    Kernel::KEvent* availability_change_event;
 | 
				
			||||||
    KernelHelpers::ServiceContext service_context;
 | 
					    KernelHelpers::ServiceContext service_context;
 | 
				
			||||||
    StartParamForAmiiboSettings applet_input_common{};
 | 
					    StartParamForAmiiboSettings applet_input_common{};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@
 | 
				
			|||||||
#include "common/fs/fs.h"
 | 
					#include "common/fs/fs.h"
 | 
				
			||||||
#include "common/fs/path_util.h"
 | 
					#include "common/fs/path_util.h"
 | 
				
			||||||
#include "common/logging/log.h"
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
#include "core/hle/service/nfp/amiibo_crypto.h"
 | 
					#include "core/hle/service/nfc/common/amiibo_crypto.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP::AmiiboCrypto {
 | 
					namespace Service::NFP::AmiiboCrypto {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,7 +55,7 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
 | 
				
			|||||||
    if (amiibo_data.constant_value != 0xA5) {
 | 
					    if (amiibo_data.constant_value != 0xA5) {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (amiibo_data.model_info.tag_type != PackedTagType::Type2) {
 | 
					    if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if ((ntag_file.dynamic_lock & 0xFFFFFF) != 0x0F0001U) {
 | 
					    if ((ntag_file.dynamic_lock & 0xFFFFFF) != 0x0F0001U) {
 | 
				
			||||||
@@ -24,9 +24,9 @@ using DrgbOutput = std::array<u8, 0x20>;
 | 
				
			|||||||
struct HashSeed {
 | 
					struct HashSeed {
 | 
				
			||||||
    u16_be magic;
 | 
					    u16_be magic;
 | 
				
			||||||
    std::array<u8, 0xE> padding;
 | 
					    std::array<u8, 0xE> padding;
 | 
				
			||||||
    UniqueSerialNumber uid_1;
 | 
					    NFC::UniqueSerialNumber uid_1;
 | 
				
			||||||
    u8 nintendo_id_1;
 | 
					    u8 nintendo_id_1;
 | 
				
			||||||
    UniqueSerialNumber uid_2;
 | 
					    NFC::UniqueSerialNumber uid_2;
 | 
				
			||||||
    u8 nintendo_id_2;
 | 
					    u8 nintendo_id_2;
 | 
				
			||||||
    std::array<u8, 0x20> keygen_salt;
 | 
					    std::array<u8, 0x20> keygen_salt;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										138
									
								
								src/core/hle/service/nfc/common/device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								src/core/hle/service/nfc/common/device.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common/common_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/kernel_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/mifare_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfp/nfp_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/time/clock_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					class KEvent;
 | 
				
			||||||
 | 
					class KReadableEvent;
 | 
				
			||||||
 | 
					} // namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Core {
 | 
				
			||||||
 | 
					class System;
 | 
				
			||||||
 | 
					} // namespace Core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Core::HID {
 | 
				
			||||||
 | 
					class EmulatedController;
 | 
				
			||||||
 | 
					enum class ControllerTriggerType;
 | 
				
			||||||
 | 
					enum class NpadIdType : u32;
 | 
				
			||||||
 | 
					} // namespace Core::HID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					class NfcDevice {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
 | 
				
			||||||
 | 
					              KernelHelpers::ServiceContext& service_context_,
 | 
				
			||||||
 | 
					              Kernel::KEvent* availability_change_event_);
 | 
				
			||||||
 | 
					    ~NfcDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Initialize();
 | 
				
			||||||
 | 
					    void Finalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result StartDetection(NfcProtocol allowed_protocol);
 | 
				
			||||||
 | 
					    Result StopDetection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result GetTagInfo(TagInfo& tag_info, bool is_mifare) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result ReadMifare(std::span<const MifareReadBlockParameter> parameters,
 | 
				
			||||||
 | 
					                      std::span<MifareReadBlockData> read_block_data) const;
 | 
				
			||||||
 | 
					    Result ReadMifare(const MifareReadBlockParameter& parameter,
 | 
				
			||||||
 | 
					                      MifareReadBlockData& read_block_data) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters);
 | 
				
			||||||
 | 
					    Result WriteMifare(const MifareWriteBlockParameter& parameter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
 | 
				
			||||||
 | 
					                                    std::span<const u8> command_data, std::span<u8> out_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result Mount(NFP::ModelType model_type, NFP::MountTarget mount_target);
 | 
				
			||||||
 | 
					    Result Unmount();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result Flush();
 | 
				
			||||||
 | 
					    Result FlushDebug();
 | 
				
			||||||
 | 
					    Result FlushWithBreak(NFP::BreakType break_type);
 | 
				
			||||||
 | 
					    Result Restore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result GetCommonInfo(NFP::CommonInfo& common_info) const;
 | 
				
			||||||
 | 
					    Result GetModelInfo(NFP::ModelInfo& model_info) const;
 | 
				
			||||||
 | 
					    Result GetRegisterInfo(NFP::RegisterInfo& register_info) const;
 | 
				
			||||||
 | 
					    Result GetRegisterInfoPrivate(NFP::RegisterInfoPrivate& register_info) const;
 | 
				
			||||||
 | 
					    Result GetAdminInfo(NFP::AdminInfo& admin_info) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result DeleteRegisterInfo();
 | 
				
			||||||
 | 
					    Result SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& register_info);
 | 
				
			||||||
 | 
					    Result RestoreAmiibo();
 | 
				
			||||||
 | 
					    Result Format();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result OpenApplicationArea(u32 access_id);
 | 
				
			||||||
 | 
					    Result GetApplicationAreaId(u32& application_area_id) const;
 | 
				
			||||||
 | 
					    Result GetApplicationArea(std::span<u8> data) const;
 | 
				
			||||||
 | 
					    Result SetApplicationArea(std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result CreateApplicationArea(u32 access_id, std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result RecreateApplicationArea(u32 access_id, std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result DeleteApplicationArea();
 | 
				
			||||||
 | 
					    Result ExistsApplicationArea(bool& has_application_area) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result GetAll(NFP::NfpData& data) const;
 | 
				
			||||||
 | 
					    Result SetAll(const NFP::NfpData& data);
 | 
				
			||||||
 | 
					    Result BreakTag(NFP::BreakType break_type);
 | 
				
			||||||
 | 
					    Result ReadBackupData(std::span<u8> data) const;
 | 
				
			||||||
 | 
					    Result WriteBackupData(std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result WriteNtf(std::span<const u8> data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u64 GetHandle() const;
 | 
				
			||||||
 | 
					    DeviceState GetCurrentState() const;
 | 
				
			||||||
 | 
					    Result GetNpadId(Core::HID::NpadIdType& out_npad_id) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Kernel::KReadableEvent& GetActivateEvent() const;
 | 
				
			||||||
 | 
					    Kernel::KReadableEvent& GetDeactivateEvent() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    void NpadUpdate(Core::HID::ControllerTriggerType type);
 | 
				
			||||||
 | 
					    bool LoadNfcTag(std::span<const u8> data);
 | 
				
			||||||
 | 
					    void CloseNfcTag();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const;
 | 
				
			||||||
 | 
					    void SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name);
 | 
				
			||||||
 | 
					    NFP::AmiiboDate GetAmiiboDate(s64 posix_time) const;
 | 
				
			||||||
 | 
					    u64 RemoveVersionByte(u64 application_id) const;
 | 
				
			||||||
 | 
					    void UpdateSettingsCrc();
 | 
				
			||||||
 | 
					    void UpdateRegisterInfoCrc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_controller_set{};
 | 
				
			||||||
 | 
					    int callback_key;
 | 
				
			||||||
 | 
					    const Core::HID::NpadIdType npad_id;
 | 
				
			||||||
 | 
					    Core::System& system;
 | 
				
			||||||
 | 
					    Core::HID::EmulatedController* npad_device = nullptr;
 | 
				
			||||||
 | 
					    KernelHelpers::ServiceContext& service_context;
 | 
				
			||||||
 | 
					    Kernel::KEvent* activate_event = nullptr;
 | 
				
			||||||
 | 
					    Kernel::KEvent* deactivate_event = nullptr;
 | 
				
			||||||
 | 
					    Kernel::KEvent* availability_change_event = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_initalized{};
 | 
				
			||||||
 | 
					    NfcProtocol allowed_protocols{};
 | 
				
			||||||
 | 
					    DeviceState device_state{DeviceState::Unavailable};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // NFP data
 | 
				
			||||||
 | 
					    bool is_data_moddified{};
 | 
				
			||||||
 | 
					    bool is_app_area_open{};
 | 
				
			||||||
 | 
					    bool is_plain_amiibo{};
 | 
				
			||||||
 | 
					    s64 current_posix_time{};
 | 
				
			||||||
 | 
					    NFP::MountTarget mount_target{NFP::MountTarget::None};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NFP::NTAG215File tag_data{};
 | 
				
			||||||
 | 
					    std::vector<u8> mifare_data{};
 | 
				
			||||||
 | 
					    NFP::EncryptedNTAG215File encrypted_tag_data{};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::NFC
 | 
				
			||||||
							
								
								
									
										695
									
								
								src/core/hle/service/nfc/common/device_manager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										695
									
								
								src/core/hle/service/nfc/common/device_manager.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,695 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
 | 
					#include "core/core.h"
 | 
				
			||||||
 | 
					#include "core/hid/hid_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/kernel/k_event.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/ipc_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/common/device.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/common/device_manager.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_result.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/time/clock_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContext& service_context_)
 | 
				
			||||||
 | 
					    : system{system_}, service_context{service_context_} {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    availability_change_event =
 | 
				
			||||||
 | 
					        service_context.CreateEvent("Nfc:DeviceManager:AvailabilityChangeEvent");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (u32 device_index = 0; device_index < devices.size(); device_index++) {
 | 
				
			||||||
 | 
					        devices[device_index] =
 | 
				
			||||||
 | 
					            std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
 | 
				
			||||||
 | 
					                                        service_context, availability_change_event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    is_initialized = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DeviceManager ::~DeviceManager() {
 | 
				
			||||||
 | 
					    service_context.CloseEvent(availability_change_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::Initialize() {
 | 
				
			||||||
 | 
					    for (auto& device : devices) {
 | 
				
			||||||
 | 
					        device->Initialize();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    is_initialized = true;
 | 
				
			||||||
 | 
					    return ResultSuccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::Finalize() {
 | 
				
			||||||
 | 
					    for (auto& device : devices) {
 | 
				
			||||||
 | 
					        device->Finalize();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    is_initialized = false;
 | 
				
			||||||
 | 
					    return ResultSuccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices,
 | 
				
			||||||
 | 
					                                  std::size_t max_allowed_devices) const {
 | 
				
			||||||
 | 
					    for (auto& device : devices) {
 | 
				
			||||||
 | 
					        if (nfp_devices.size() >= max_allowed_devices) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (device->GetCurrentState() != DeviceState::Unavailable) {
 | 
				
			||||||
 | 
					            nfp_devices.push_back(device->GetHandle());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (nfp_devices.empty()) {
 | 
				
			||||||
 | 
					        return ResultDeviceNotFound;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ResultSuccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DeviceState DeviceManager::GetDeviceState(u64 device_handle) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    const auto result = GetDeviceFromHandle(device_handle, device, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        return device->GetCurrentState();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return DeviceState::Unavailable;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetNpadId(npad_id);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Kernel::KReadableEvent& DeviceManager::AttachAvailabilityChangeEvent() const {
 | 
				
			||||||
 | 
					    return availability_change_event->GetReadableEvent();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::StartDetection(u64 device_handle, NfcProtocol tag_protocol) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->StartDetection(tag_protocol);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::StopDetection(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->StopDetection();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info, bool is_mifare) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetTagInfo(tag_info, is_mifare);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Kernel::KReadableEvent& DeviceManager::AttachActivateEvent(u64 device_handle) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    GetDeviceFromHandle(device_handle, device, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Return proper error code on failure
 | 
				
			||||||
 | 
					    return device->GetActivateEvent();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Kernel::KReadableEvent& DeviceManager::AttachDeactivateEvent(u64 device_handle) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    GetDeviceFromHandle(device_handle, device, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Return proper error code on failure
 | 
				
			||||||
 | 
					    return device->GetDeactivateEvent();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::ReadMifare(u64 device_handle,
 | 
				
			||||||
 | 
					                                 std::span<const MifareReadBlockParameter> read_parameters,
 | 
				
			||||||
 | 
					                                 std::span<MifareReadBlockData> read_data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->ReadMifare(read_parameters, read_data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::WriteMifare(u64 device_handle,
 | 
				
			||||||
 | 
					                                  std::span<const MifareWriteBlockParameter> write_parameters) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->WriteMifare(write_parameters);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::SendCommandByPassThrough(u64 device_handle,
 | 
				
			||||||
 | 
					                                               const Time::Clock::TimeSpanType& timeout,
 | 
				
			||||||
 | 
					                                               std::span<const u8> command_data,
 | 
				
			||||||
 | 
					                                               std::span<u8> out_data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->SendCommandByPassThrough(timeout, command_data, out_data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::Mount(u64 device_handle, NFP::ModelType model_type,
 | 
				
			||||||
 | 
					                            NFP::MountTarget mount_target) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->Mount(model_type, mount_target);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::Unmount(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->Unmount();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::OpenApplicationArea(u64 device_handle, u32 access_id) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->OpenApplicationArea(access_id);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetApplicationArea(data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::SetApplicationArea(u64 device_handle, std::span<const u8> data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->SetApplicationArea(data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::Flush(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->Flush();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::Restore(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->Restore();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::CreateApplicationArea(u64 device_handle, u32 access_id,
 | 
				
			||||||
 | 
					                                            std::span<const u8> data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->CreateApplicationArea(access_id, data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetRegisterInfo(register_info);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetCommonInfo(common_info);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetModelInfo(model_info);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					u32 DeviceManager::GetApplicationAreaSize() const {
 | 
				
			||||||
 | 
					    return sizeof(NFP::ApplicationArea);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::RecreateApplicationArea(u64 device_handle, u32 access_id,
 | 
				
			||||||
 | 
					                                              std::span<const u8> data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->RecreateApplicationArea(access_id, data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::Format(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->Format();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetAdminInfo(admin_info);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle,
 | 
				
			||||||
 | 
					                                             NFP::RegisterInfoPrivate& register_info) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetRegisterInfoPrivate(register_info);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::SetRegisterInfoPrivate(u64 device_handle,
 | 
				
			||||||
 | 
					                                             const NFP::RegisterInfoPrivate& register_info) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->SetRegisterInfoPrivate(register_info);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::DeleteRegisterInfo(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->DeleteRegisterInfo();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::DeleteApplicationArea(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->DeleteApplicationArea();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->ExistsApplicationArea(has_application_area);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->GetAll(nfp_data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::SetAll(u64 device_handle, const NFP::NfpData& nfp_data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->SetAll(nfp_data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::FlushDebug(u64 device_handle) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->FlushDebug();
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::BreakTag(u64 device_handle, NFP::BreakType break_type) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->BreakTag(break_type);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) const {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->ReadBackupData(data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->WriteBackupData(data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data) {
 | 
				
			||||||
 | 
					    std::scoped_lock lock{mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<NfcDevice> device = nullptr;
 | 
				
			||||||
 | 
					    auto result = GetDeviceHandle(device_handle, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        result = device->WriteNtf(data);
 | 
				
			||||||
 | 
					        result = VerifyDeviceResult(device, result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device,
 | 
				
			||||||
 | 
					                                          bool check_state) const {
 | 
				
			||||||
 | 
					    if (check_state) {
 | 
				
			||||||
 | 
					        const Result is_parameter_set = IsNfcParameterSet();
 | 
				
			||||||
 | 
					        if (is_parameter_set.IsError()) {
 | 
				
			||||||
 | 
					            return is_parameter_set;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const Result is_enabled = IsNfcEnabled();
 | 
				
			||||||
 | 
					        if (is_enabled.IsError()) {
 | 
				
			||||||
 | 
					            return is_enabled;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const Result is_nfc_initialized = IsNfcInitialized();
 | 
				
			||||||
 | 
					        if (is_nfc_initialized.IsError()) {
 | 
				
			||||||
 | 
					            return is_nfc_initialized;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (auto& device : devices) {
 | 
				
			||||||
 | 
					        if (device->GetHandle() == handle) {
 | 
				
			||||||
 | 
					            nfc_device = device;
 | 
				
			||||||
 | 
					            return ResultSuccess;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ResultDeviceNotFound;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::optional<std::shared_ptr<NfcDevice>> DeviceManager::GetNfcDevice(u64 handle) {
 | 
				
			||||||
 | 
					    for (auto& device : devices) {
 | 
				
			||||||
 | 
					        if (device->GetHandle() == handle) {
 | 
				
			||||||
 | 
					            return device;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return std::nullopt;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std::optional<std::shared_ptr<NfcDevice>> DeviceManager::GetNfcDevice(u64 handle) const {
 | 
				
			||||||
 | 
					    for (auto& device : devices) {
 | 
				
			||||||
 | 
					        if (device->GetHandle() == handle) {
 | 
				
			||||||
 | 
					            return device;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return std::nullopt;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const {
 | 
				
			||||||
 | 
					    const auto result = GetDeviceFromHandle(handle, device, true);
 | 
				
			||||||
 | 
					    if (result.IsError()) {
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return CheckDeviceState(device);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
 | 
				
			||||||
 | 
					                                         Result operation_result) const {
 | 
				
			||||||
 | 
					    if (operation_result.IsSuccess()) {
 | 
				
			||||||
 | 
					        return operation_result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Result is_parameter_set = IsNfcParameterSet();
 | 
				
			||||||
 | 
					    if (is_parameter_set.IsError()) {
 | 
				
			||||||
 | 
					        return is_parameter_set;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const Result is_enabled = IsNfcEnabled();
 | 
				
			||||||
 | 
					    if (is_enabled.IsError()) {
 | 
				
			||||||
 | 
					        return is_enabled;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const Result is_nfc_initialized = IsNfcInitialized();
 | 
				
			||||||
 | 
					    if (is_nfc_initialized.IsError()) {
 | 
				
			||||||
 | 
					        return is_nfc_initialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const Result device_state = CheckDeviceState(device);
 | 
				
			||||||
 | 
					    if (device_state.IsError()) {
 | 
				
			||||||
 | 
					        return device_state;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return operation_result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::CheckDeviceState(std::shared_ptr<NfcDevice> device) const {
 | 
				
			||||||
 | 
					    if (device == nullptr) {
 | 
				
			||||||
 | 
					        return ResultInvalidArgument;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ResultSuccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::IsNfcEnabled() const {
 | 
				
			||||||
 | 
					    // TODO: This calls nn::settings::detail::GetNfcEnableFlag
 | 
				
			||||||
 | 
					    const bool is_enabled = true;
 | 
				
			||||||
 | 
					    if (!is_enabled) {
 | 
				
			||||||
 | 
					        return ResultNfcDisabled;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ResultSuccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::IsNfcParameterSet() const {
 | 
				
			||||||
 | 
					    // TODO: This calls checks against a bool on offset 0x450
 | 
				
			||||||
 | 
					    const bool is_set = true;
 | 
				
			||||||
 | 
					    if (!is_set) {
 | 
				
			||||||
 | 
					        return ResultUnknown76;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ResultSuccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result DeviceManager::IsNfcInitialized() const {
 | 
				
			||||||
 | 
					    if (!is_initialized) {
 | 
				
			||||||
 | 
					        return ResultNfcNotInitialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ResultSuccess;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::NFC
 | 
				
			||||||
							
								
								
									
										100
									
								
								src/core/hle/service/nfc/common/device_manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/core/hle/service/nfc/common/device_manager.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <optional>
 | 
				
			||||||
 | 
					#include <span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "core/hid/hid_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/kernel_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/mifare_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfp/nfp_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/time/clock_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					class NfcDevice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DeviceManager {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit DeviceManager(Core::System& system_, KernelHelpers::ServiceContext& service_context_);
 | 
				
			||||||
 | 
					    ~DeviceManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Nfc device manager
 | 
				
			||||||
 | 
					    Result Initialize();
 | 
				
			||||||
 | 
					    Result Finalize();
 | 
				
			||||||
 | 
					    Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices) const;
 | 
				
			||||||
 | 
					    DeviceState GetDeviceState(u64 device_handle) const;
 | 
				
			||||||
 | 
					    Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const;
 | 
				
			||||||
 | 
					    Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;
 | 
				
			||||||
 | 
					    Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);
 | 
				
			||||||
 | 
					    Result StopDetection(u64 device_handle);
 | 
				
			||||||
 | 
					    Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info, bool is_mifare) const;
 | 
				
			||||||
 | 
					    Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const;
 | 
				
			||||||
 | 
					    Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const;
 | 
				
			||||||
 | 
					    Result ReadMifare(u64 device_handle,
 | 
				
			||||||
 | 
					                      const std::span<const MifareReadBlockParameter> read_parameters,
 | 
				
			||||||
 | 
					                      std::span<MifareReadBlockData> read_data);
 | 
				
			||||||
 | 
					    Result WriteMifare(u64 device_handle,
 | 
				
			||||||
 | 
					                       std::span<const MifareWriteBlockParameter> write_parameters);
 | 
				
			||||||
 | 
					    Result SendCommandByPassThrough(u64 device_handle, const Time::Clock::TimeSpanType& timeout,
 | 
				
			||||||
 | 
					                                    std::span<const u8> command_data, std::span<u8> out_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Nfp device manager
 | 
				
			||||||
 | 
					    Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target);
 | 
				
			||||||
 | 
					    Result Unmount(u64 device_handle);
 | 
				
			||||||
 | 
					    Result OpenApplicationArea(u64 device_handle, u32 access_id);
 | 
				
			||||||
 | 
					    Result GetApplicationArea(u64 device_handle, std::span<u8> data) const;
 | 
				
			||||||
 | 
					    Result SetApplicationArea(u64 device_handle, std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result Flush(u64 device_handle);
 | 
				
			||||||
 | 
					    Result Restore(u64 device_handle);
 | 
				
			||||||
 | 
					    Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const;
 | 
				
			||||||
 | 
					    Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const;
 | 
				
			||||||
 | 
					    Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const;
 | 
				
			||||||
 | 
					    u32 GetApplicationAreaSize() const;
 | 
				
			||||||
 | 
					    Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result Format(u64 device_handle);
 | 
				
			||||||
 | 
					    Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const;
 | 
				
			||||||
 | 
					    Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info) const;
 | 
				
			||||||
 | 
					    Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info);
 | 
				
			||||||
 | 
					    Result DeleteRegisterInfo(u64 device_handle);
 | 
				
			||||||
 | 
					    Result DeleteApplicationArea(u64 device_handle);
 | 
				
			||||||
 | 
					    Result ExistsApplicationArea(u64 device_handle, bool& has_application_area) const;
 | 
				
			||||||
 | 
					    Result GetAll(u64 device_handle, NFP::NfpData& nfp_data) const;
 | 
				
			||||||
 | 
					    Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data);
 | 
				
			||||||
 | 
					    Result FlushDebug(u64 device_handle);
 | 
				
			||||||
 | 
					    Result BreakTag(u64 device_handle, NFP::BreakType break_type);
 | 
				
			||||||
 | 
					    Result ReadBackupData(u64 device_handle, std::span<u8> data) const;
 | 
				
			||||||
 | 
					    Result WriteBackupData(u64 device_handle, std::span<const u8> data);
 | 
				
			||||||
 | 
					    Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    Result IsNfcEnabled() const;
 | 
				
			||||||
 | 
					    Result IsNfcParameterSet() const;
 | 
				
			||||||
 | 
					    Result IsNfcInitialized() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device,
 | 
				
			||||||
 | 
					                               bool check_state) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const;
 | 
				
			||||||
 | 
					    Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result) const;
 | 
				
			||||||
 | 
					    Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
 | 
				
			||||||
 | 
					    const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_initialized = false;
 | 
				
			||||||
 | 
					    mutable std::mutex mutex;
 | 
				
			||||||
 | 
					    std::array<std::shared_ptr<NfcDevice>, 10> devices{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Core::System& system;
 | 
				
			||||||
 | 
					    KernelHelpers::ServiceContext service_context;
 | 
				
			||||||
 | 
					    Kernel::KEvent* availability_change_event;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::NFC
 | 
				
			||||||
							
								
								
									
										17
									
								
								src/core/hle/service/nfc/mifare_result.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/core/hle/service/nfc/mifare_result.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "core/hle/result.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::NFC::Mifare {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr Result ResultDeviceNotFound(ErrorModule::NFCMifare, 64);
 | 
				
			||||||
 | 
					constexpr Result ResultInvalidArgument(ErrorModule::NFCMifare, 65);
 | 
				
			||||||
 | 
					constexpr Result ResultWrongDeviceState(ErrorModule::NFCMifare, 73);
 | 
				
			||||||
 | 
					constexpr Result ResultNfcDisabled(ErrorModule::NFCMifare, 80);
 | 
				
			||||||
 | 
					constexpr Result ResultTagRemoved(ErrorModule::NFCMifare, 97);
 | 
				
			||||||
 | 
					constexpr Result ResultReadError(ErrorModule::NFCMifare, 288);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::NFC::Mifare
 | 
				
			||||||
							
								
								
									
										63
									
								
								src/core/hle/service/nfc/mifare_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/core/hle/service/nfc/mifare_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common/common_funcs.h"
 | 
				
			||||||
 | 
					#include "common/common_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class MifareCmd : u8 {
 | 
				
			||||||
 | 
					    AuthA = 0x60,
 | 
				
			||||||
 | 
					    AuthB = 0x61,
 | 
				
			||||||
 | 
					    Read = 0x30,
 | 
				
			||||||
 | 
					    Write = 0xA0,
 | 
				
			||||||
 | 
					    Transfer = 0xB0,
 | 
				
			||||||
 | 
					    Decrement = 0xC0,
 | 
				
			||||||
 | 
					    Increment = 0xC1,
 | 
				
			||||||
 | 
					    Store = 0xC2
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using DataBlock = std::array<u8, 0x10>;
 | 
				
			||||||
 | 
					using KeyData = std::array<u8, 0x6>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SectorKey {
 | 
				
			||||||
 | 
					    MifareCmd command;
 | 
				
			||||||
 | 
					    u8 unknown; // Usually 1
 | 
				
			||||||
 | 
					    INSERT_PADDING_BYTES(0x6);
 | 
				
			||||||
 | 
					    KeyData sector_key;
 | 
				
			||||||
 | 
					    INSERT_PADDING_BYTES(0x2);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::MifareReadBlockParameter
 | 
				
			||||||
 | 
					struct MifareReadBlockParameter {
 | 
				
			||||||
 | 
					    u8 sector_number;
 | 
				
			||||||
 | 
					    INSERT_PADDING_BYTES(0x7);
 | 
				
			||||||
 | 
					    SectorKey sector_key;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static_assert(sizeof(MifareReadBlockParameter) == 0x18,
 | 
				
			||||||
 | 
					              "MifareReadBlockParameter is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::MifareReadBlockData
 | 
				
			||||||
 | 
					struct MifareReadBlockData {
 | 
				
			||||||
 | 
					    DataBlock data;
 | 
				
			||||||
 | 
					    u8 sector_number;
 | 
				
			||||||
 | 
					    INSERT_PADDING_BYTES(0x7);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::MifareWriteBlockParameter
 | 
				
			||||||
 | 
					struct MifareWriteBlockParameter {
 | 
				
			||||||
 | 
					    DataBlock data;
 | 
				
			||||||
 | 
					    u8 sector_number;
 | 
				
			||||||
 | 
					    INSERT_PADDING_BYTES(0x7);
 | 
				
			||||||
 | 
					    SectorKey sector_key;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static_assert(sizeof(MifareWriteBlockParameter) == 0x28,
 | 
				
			||||||
 | 
					              "MifareWriteBlockParameter is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::NFC
 | 
				
			||||||
@@ -1,400 +0,0 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
					 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "common/logging/log.h"
 | 
					 | 
				
			||||||
#include "core/core.h"
 | 
					 | 
				
			||||||
#include "core/hid/hid_types.h"
 | 
					 | 
				
			||||||
#include "core/hle/kernel/k_event.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/ipc_helpers.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/mifare_user.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_device.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_result.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Service::NFC {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MFIUser::MFIUser(Core::System& system_)
 | 
					 | 
				
			||||||
    : ServiceFramework{system_, "NFC::MFIUser"}, service_context{system_, service_name} {
 | 
					 | 
				
			||||||
    static const FunctionInfo functions[] = {
 | 
					 | 
				
			||||||
        {0, &MFIUser::Initialize, "Initialize"},
 | 
					 | 
				
			||||||
        {1, &MFIUser::Finalize, "Finalize"},
 | 
					 | 
				
			||||||
        {2, &MFIUser::ListDevices, "ListDevices"},
 | 
					 | 
				
			||||||
        {3, &MFIUser::StartDetection, "StartDetection"},
 | 
					 | 
				
			||||||
        {4, &MFIUser::StopDetection, "StopDetection"},
 | 
					 | 
				
			||||||
        {5, &MFIUser::Read, "Read"},
 | 
					 | 
				
			||||||
        {6, &MFIUser::Write, "Write"},
 | 
					 | 
				
			||||||
        {7, &MFIUser::GetTagInfo, "GetTagInfo"},
 | 
					 | 
				
			||||||
        {8, &MFIUser::GetActivateEventHandle, "GetActivateEventHandle"},
 | 
					 | 
				
			||||||
        {9, &MFIUser::GetDeactivateEventHandle, "GetDeactivateEventHandle"},
 | 
					 | 
				
			||||||
        {10, &MFIUser::GetState, "GetState"},
 | 
					 | 
				
			||||||
        {11, &MFIUser::GetDeviceState, "GetDeviceState"},
 | 
					 | 
				
			||||||
        {12, &MFIUser::GetNpadId, "GetNpadId"},
 | 
					 | 
				
			||||||
        {13, &MFIUser::GetAvailabilityChangeEventHandle, "GetAvailabilityChangeEventHandle"},
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    RegisterHandlers(functions);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    availability_change_event = service_context.CreateEvent("MFIUser:AvailabilityChangeEvent");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (u32 device_index = 0; device_index < 10; device_index++) {
 | 
					 | 
				
			||||||
        devices[device_index] =
 | 
					 | 
				
			||||||
            std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
 | 
					 | 
				
			||||||
                                        service_context, availability_change_event);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MFIUser ::~MFIUser() {
 | 
					 | 
				
			||||||
    availability_change_event->Close();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::Initialize(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    state = State::Initialized;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (auto& device : devices) {
 | 
					 | 
				
			||||||
        device->Initialize();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 0};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::Finalize(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    state = State::NonInitialized;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (auto& device : devices) {
 | 
					 | 
				
			||||||
        device->Finalize();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::ListDevices(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!ctx.CanWriteBuffer()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareInvalidArgument);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (ctx.GetWriteBufferSize() == 0) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareInvalidArgument);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::vector<u64> nfp_devices;
 | 
					 | 
				
			||||||
    const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const auto& device : devices) {
 | 
					 | 
				
			||||||
        if (nfp_devices.size() >= max_allowed_devices) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (device->GetCurrentState() != NFP::DeviceState::Unavailable) {
 | 
					 | 
				
			||||||
            nfp_devices.push_back(device->GetHandle());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (nfp_devices.empty()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ctx.WriteBuffer(nfp_devices);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.Push(static_cast<s32>(nfp_devices.size()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::StartDetection(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto result = device.value()->StartDetection(NFP::TagProtocol::All);
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::StopDetection(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto result = device.value()->StopDetection();
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::Read(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    const auto buffer{ctx.ReadBuffer()};
 | 
					 | 
				
			||||||
    const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareReadBlockParameter>()};
 | 
					 | 
				
			||||||
    std::vector<NFP::MifareReadBlockParameter> read_commands(number_of_commands);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memcpy(read_commands.data(), buffer.data(),
 | 
					 | 
				
			||||||
           number_of_commands * sizeof(NFP::MifareReadBlockParameter));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
 | 
					 | 
				
			||||||
             device_handle, number_of_commands);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result result = ResultSuccess;
 | 
					 | 
				
			||||||
    std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
 | 
					 | 
				
			||||||
    for (std::size_t i = 0; i < number_of_commands; i++) {
 | 
					 | 
				
			||||||
        result = device.value()->MifareRead(read_commands[i], out_data[i]);
 | 
					 | 
				
			||||||
        if (result.IsError()) {
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ctx.WriteBuffer(out_data);
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::Write(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    const auto buffer{ctx.ReadBuffer()};
 | 
					 | 
				
			||||||
    const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareWriteBlockParameter>()};
 | 
					 | 
				
			||||||
    std::vector<NFP::MifareWriteBlockParameter> write_commands(number_of_commands);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memcpy(write_commands.data(), buffer.data(),
 | 
					 | 
				
			||||||
           number_of_commands * sizeof(NFP::MifareWriteBlockParameter));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
 | 
					 | 
				
			||||||
             device_handle, number_of_commands);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result result = ResultSuccess;
 | 
					 | 
				
			||||||
    std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
 | 
					 | 
				
			||||||
    for (std::size_t i = 0; i < number_of_commands; i++) {
 | 
					 | 
				
			||||||
        result = device.value()->MifareWrite(write_commands[i]);
 | 
					 | 
				
			||||||
        if (result.IsError()) {
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (result.IsSuccess()) {
 | 
					 | 
				
			||||||
        result = device.value()->Flush();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::GetTagInfo(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    NFP::TagInfo tag_info{};
 | 
					 | 
				
			||||||
    const auto result = device.value()->GetTagInfo(tag_info, true);
 | 
					 | 
				
			||||||
    ctx.WriteBuffer(tag_info);
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::GetActivateEventHandle(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushCopyObjects(device.value()->GetActivateEvent());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::GetDeactivateEventHandle(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushCopyObjects(device.value()->GetDeactivateEvent());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::GetState(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushEnum(state);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::GetDeviceState(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushEnum(device.value()->GetCurrentState());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::GetNpadId(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareDeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushEnum(device.value()->GetNpadId());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void MFIUser::GetAvailabilityChangeEventHandle(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(MifareNfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushCopyObjects(availability_change_event->GetReadableEvent());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::optional<std::shared_ptr<NfcDevice>> MFIUser::GetNfcDevice(u64 handle) {
 | 
					 | 
				
			||||||
    for (auto& device : devices) {
 | 
					 | 
				
			||||||
        if (device->GetHandle() == handle) {
 | 
					 | 
				
			||||||
            return device;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return std::nullopt;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::NFC
 | 
					 | 
				
			||||||
@@ -1,52 +0,0 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
					 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <array>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					 | 
				
			||||||
#include <optional>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "core/hle/service/kernel_helpers.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/service.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Service::NFC {
 | 
					 | 
				
			||||||
class NfcDevice;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MFIUser final : public ServiceFramework<MFIUser> {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    explicit MFIUser(Core::System& system_);
 | 
					 | 
				
			||||||
    ~MFIUser();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    enum class State : u32 {
 | 
					 | 
				
			||||||
        NonInitialized,
 | 
					 | 
				
			||||||
        Initialized,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void Initialize(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void Finalize(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void ListDevices(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void StartDetection(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void StopDetection(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void Read(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void Write(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetTagInfo(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetActivateEventHandle(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetDeactivateEventHandle(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetState(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetDeviceState(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetNpadId(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetAvailabilityChangeEventHandle(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    KernelHelpers::ServiceContext service_context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::array<std::shared_ptr<NfcDevice>, 10> devices{};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    State state{State::NonInitialized};
 | 
					 | 
				
			||||||
    Kernel::KEvent* availability_change_event;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::NFC
 | 
					 | 
				
			||||||
@@ -6,14 +6,115 @@
 | 
				
			|||||||
#include "common/logging/log.h"
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
#include "common/settings.h"
 | 
					#include "common/settings.h"
 | 
				
			||||||
#include "core/hle/service/ipc_helpers.h"
 | 
					#include "core/hle/service/ipc_helpers.h"
 | 
				
			||||||
#include "core/hle/service/nfc/mifare_user.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc.h"
 | 
					#include "core/hle/service/nfc/nfc.h"
 | 
				
			||||||
#include "core/hle/service/nfc/nfc_user.h"
 | 
					#include "core/hle/service/nfc/nfc_interface.h"
 | 
				
			||||||
#include "core/hle/service/server_manager.h"
 | 
					#include "core/hle/service/server_manager.h"
 | 
				
			||||||
#include "core/hle/service/service.h"
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFC {
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class IUser final : public NfcInterface {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit IUser(Core::System& system_) : NfcInterface(system_, "NFC::IUser", BackendType::Nfc) {
 | 
				
			||||||
 | 
					        // clang-format off
 | 
				
			||||||
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
 | 
					            {0, &NfcInterface::Initialize, "InitializeOld"},
 | 
				
			||||||
 | 
					            {1, &NfcInterface::Finalize, "FinalizeOld"},
 | 
				
			||||||
 | 
					            {2, &NfcInterface::GetState, "GetStateOld"},
 | 
				
			||||||
 | 
					            {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"},
 | 
				
			||||||
 | 
					            {400, &NfcInterface::Initialize, "Initialize"},
 | 
				
			||||||
 | 
					            {401, &NfcInterface::Finalize, "Finalize"},
 | 
				
			||||||
 | 
					            {402, &NfcInterface::GetState, "GetState"},
 | 
				
			||||||
 | 
					            {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"},
 | 
				
			||||||
 | 
					            {404, &NfcInterface::ListDevices, "ListDevices"},
 | 
				
			||||||
 | 
					            {405, &NfcInterface::GetDeviceState, "GetDeviceState"},
 | 
				
			||||||
 | 
					            {406, &NfcInterface::GetNpadId, "GetNpadId"},
 | 
				
			||||||
 | 
					            {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"},
 | 
				
			||||||
 | 
					            {408, &NfcInterface::StartDetection, "StartDetection"},
 | 
				
			||||||
 | 
					            {409, &NfcInterface::StopDetection, "StopDetection"},
 | 
				
			||||||
 | 
					            {410, &NfcInterface::GetTagInfo, "GetTagInfo"},
 | 
				
			||||||
 | 
					            {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"},
 | 
				
			||||||
 | 
					            {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"},
 | 
				
			||||||
 | 
					            {1000, &NfcInterface::ReadMifare, "ReadMifare"},
 | 
				
			||||||
 | 
					            {1001, &NfcInterface::WriteMifare ,"WriteMifare"},
 | 
				
			||||||
 | 
					            {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"},
 | 
				
			||||||
 | 
					            {1301, nullptr, "KeepPassThroughSession"},
 | 
				
			||||||
 | 
					            {1302, nullptr, "ReleasePassThroughSession"},
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RegisterHandlers(functions);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ISystem final : public NfcInterface {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit ISystem(Core::System& system_)
 | 
				
			||||||
 | 
					        : NfcInterface{system_, "NFC::ISystem", BackendType::Nfc} {
 | 
				
			||||||
 | 
					        // clang-format off
 | 
				
			||||||
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
 | 
					            {0, &NfcInterface::Initialize, "InitializeOld"},
 | 
				
			||||||
 | 
					            {1, &NfcInterface::Finalize, "FinalizeOld"},
 | 
				
			||||||
 | 
					            {2, &NfcInterface::GetState, "GetStateOld"},
 | 
				
			||||||
 | 
					            {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"},
 | 
				
			||||||
 | 
					            {100, nullptr, "SetNfcEnabledOld"},
 | 
				
			||||||
 | 
					            {400, &NfcInterface::Initialize, "Initialize"},
 | 
				
			||||||
 | 
					            {401, &NfcInterface::Finalize, "Finalize"},
 | 
				
			||||||
 | 
					            {402, &NfcInterface::GetState, "GetState"},
 | 
				
			||||||
 | 
					            {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"},
 | 
				
			||||||
 | 
					            {404, &NfcInterface::ListDevices, "ListDevices"},
 | 
				
			||||||
 | 
					            {405, &NfcInterface::GetDeviceState, "GetDeviceState"},
 | 
				
			||||||
 | 
					            {406, &NfcInterface::GetNpadId, "GetNpadId"},
 | 
				
			||||||
 | 
					            {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"},
 | 
				
			||||||
 | 
					            {408, &NfcInterface::StartDetection, "StartDetection"},
 | 
				
			||||||
 | 
					            {409, &NfcInterface::StopDetection, "StopDetection"},
 | 
				
			||||||
 | 
					            {410, &NfcInterface::GetTagInfo, "GetTagInfo"},
 | 
				
			||||||
 | 
					            {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"},
 | 
				
			||||||
 | 
					            {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"},
 | 
				
			||||||
 | 
					            {500, nullptr, "SetNfcEnabled"},
 | 
				
			||||||
 | 
					            {510, nullptr, "OutputTestWave"},
 | 
				
			||||||
 | 
					            {1000, &NfcInterface::ReadMifare, "ReadMifare"},
 | 
				
			||||||
 | 
					            {1001, &NfcInterface::WriteMifare, "WriteMifare"},
 | 
				
			||||||
 | 
					            {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"},
 | 
				
			||||||
 | 
					            {1301, nullptr, "KeepPassThroughSession"},
 | 
				
			||||||
 | 
					            {1302, nullptr, "ReleasePassThroughSession"},
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RegisterHandlers(functions);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MFInterface has an unique interface but it's identical to NfcInterface so we can keep the code
 | 
				
			||||||
 | 
					// simpler
 | 
				
			||||||
 | 
					using MFInterface = NfcInterface;
 | 
				
			||||||
 | 
					class MFIUser final : public MFInterface {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit MFIUser(Core::System& system_)
 | 
				
			||||||
 | 
					        : MFInterface{system_, "NFC::MFInterface", BackendType::Mifare} {
 | 
				
			||||||
 | 
					        // clang-format off
 | 
				
			||||||
 | 
					        static const FunctionInfoTyped<MFIUser> functions[] = {
 | 
				
			||||||
 | 
					            {0, &MFIUser::Initialize, "Initialize"},
 | 
				
			||||||
 | 
					            {1, &MFIUser::Finalize, "Finalize"},
 | 
				
			||||||
 | 
					            {2, &MFIUser::ListDevices, "ListDevices"},
 | 
				
			||||||
 | 
					            {3, &MFIUser::StartDetection, "StartDetection"},
 | 
				
			||||||
 | 
					            {4, &MFIUser::StopDetection, "StopDetection"},
 | 
				
			||||||
 | 
					            {5, &MFIUser::ReadMifare, "Read"},
 | 
				
			||||||
 | 
					            {6, &MFIUser::WriteMifare, "Write"},
 | 
				
			||||||
 | 
					            {7, &MFIUser::GetTagInfo, "GetTagInfo"},
 | 
				
			||||||
 | 
					            {8, &MFIUser::AttachActivateEvent, "GetActivateEventHandle"},
 | 
				
			||||||
 | 
					            {9, &MFIUser::AttachDeactivateEvent, "GetDeactivateEventHandle"},
 | 
				
			||||||
 | 
					            {10, &MFIUser::GetState, "GetState"},
 | 
				
			||||||
 | 
					            {11, &MFIUser::GetDeviceState, "GetDeviceState"},
 | 
				
			||||||
 | 
					            {12, &MFIUser::GetNpadId, "GetNpadId"},
 | 
				
			||||||
 | 
					            {13, &MFIUser::AttachAvailabilityChangeEvent, "GetAvailabilityChangeEventHandle"},
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RegisterHandlers(functions);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IAm final : public ServiceFramework<IAm> {
 | 
					class IAm final : public ServiceFramework<IAm> {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit IAm(Core::System& system_) : ServiceFramework{system_, "NFC::IAm"} {
 | 
					    explicit IAm(Core::System& system_) : ServiceFramework{system_, "NFC::IAm"} {
 | 
				
			||||||
@@ -34,7 +135,7 @@ public:
 | 
				
			|||||||
    explicit NFC_AM(Core::System& system_) : ServiceFramework{system_, "nfc:am"} {
 | 
					    explicit NFC_AM(Core::System& system_) : ServiceFramework{system_, "nfc:am"} {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
            {0, &NFC_AM::CreateAmInterface, "CreateAmInterface"},
 | 
					            {0, &NFC_AM::CreateAmNfcInterface, "CreateAmNfcInterface"},
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        // clang-format on
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -42,7 +143,7 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    void CreateAmInterface(HLERequestContext& ctx) {
 | 
					    void CreateAmNfcInterface(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_DEBUG(Service_NFC, "called");
 | 
					        LOG_DEBUG(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
@@ -56,7 +157,7 @@ public:
 | 
				
			|||||||
    explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} {
 | 
					    explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
            {0, &NFC_MF_U::CreateUserInterface, "CreateUserInterface"},
 | 
					            {0, &NFC_MF_U::CreateUserNfcInterface, "CreateUserNfcInterface"},
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        // clang-format on
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,7 +165,7 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    void CreateUserInterface(HLERequestContext& ctx) {
 | 
					    void CreateUserNfcInterface(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_DEBUG(Service_NFC, "called");
 | 
					        LOG_DEBUG(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
@@ -78,7 +179,7 @@ public:
 | 
				
			|||||||
    explicit NFC_U(Core::System& system_) : ServiceFramework{system_, "nfc:user"} {
 | 
					    explicit NFC_U(Core::System& system_) : ServiceFramework{system_, "nfc:user"} {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
            {0, &NFC_U::CreateUserInterface, "CreateUserInterface"},
 | 
					            {0, &NFC_U::CreateUserNfcInterface, "CreateUserNfcInterface"},
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        // clang-format on
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -86,7 +187,7 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    void CreateUserInterface(HLERequestContext& ctx) {
 | 
					    void CreateUserNfcInterface(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_DEBUG(Service_NFC, "called");
 | 
					        LOG_DEBUG(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
@@ -95,49 +196,12 @@ private:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ISystem final : public ServiceFramework<ISystem> {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    explicit ISystem(Core::System& system_) : ServiceFramework{system_, "ISystem"} {
 | 
					 | 
				
			||||||
        // clang-format off
 | 
					 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					 | 
				
			||||||
            {0, nullptr, "Initialize"},
 | 
					 | 
				
			||||||
            {1, nullptr, "Finalize"},
 | 
					 | 
				
			||||||
            {2, nullptr, "GetStateOld"},
 | 
					 | 
				
			||||||
            {3, nullptr, "IsNfcEnabledOld"},
 | 
					 | 
				
			||||||
            {100, nullptr, "SetNfcEnabledOld"},
 | 
					 | 
				
			||||||
            {400, nullptr, "InitializeSystem"},
 | 
					 | 
				
			||||||
            {401, nullptr, "FinalizeSystem"},
 | 
					 | 
				
			||||||
            {402, nullptr, "GetState"},
 | 
					 | 
				
			||||||
            {403, nullptr, "IsNfcEnabled"},
 | 
					 | 
				
			||||||
            {404, nullptr, "ListDevices"},
 | 
					 | 
				
			||||||
            {405, nullptr, "GetDeviceState"},
 | 
					 | 
				
			||||||
            {406, nullptr, "GetNpadId"},
 | 
					 | 
				
			||||||
            {407, nullptr, "AttachAvailabilityChangeEvent"},
 | 
					 | 
				
			||||||
            {408, nullptr, "StartDetection"},
 | 
					 | 
				
			||||||
            {409, nullptr, "StopDetection"},
 | 
					 | 
				
			||||||
            {410, nullptr, "GetTagInfo"},
 | 
					 | 
				
			||||||
            {411, nullptr, "AttachActivateEvent"},
 | 
					 | 
				
			||||||
            {412, nullptr, "AttachDeactivateEvent"},
 | 
					 | 
				
			||||||
            {500, nullptr, "SetNfcEnabled"},
 | 
					 | 
				
			||||||
            {510, nullptr, "OutputTestWave"},
 | 
					 | 
				
			||||||
            {1000, nullptr, "ReadMifare"},
 | 
					 | 
				
			||||||
            {1001, nullptr, "WriteMifare"},
 | 
					 | 
				
			||||||
            {1300, nullptr, "SendCommandByPassThrough"},
 | 
					 | 
				
			||||||
            {1301, nullptr, "KeepPassThroughSession"},
 | 
					 | 
				
			||||||
            {1302, nullptr, "ReleasePassThroughSession"},
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        // clang-format on
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        RegisterHandlers(functions);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NFC_SYS final : public ServiceFramework<NFC_SYS> {
 | 
					class NFC_SYS final : public ServiceFramework<NFC_SYS> {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit NFC_SYS(Core::System& system_) : ServiceFramework{system_, "nfc:sys"} {
 | 
					    explicit NFC_SYS(Core::System& system_) : ServiceFramework{system_, "nfc:sys"} {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfo functions[] = {
 | 
				
			||||||
            {0, &NFC_SYS::CreateSystemInterface, "CreateSystemInterface"},
 | 
					            {0, &NFC_SYS::CreateSystemNfcInterface, "CreateSystemNfcInterface"},
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        // clang-format on
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -145,7 +209,7 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    void CreateSystemInterface(HLERequestContext& ctx) {
 | 
					    void CreateSystemNfcInterface(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_DEBUG(Service_NFC, "called");
 | 
					        LOG_DEBUG(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
@@ -161,6 +225,7 @@ void LoopProcess(Core::System& system) {
 | 
				
			|||||||
    server_manager->RegisterNamedService("nfc:mf:u", std::make_shared<NFC_MF_U>(system));
 | 
					    server_manager->RegisterNamedService("nfc:mf:u", std::make_shared<NFC_MF_U>(system));
 | 
				
			||||||
    server_manager->RegisterNamedService("nfc:user", std::make_shared<NFC_U>(system));
 | 
					    server_manager->RegisterNamedService("nfc:user", std::make_shared<NFC_U>(system));
 | 
				
			||||||
    server_manager->RegisterNamedService("nfc:sys", std::make_shared<NFC_SYS>(system));
 | 
					    server_manager->RegisterNamedService("nfc:sys", std::make_shared<NFC_SYS>(system));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ServerManager::RunServer(std::move(server_manager));
 | 
					    ServerManager::RunServer(std::move(server_manager));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,288 +0,0 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
					 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "common/input.h"
 | 
					 | 
				
			||||||
#include "common/logging/log.h"
 | 
					 | 
				
			||||||
#include "core/core.h"
 | 
					 | 
				
			||||||
#include "core/hid/emulated_controller.h"
 | 
					 | 
				
			||||||
#include "core/hid/hid_core.h"
 | 
					 | 
				
			||||||
#include "core/hid/hid_types.h"
 | 
					 | 
				
			||||||
#include "core/hle/kernel/k_event.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/ipc_helpers.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_device.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_result.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_user.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Service::NFC {
 | 
					 | 
				
			||||||
NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
 | 
					 | 
				
			||||||
                     KernelHelpers::ServiceContext& service_context_,
 | 
					 | 
				
			||||||
                     Kernel::KEvent* availability_change_event_)
 | 
					 | 
				
			||||||
    : npad_id{npad_id_}, system{system_}, service_context{service_context_},
 | 
					 | 
				
			||||||
      availability_change_event{availability_change_event_} {
 | 
					 | 
				
			||||||
    activate_event = service_context.CreateEvent("IUser:NFCActivateEvent");
 | 
					 | 
				
			||||||
    deactivate_event = service_context.CreateEvent("IUser:NFCDeactivateEvent");
 | 
					 | 
				
			||||||
    npad_device = system.HIDCore().GetEmulatedController(npad_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Core::HID::ControllerUpdateCallback engine_callback{
 | 
					 | 
				
			||||||
        .on_change = [this](Core::HID::ControllerTriggerType type) { NpadUpdate(type); },
 | 
					 | 
				
			||||||
        .is_npad_service = false,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    is_controller_set = true;
 | 
					 | 
				
			||||||
    callback_key = npad_device->SetCallback(engine_callback);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NfcDevice::~NfcDevice() {
 | 
					 | 
				
			||||||
    activate_event->Close();
 | 
					 | 
				
			||||||
    deactivate_event->Close();
 | 
					 | 
				
			||||||
    if (!is_controller_set) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    npad_device->DeleteCallback(callback_key);
 | 
					 | 
				
			||||||
    is_controller_set = false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
 | 
					 | 
				
			||||||
    if (!is_initalized) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (type == Core::HID::ControllerTriggerType::Connected) {
 | 
					 | 
				
			||||||
        Initialize();
 | 
					 | 
				
			||||||
        availability_change_event->Signal();
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (type == Core::HID::ControllerTriggerType::Disconnected) {
 | 
					 | 
				
			||||||
        device_state = NFP::DeviceState::Unavailable;
 | 
					 | 
				
			||||||
        availability_change_event->Signal();
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (type != Core::HID::ControllerTriggerType::Nfc) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!npad_device->IsConnected()) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto nfc_status = npad_device->GetNfc();
 | 
					 | 
				
			||||||
    switch (nfc_status.state) {
 | 
					 | 
				
			||||||
    case Common::Input::NfcState::NewAmiibo:
 | 
					 | 
				
			||||||
        LoadNfcTag(nfc_status.data);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case Common::Input::NfcState::AmiiboRemoved:
 | 
					 | 
				
			||||||
        if (device_state != NFP::DeviceState::SearchingForTag) {
 | 
					 | 
				
			||||||
            CloseNfcTag();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool NfcDevice::LoadNfcTag(std::span<const u8> data) {
 | 
					 | 
				
			||||||
    if (device_state != NFP::DeviceState::SearchingForTag) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state);
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (data.size() < sizeof(NFP::EncryptedNTAG215File)) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size());
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tag_data.resize(data.size());
 | 
					 | 
				
			||||||
    memcpy(tag_data.data(), data.data(), data.size());
 | 
					 | 
				
			||||||
    memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    device_state = NFP::DeviceState::TagFound;
 | 
					 | 
				
			||||||
    deactivate_event->GetReadableEvent().Clear();
 | 
					 | 
				
			||||||
    activate_event->Signal();
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NfcDevice::CloseNfcTag() {
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "Remove nfc tag");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    device_state = NFP::DeviceState::TagRemoved;
 | 
					 | 
				
			||||||
    encrypted_tag_data = {};
 | 
					 | 
				
			||||||
    activate_event->GetReadableEvent().Clear();
 | 
					 | 
				
			||||||
    deactivate_event->Signal();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const {
 | 
					 | 
				
			||||||
    return activate_event->GetReadableEvent();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Kernel::KReadableEvent& NfcDevice::GetDeactivateEvent() const {
 | 
					 | 
				
			||||||
    return deactivate_event->GetReadableEvent();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NfcDevice::Initialize() {
 | 
					 | 
				
			||||||
    device_state =
 | 
					 | 
				
			||||||
        npad_device->HasNfc() ? NFP::DeviceState::Initialized : NFP::DeviceState::Unavailable;
 | 
					 | 
				
			||||||
    encrypted_tag_data = {};
 | 
					 | 
				
			||||||
    is_initalized = true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NfcDevice::Finalize() {
 | 
					 | 
				
			||||||
    if (device_state == NFP::DeviceState::SearchingForTag ||
 | 
					 | 
				
			||||||
        device_state == NFP::DeviceState::TagRemoved) {
 | 
					 | 
				
			||||||
        StopDetection();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    device_state = NFP::DeviceState::Unavailable;
 | 
					 | 
				
			||||||
    is_initalized = false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) {
 | 
					 | 
				
			||||||
    if (device_state != NFP::DeviceState::Initialized &&
 | 
					 | 
				
			||||||
        device_state != NFP::DeviceState::TagRemoved) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
 | 
					 | 
				
			||||||
        return WrongDeviceState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
					 | 
				
			||||||
                                    Common::Input::PollingMode::NFC) !=
 | 
					 | 
				
			||||||
        Common::Input::DriverResult::Success) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Nfc not supported");
 | 
					 | 
				
			||||||
        return NfcDisabled;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    device_state = NFP::DeviceState::SearchingForTag;
 | 
					 | 
				
			||||||
    allowed_protocols = allowed_protocol;
 | 
					 | 
				
			||||||
    return ResultSuccess;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Result NfcDevice::StopDetection() {
 | 
					 | 
				
			||||||
    npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
					 | 
				
			||||||
                                Common::Input::PollingMode::Active);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (device_state == NFP::DeviceState::Initialized) {
 | 
					 | 
				
			||||||
        return ResultSuccess;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (device_state == NFP::DeviceState::TagFound ||
 | 
					 | 
				
			||||||
        device_state == NFP::DeviceState::TagMounted) {
 | 
					 | 
				
			||||||
        CloseNfcTag();
 | 
					 | 
				
			||||||
        return ResultSuccess;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (device_state == NFP::DeviceState::SearchingForTag ||
 | 
					 | 
				
			||||||
        device_state == NFP::DeviceState::TagRemoved) {
 | 
					 | 
				
			||||||
        device_state = NFP::DeviceState::Initialized;
 | 
					 | 
				
			||||||
        return ResultSuccess;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
 | 
					 | 
				
			||||||
    return WrongDeviceState;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Result NfcDevice::Flush() {
 | 
					 | 
				
			||||||
    if (device_state != NFP::DeviceState::TagFound &&
 | 
					 | 
				
			||||||
        device_state != NFP::DeviceState::TagMounted) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
 | 
					 | 
				
			||||||
        if (device_state == NFP::DeviceState::TagRemoved) {
 | 
					 | 
				
			||||||
            return TagRemoved;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return WrongDeviceState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!npad_device->WriteNfc(tag_data)) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFP, "Error writing to file");
 | 
					 | 
				
			||||||
        return MifareReadError;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ResultSuccess;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
 | 
					 | 
				
			||||||
    if (device_state != NFP::DeviceState::TagFound &&
 | 
					 | 
				
			||||||
        device_state != NFP::DeviceState::TagMounted) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
 | 
					 | 
				
			||||||
        if (device_state == NFP::DeviceState::TagRemoved) {
 | 
					 | 
				
			||||||
            return TagRemoved;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return WrongDeviceState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (is_mifare) {
 | 
					 | 
				
			||||||
        tag_info = {
 | 
					 | 
				
			||||||
            .uuid = encrypted_tag_data.uuid.uid,
 | 
					 | 
				
			||||||
            .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
 | 
					 | 
				
			||||||
            .protocol = NFP::TagProtocol::TypeA,
 | 
					 | 
				
			||||||
            .tag_type = NFP::TagType::Type4,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        return ResultSuccess;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Protocol and tag type may change here
 | 
					 | 
				
			||||||
    tag_info = {
 | 
					 | 
				
			||||||
        .uuid = encrypted_tag_data.uuid.uid,
 | 
					 | 
				
			||||||
        .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
 | 
					 | 
				
			||||||
        .protocol = NFP::TagProtocol::TypeA,
 | 
					 | 
				
			||||||
        .tag_type = NFP::TagType::Type2,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ResultSuccess;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Result NfcDevice::MifareRead(const NFP::MifareReadBlockParameter& parameter,
 | 
					 | 
				
			||||||
                             NFP::MifareReadBlockData& read_block_data) {
 | 
					 | 
				
			||||||
    const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock);
 | 
					 | 
				
			||||||
    read_block_data.sector_number = parameter.sector_number;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (device_state != NFP::DeviceState::TagFound &&
 | 
					 | 
				
			||||||
        device_state != NFP::DeviceState::TagMounted) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
 | 
					 | 
				
			||||||
        if (device_state == NFP::DeviceState::TagRemoved) {
 | 
					 | 
				
			||||||
            return TagRemoved;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return WrongDeviceState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) {
 | 
					 | 
				
			||||||
        return MifareReadError;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO: Use parameter.sector_key to read encrypted data
 | 
					 | 
				
			||||||
    memcpy(read_block_data.data.data(), tag_data.data() + sector_index, sizeof(NFP::DataBlock));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ResultSuccess;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Result NfcDevice::MifareWrite(const NFP::MifareWriteBlockParameter& parameter) {
 | 
					 | 
				
			||||||
    const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (device_state != NFP::DeviceState::TagFound &&
 | 
					 | 
				
			||||||
        device_state != NFP::DeviceState::TagMounted) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
 | 
					 | 
				
			||||||
        if (device_state == NFP::DeviceState::TagRemoved) {
 | 
					 | 
				
			||||||
            return TagRemoved;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return WrongDeviceState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) {
 | 
					 | 
				
			||||||
        return MifareReadError;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO: Use parameter.sector_key to encrypt the data
 | 
					 | 
				
			||||||
    memcpy(tag_data.data() + sector_index, parameter.data.data(), sizeof(NFP::DataBlock));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ResultSuccess;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
u64 NfcDevice::GetHandle() const {
 | 
					 | 
				
			||||||
    // Generate a handle based of the npad id
 | 
					 | 
				
			||||||
    return static_cast<u64>(npad_id);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NFP::DeviceState NfcDevice::GetCurrentState() const {
 | 
					 | 
				
			||||||
    return device_state;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Core::HID::NpadIdType NfcDevice::GetNpadId() const {
 | 
					 | 
				
			||||||
    return npad_id;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::NFC
 | 
					 | 
				
			||||||
@@ -1,78 +0,0 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
					 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "common/common_types.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/kernel_helpers.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfp/nfp_types.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/service.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Kernel {
 | 
					 | 
				
			||||||
class KEvent;
 | 
					 | 
				
			||||||
class KReadableEvent;
 | 
					 | 
				
			||||||
} // namespace Kernel
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Core {
 | 
					 | 
				
			||||||
class System;
 | 
					 | 
				
			||||||
} // namespace Core
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Core::HID {
 | 
					 | 
				
			||||||
class EmulatedController;
 | 
					 | 
				
			||||||
enum class ControllerTriggerType;
 | 
					 | 
				
			||||||
enum class NpadIdType : u32;
 | 
					 | 
				
			||||||
} // namespace Core::HID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Service::NFC {
 | 
					 | 
				
			||||||
class NfcDevice {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
 | 
					 | 
				
			||||||
              KernelHelpers::ServiceContext& service_context_,
 | 
					 | 
				
			||||||
              Kernel::KEvent* availability_change_event_);
 | 
					 | 
				
			||||||
    ~NfcDevice();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void Initialize();
 | 
					 | 
				
			||||||
    void Finalize();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result StartDetection(NFP::TagProtocol allowed_protocol);
 | 
					 | 
				
			||||||
    Result StopDetection();
 | 
					 | 
				
			||||||
    Result Flush();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result MifareRead(const NFP::MifareReadBlockParameter& parameter,
 | 
					 | 
				
			||||||
                      NFP::MifareReadBlockData& read_block_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result MifareWrite(const NFP::MifareWriteBlockParameter& parameter);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    u64 GetHandle() const;
 | 
					 | 
				
			||||||
    NFP::DeviceState GetCurrentState() const;
 | 
					 | 
				
			||||||
    Core::HID::NpadIdType GetNpadId() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Kernel::KReadableEvent& GetActivateEvent() const;
 | 
					 | 
				
			||||||
    Kernel::KReadableEvent& GetDeactivateEvent() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    void NpadUpdate(Core::HID::ControllerTriggerType type);
 | 
					 | 
				
			||||||
    bool LoadNfcTag(std::span<const u8> data);
 | 
					 | 
				
			||||||
    void CloseNfcTag();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool is_controller_set{};
 | 
					 | 
				
			||||||
    int callback_key;
 | 
					 | 
				
			||||||
    const Core::HID::NpadIdType npad_id;
 | 
					 | 
				
			||||||
    Core::System& system;
 | 
					 | 
				
			||||||
    Core::HID::EmulatedController* npad_device = nullptr;
 | 
					 | 
				
			||||||
    KernelHelpers::ServiceContext& service_context;
 | 
					 | 
				
			||||||
    Kernel::KEvent* activate_event = nullptr;
 | 
					 | 
				
			||||||
    Kernel::KEvent* deactivate_event = nullptr;
 | 
					 | 
				
			||||||
    Kernel::KEvent* availability_change_event = nullptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool is_initalized{};
 | 
					 | 
				
			||||||
    NFP::TagProtocol allowed_protocols{};
 | 
					 | 
				
			||||||
    NFP::DeviceState device_state{NFP::DeviceState::Unavailable};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    NFP::EncryptedNTAG215File encrypted_tag_data{};
 | 
					 | 
				
			||||||
    std::vector<u8> tag_data{};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::NFC
 | 
					 | 
				
			||||||
							
								
								
									
										382
									
								
								src/core/hle/service/nfc/nfc_interface.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										382
									
								
								src/core/hle/service/nfc/nfc_interface.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,382 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
 | 
					#include "core/core.h"
 | 
				
			||||||
 | 
					#include "core/hid/hid_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/kernel/k_event.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/ipc_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/common/device.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/common/device_manager.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/mifare_result.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/mifare_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_interface.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_result.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfp/nfp_result.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/time/clock_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NfcInterface::NfcInterface(Core::System& system_, const char* name, BackendType service_backend)
 | 
				
			||||||
 | 
					    : ServiceFramework{system_, name}, service_context{system_, service_name},
 | 
				
			||||||
 | 
					      backend_type{service_backend} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NfcInterface ::~NfcInterface() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::Initialize(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto manager = GetManager();
 | 
				
			||||||
 | 
					    auto result = manager->Initialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        state = State::Initialized;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        manager->Finalize();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 0};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::Finalize(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (state != State::NonInitialized) {
 | 
				
			||||||
 | 
					        if (GetBackendType() != BackendType::None) {
 | 
				
			||||||
 | 
					            GetManager()->Finalize();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        device_manager = nullptr;
 | 
				
			||||||
 | 
					        state = State::NonInitialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::GetState(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushEnum(state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::IsNfcEnabled(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: This calls nn::settings::detail::GetNfcEnableFlag
 | 
				
			||||||
 | 
					    const bool is_enabled = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(is_enabled);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::ListDevices(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    std::vector<u64> nfp_devices;
 | 
				
			||||||
 | 
					    const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsError()) {
 | 
				
			||||||
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					        rb.Push(result);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.WriteBuffer(nfp_devices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(static_cast<s32>(nfp_devices.size()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::GetDeviceState(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto device_state = GetManager()->GetDeviceState(device_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (device_state > DeviceState::Finalized) {
 | 
				
			||||||
 | 
					        ASSERT_MSG(false, "Invalid device state");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushEnum(device_state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::GetNpadId(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Core::HID::NpadIdType npad_id{};
 | 
				
			||||||
 | 
					    auto result = GetManager()->GetNpadId(device_handle, npad_id);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsError()) {
 | 
				
			||||||
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					        rb.Push(result);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushEnum(npad_id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushCopyObjects(GetManager()->AttachAvailabilityChangeEvent());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::StartDetection(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    const auto tag_protocol{rp.PopEnum<NfcProtocol>()};
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto result = GetManager()->StartDetection(device_handle, tag_protocol);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::StopDetection(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto result = GetManager()->StopDetection(device_handle);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::GetTagInfo(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TagInfo tag_info{};
 | 
				
			||||||
 | 
					    auto result =
 | 
				
			||||||
 | 
					        GetManager()->GetTagInfo(device_handle, tag_info, backend_type == BackendType::Mifare);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        ctx.WriteBuffer(tag_info);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::ReadMifare(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    const auto buffer{ctx.ReadBuffer()};
 | 
				
			||||||
 | 
					    const auto number_of_commands{ctx.GetReadBufferNumElements<MifareReadBlockParameter>()};
 | 
				
			||||||
 | 
					    std::vector<MifareReadBlockParameter> read_commands(number_of_commands);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(read_commands.data(), buffer.data(),
 | 
				
			||||||
 | 
					           number_of_commands * sizeof(MifareReadBlockParameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
 | 
				
			||||||
 | 
					             device_handle, number_of_commands);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<MifareReadBlockData> out_data(number_of_commands);
 | 
				
			||||||
 | 
					    auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        ctx.WriteBuffer(out_data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::WriteMifare(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    const auto buffer{ctx.ReadBuffer()};
 | 
				
			||||||
 | 
					    const auto number_of_commands{ctx.GetReadBufferNumElements<MifareWriteBlockParameter>()};
 | 
				
			||||||
 | 
					    std::vector<MifareWriteBlockParameter> write_commands(number_of_commands);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(write_commands.data(), buffer.data(),
 | 
				
			||||||
 | 
					           number_of_commands * sizeof(MifareWriteBlockParameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
 | 
				
			||||||
 | 
					             device_handle, number_of_commands);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto result = GetManager()->WriteMifare(device_handle, write_commands);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NfcInterface::SendCommandByPassThrough(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const auto device_handle{rp.Pop<u64>()};
 | 
				
			||||||
 | 
					    const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()};
 | 
				
			||||||
 | 
					    const auto command_data{ctx.ReadBuffer()};
 | 
				
			||||||
 | 
					    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}",
 | 
				
			||||||
 | 
					             device_handle, timeout.ToSeconds(), command_data.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<u8> out_data(1);
 | 
				
			||||||
 | 
					    auto result =
 | 
				
			||||||
 | 
					        GetManager()->SendCommandByPassThrough(device_handle, timeout, command_data, out_data);
 | 
				
			||||||
 | 
					    result = TranslateResultToServiceError(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsError()) {
 | 
				
			||||||
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					        rb.Push(result);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.WriteBuffer(out_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(static_cast<u32>(out_data.size()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::shared_ptr<DeviceManager> NfcInterface::GetManager() {
 | 
				
			||||||
 | 
					    if (device_manager == nullptr) {
 | 
				
			||||||
 | 
					        device_manager = std::make_shared<DeviceManager>(system, service_context);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return device_manager;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BackendType NfcInterface::GetBackendType() const {
 | 
				
			||||||
 | 
					    return backend_type;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result NfcInterface::TranslateResultToServiceError(Result result) const {
 | 
				
			||||||
 | 
					    const auto backend = GetBackendType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.module != ErrorModule::NFC) {
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (backend) {
 | 
				
			||||||
 | 
					    case BackendType::Mifare:
 | 
				
			||||||
 | 
					        return TranslateResultToNfp(result);
 | 
				
			||||||
 | 
					    case BackendType::Nfp: {
 | 
				
			||||||
 | 
					        return TranslateResultToNfp(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        if (result != ResultUnknown216) {
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ResultUnknown74;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result NfcInterface::TranslateResultToNfp(Result result) const {
 | 
				
			||||||
 | 
					    if (result == ResultDeviceNotFound) {
 | 
				
			||||||
 | 
					        return NFP::ResultDeviceNotFound;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultInvalidArgument) {
 | 
				
			||||||
 | 
					        return NFP::ResultInvalidArgument;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultWrongApplicationAreaSize) {
 | 
				
			||||||
 | 
					        return NFP::ResultWrongApplicationAreaSize;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultWrongDeviceState) {
 | 
				
			||||||
 | 
					        return NFP::ResultWrongDeviceState;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultUnknown74) {
 | 
				
			||||||
 | 
					        return NFP::ResultUnknown74;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultNfcDisabled) {
 | 
				
			||||||
 | 
					        return NFP::ResultNfcDisabled;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultNfcNotInitialized) {
 | 
				
			||||||
 | 
					        return NFP::ResultNfcDisabled;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultWriteAmiiboFailed) {
 | 
				
			||||||
 | 
					        return NFP::ResultWriteAmiiboFailed;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultTagRemoved) {
 | 
				
			||||||
 | 
					        return NFP::ResultTagRemoved;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultRegistrationIsNotInitialized) {
 | 
				
			||||||
 | 
					        return NFP::ResultRegistrationIsNotInitialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultApplicationAreaIsNotInitialized) {
 | 
				
			||||||
 | 
					        return NFP::ResultApplicationAreaIsNotInitialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultCorruptedData) {
 | 
				
			||||||
 | 
					        return NFP::ResultCorruptedData;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultWrongApplicationAreaId) {
 | 
				
			||||||
 | 
					        return NFP::ResultWrongApplicationAreaId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultApplicationAreaExist) {
 | 
				
			||||||
 | 
					        return NFP::ResultApplicationAreaExist;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultNotAnAmiibo) {
 | 
				
			||||||
 | 
					        return NFP::ResultNotAnAmiibo;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    LOG_WARNING(Service_NFC, "Result conversion not handled");
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result NfcInterface::TranslateResultToMifare(Result result) const {
 | 
				
			||||||
 | 
					    if (result == ResultDeviceNotFound) {
 | 
				
			||||||
 | 
					        return Mifare::ResultDeviceNotFound;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultInvalidArgument) {
 | 
				
			||||||
 | 
					        return Mifare::ResultInvalidArgument;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultWrongDeviceState) {
 | 
				
			||||||
 | 
					        return Mifare::ResultWrongDeviceState;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultNfcDisabled) {
 | 
				
			||||||
 | 
					        return Mifare::ResultNfcDisabled;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (result == ResultTagRemoved) {
 | 
				
			||||||
 | 
					        return Mifare::ResultTagRemoved;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    LOG_WARNING(Service_NFC, "Result conversion not handled");
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::NFC
 | 
				
			||||||
@@ -3,26 +3,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <array>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					 | 
				
			||||||
#include <optional>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "core/hle/service/kernel_helpers.h"
 | 
					#include "core/hle/service/kernel_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_types.h"
 | 
				
			||||||
#include "core/hle/service/service.h"
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFC {
 | 
					namespace Service::NFC {
 | 
				
			||||||
class NfcDevice;
 | 
					class DeviceManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IUser final : public ServiceFramework<IUser> {
 | 
					class NfcInterface : public ServiceFramework<NfcInterface> {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit IUser(Core::System& system_);
 | 
					    explicit NfcInterface(Core::System& system_, const char* name, BackendType service_backend);
 | 
				
			||||||
    ~IUser();
 | 
					    ~NfcInterface();
 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    enum class State : u32 {
 | 
					 | 
				
			||||||
        NonInitialized,
 | 
					 | 
				
			||||||
        Initialized,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Initialize(HLERequestContext& ctx);
 | 
					    void Initialize(HLERequestContext& ctx);
 | 
				
			||||||
    void Finalize(HLERequestContext& ctx);
 | 
					    void Finalize(HLERequestContext& ctx);
 | 
				
			||||||
@@ -37,16 +28,22 @@ private:
 | 
				
			|||||||
    void GetTagInfo(HLERequestContext& ctx);
 | 
					    void GetTagInfo(HLERequestContext& ctx);
 | 
				
			||||||
    void AttachActivateEvent(HLERequestContext& ctx);
 | 
					    void AttachActivateEvent(HLERequestContext& ctx);
 | 
				
			||||||
    void AttachDeactivateEvent(HLERequestContext& ctx);
 | 
					    void AttachDeactivateEvent(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void ReadMifare(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void WriteMifare(HLERequestContext& ctx);
 | 
				
			||||||
    void SendCommandByPassThrough(HLERequestContext& ctx);
 | 
					    void SendCommandByPassThrough(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
 | 
					protected:
 | 
				
			||||||
 | 
					    std::shared_ptr<DeviceManager> GetManager();
 | 
				
			||||||
 | 
					    BackendType GetBackendType() const;
 | 
				
			||||||
 | 
					    Result TranslateResultToServiceError(Result result) const;
 | 
				
			||||||
 | 
					    Result TranslateResultToNfp(Result result) const;
 | 
				
			||||||
 | 
					    Result TranslateResultToMifare(Result result) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    KernelHelpers::ServiceContext service_context;
 | 
					    KernelHelpers::ServiceContext service_context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::array<std::shared_ptr<NfcDevice>, 10> devices{};
 | 
					    BackendType backend_type;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    State state{State::NonInitialized};
 | 
					    State state{State::NonInitialized};
 | 
				
			||||||
    Kernel::KEvent* availability_change_event;
 | 
					    std::shared_ptr<DeviceManager> device_manager = nullptr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::NFC
 | 
					} // namespace Service::NFC
 | 
				
			||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					// SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7,17 +7,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Service::NFC {
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr Result DeviceNotFound(ErrorModule::NFC, 64);
 | 
					constexpr Result ResultDeviceNotFound(ErrorModule::NFC, 64);
 | 
				
			||||||
constexpr Result InvalidArgument(ErrorModule::NFC, 65);
 | 
					constexpr Result ResultInvalidArgument(ErrorModule::NFC, 65);
 | 
				
			||||||
constexpr Result WrongDeviceState(ErrorModule::NFC, 73);
 | 
					constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFP, 68);
 | 
				
			||||||
constexpr Result NfcDisabled(ErrorModule::NFC, 80);
 | 
					constexpr Result ResultWrongDeviceState(ErrorModule::NFC, 73);
 | 
				
			||||||
constexpr Result TagRemoved(ErrorModule::NFC, 97);
 | 
					constexpr Result ResultUnknown74(ErrorModule::NFC, 74);
 | 
				
			||||||
 | 
					constexpr Result ResultUnknown76(ErrorModule::NFC, 76);
 | 
				
			||||||
constexpr Result MifareDeviceNotFound(ErrorModule::NFCMifare, 64);
 | 
					constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77);
 | 
				
			||||||
constexpr Result MifareInvalidArgument(ErrorModule::NFCMifare, 65);
 | 
					constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80);
 | 
				
			||||||
constexpr Result MifareWrongDeviceState(ErrorModule::NFCMifare, 73);
 | 
					constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFP, 88);
 | 
				
			||||||
constexpr Result MifareNfcDisabled(ErrorModule::NFCMifare, 80);
 | 
					constexpr Result ResultTagRemoved(ErrorModule::NFC, 97);
 | 
				
			||||||
constexpr Result MifareTagRemoved(ErrorModule::NFCMifare, 97);
 | 
					constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120);
 | 
				
			||||||
constexpr Result MifareReadError(ErrorModule::NFCMifare, 288);
 | 
					constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
 | 
				
			||||||
 | 
					constexpr Result ResultCorruptedData(ErrorModule::NFP, 144);
 | 
				
			||||||
 | 
					constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152);
 | 
				
			||||||
 | 
					constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168);
 | 
				
			||||||
 | 
					constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178);
 | 
				
			||||||
 | 
					constexpr Result ResultUnknown216(ErrorModule::NFC, 216);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::NFC
 | 
					} // namespace Service::NFC
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										90
									
								
								src/core/hle/service/nfc/nfc_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/core/hle/service/nfc/nfc_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-3.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common/common_funcs.h"
 | 
				
			||||||
 | 
					#include "common/common_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::NFC {
 | 
				
			||||||
 | 
					enum class BackendType : u32 {
 | 
				
			||||||
 | 
					    None,
 | 
				
			||||||
 | 
					    Nfc,
 | 
				
			||||||
 | 
					    Nfp,
 | 
				
			||||||
 | 
					    Mifare,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::DeviceState
 | 
				
			||||||
 | 
					enum class DeviceState : u32 {
 | 
				
			||||||
 | 
					    Initialized,
 | 
				
			||||||
 | 
					    SearchingForTag,
 | 
				
			||||||
 | 
					    TagFound,
 | 
				
			||||||
 | 
					    TagRemoved,
 | 
				
			||||||
 | 
					    TagMounted,
 | 
				
			||||||
 | 
					    Unavailable,
 | 
				
			||||||
 | 
					    Finalized,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::State
 | 
				
			||||||
 | 
					enum class State : u32 {
 | 
				
			||||||
 | 
					    NonInitialized,
 | 
				
			||||||
 | 
					    Initialized,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::TagType
 | 
				
			||||||
 | 
					enum class TagType : u32 {
 | 
				
			||||||
 | 
					    None,
 | 
				
			||||||
 | 
					    Type1, // ISO14443A RW 96-2k bytes 106kbit/s
 | 
				
			||||||
 | 
					    Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
 | 
				
			||||||
 | 
					    Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s
 | 
				
			||||||
 | 
					    Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
 | 
				
			||||||
 | 
					    Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class PackedTagType : u8 {
 | 
				
			||||||
 | 
					    None,
 | 
				
			||||||
 | 
					    Type1, // ISO14443A RW 96-2k bytes 106kbit/s
 | 
				
			||||||
 | 
					    Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
 | 
				
			||||||
 | 
					    Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s
 | 
				
			||||||
 | 
					    Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
 | 
				
			||||||
 | 
					    Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::NfcProtocol
 | 
				
			||||||
 | 
					// Verify this enum. It might be completely wrong default protocol is 0x48
 | 
				
			||||||
 | 
					enum class NfcProtocol : u32 {
 | 
				
			||||||
 | 
					    None,
 | 
				
			||||||
 | 
					    TypeA = 1U << 0, // ISO14443A
 | 
				
			||||||
 | 
					    TypeB = 1U << 1, // ISO14443B
 | 
				
			||||||
 | 
					    TypeF = 1U << 2, // Sony FeliCa
 | 
				
			||||||
 | 
					    Unknown1 = 1U << 3,
 | 
				
			||||||
 | 
					    Unknown2 = 1U << 5,
 | 
				
			||||||
 | 
					    All = 0xFFFFFFFFU,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// this is nn::nfc::TestWaveType
 | 
				
			||||||
 | 
					enum class TestWaveType : u32 {
 | 
				
			||||||
 | 
					    Unknown,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using UniqueSerialNumber = std::array<u8, 7>;
 | 
				
			||||||
 | 
					using UniqueSerialNumberExtension = std::array<u8, 3>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::DeviceHandle
 | 
				
			||||||
 | 
					using DeviceHandle = u64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfc::TagInfo
 | 
				
			||||||
 | 
					struct TagInfo {
 | 
				
			||||||
 | 
					    UniqueSerialNumber uuid;
 | 
				
			||||||
 | 
					    UniqueSerialNumberExtension uuid_extension;
 | 
				
			||||||
 | 
					    u8 uuid_length;
 | 
				
			||||||
 | 
					    INSERT_PADDING_BYTES(0x15);
 | 
				
			||||||
 | 
					    NfcProtocol protocol;
 | 
				
			||||||
 | 
					    TagType tag_type;
 | 
				
			||||||
 | 
					    INSERT_PADDING_BYTES(0x30);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::NFC
 | 
				
			||||||
@@ -1,365 +0,0 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
					 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "common/logging/log.h"
 | 
					 | 
				
			||||||
#include "core/core.h"
 | 
					 | 
				
			||||||
#include "core/hid/hid_types.h"
 | 
					 | 
				
			||||||
#include "core/hle/kernel/k_event.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/ipc_helpers.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_device.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_result.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfc/nfc_user.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/time/clock_types.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Service::NFC {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IUser::IUser(Core::System& system_)
 | 
					 | 
				
			||||||
    : ServiceFramework{system_, "NFC::IUser"}, service_context{system_, service_name} {
 | 
					 | 
				
			||||||
    static const FunctionInfo functions[] = {
 | 
					 | 
				
			||||||
        {0, &IUser::Initialize, "InitializeOld"},
 | 
					 | 
				
			||||||
        {1, &IUser::Finalize, "FinalizeOld"},
 | 
					 | 
				
			||||||
        {2, &IUser::GetState, "GetStateOld"},
 | 
					 | 
				
			||||||
        {3, &IUser::IsNfcEnabled, "IsNfcEnabledOld"},
 | 
					 | 
				
			||||||
        {400, &IUser::Initialize, "Initialize"},
 | 
					 | 
				
			||||||
        {401, &IUser::Finalize, "Finalize"},
 | 
					 | 
				
			||||||
        {402, &IUser::GetState, "GetState"},
 | 
					 | 
				
			||||||
        {403, &IUser::IsNfcEnabled, "IsNfcEnabled"},
 | 
					 | 
				
			||||||
        {404, &IUser::ListDevices, "ListDevices"},
 | 
					 | 
				
			||||||
        {405, &IUser::GetDeviceState, "GetDeviceState"},
 | 
					 | 
				
			||||||
        {406, &IUser::GetNpadId, "GetNpadId"},
 | 
					 | 
				
			||||||
        {407, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"},
 | 
					 | 
				
			||||||
        {408, &IUser::StartDetection, "StartDetection"},
 | 
					 | 
				
			||||||
        {409, &IUser::StopDetection, "StopDetection"},
 | 
					 | 
				
			||||||
        {410, &IUser::GetTagInfo, "GetTagInfo"},
 | 
					 | 
				
			||||||
        {411, &IUser::AttachActivateEvent, "AttachActivateEvent"},
 | 
					 | 
				
			||||||
        {412, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"},
 | 
					 | 
				
			||||||
        {1000, nullptr, "ReadMifare"},
 | 
					 | 
				
			||||||
        {1001, nullptr, "WriteMifare"},
 | 
					 | 
				
			||||||
        {1300, &IUser::SendCommandByPassThrough, "SendCommandByPassThrough"},
 | 
					 | 
				
			||||||
        {1301, nullptr, "KeepPassThroughSession"},
 | 
					 | 
				
			||||||
        {1302, nullptr, "ReleasePassThroughSession"},
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    RegisterHandlers(functions);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (u32 device_index = 0; device_index < 10; device_index++) {
 | 
					 | 
				
			||||||
        devices[device_index] =
 | 
					 | 
				
			||||||
            std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
 | 
					 | 
				
			||||||
                                        service_context, availability_change_event);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IUser ::~IUser() {
 | 
					 | 
				
			||||||
    availability_change_event->Close();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::Initialize(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    state = State::Initialized;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (auto& device : devices) {
 | 
					 | 
				
			||||||
        device->Initialize();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 0};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::Finalize(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    state = State::NonInitialized;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (auto& device : devices) {
 | 
					 | 
				
			||||||
        device->Finalize();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::GetState(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushEnum(state);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::IsNfcEnabled(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.Push(state != State::NonInitialized);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::ListDevices(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!ctx.CanWriteBuffer()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(InvalidArgument);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (ctx.GetWriteBufferSize() == 0) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(InvalidArgument);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::vector<u64> nfp_devices;
 | 
					 | 
				
			||||||
    const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (auto& device : devices) {
 | 
					 | 
				
			||||||
        if (nfp_devices.size() >= max_allowed_devices) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (device->GetCurrentState() != NFP::DeviceState::Unavailable) {
 | 
					 | 
				
			||||||
            nfp_devices.push_back(device->GetHandle());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (nfp_devices.empty()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ctx.WriteBuffer(nfp_devices);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.Push(static_cast<s32>(nfp_devices.size()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::GetDeviceState(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushEnum(device.value()->GetCurrentState());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::GetNpadId(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushEnum(device.value()->GetNpadId());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushCopyObjects(availability_change_event->GetReadableEvent());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::StartDetection(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    const auto nfp_protocol{rp.PopEnum<NFP::TagProtocol>()};
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto result = device.value()->StartDetection(nfp_protocol);
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::StopDetection(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto result = device.value()->StopDetection();
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::GetTagInfo(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    NFP::TagInfo tag_info{};
 | 
					 | 
				
			||||||
    const auto result = device.value()->GetTagInfo(tag_info, false);
 | 
					 | 
				
			||||||
    ctx.WriteBuffer(tag_info);
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::AttachActivateEvent(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushCopyObjects(device.value()->GetActivateEvent());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::AttachDeactivateEvent(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushCopyObjects(device.value()->GetDeactivateEvent());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void IUser::SendCommandByPassThrough(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    const auto device_handle{rp.Pop<u64>()};
 | 
					 | 
				
			||||||
    const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()};
 | 
					 | 
				
			||||||
    const auto command_data{ctx.ReadBuffer()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}",
 | 
					 | 
				
			||||||
             device_handle, timeout.ToSeconds(), command_data.size());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state == State::NonInitialized) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(NfcDisabled);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto device = GetNfcDevice(device_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!device.has_value()) {
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(DeviceNotFound);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::vector<u8> out_data(1);
 | 
					 | 
				
			||||||
    // TODO: Request data from nfc device
 | 
					 | 
				
			||||||
    ctx.WriteBuffer(out_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.Push(static_cast<u32>(out_data.size()));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::optional<std::shared_ptr<NfcDevice>> IUser::GetNfcDevice(u64 handle) {
 | 
					 | 
				
			||||||
    for (auto& device : devices) {
 | 
					 | 
				
			||||||
        if (device->GetHandle() == handle) {
 | 
					 | 
				
			||||||
            return device;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return std::nullopt;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::NFC
 | 
					 | 
				
			||||||
@@ -13,7 +13,7 @@ class IUser final : public Interface {
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit IUser(Core::System& system_) : Interface(system_, "NFP:IUser") {
 | 
					    explicit IUser(Core::System& system_) : Interface(system_, "NFP:IUser") {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfoTyped<IUser> functions[] = {
 | 
				
			||||||
            {0, &IUser::Initialize, "Initialize"},
 | 
					            {0, &IUser::Initialize, "Initialize"},
 | 
				
			||||||
            {1, &IUser::Finalize, "Finalize"},
 | 
					            {1, &IUser::Finalize, "Finalize"},
 | 
				
			||||||
            {2, &IUser::ListDevices, "ListDevices"},
 | 
					            {2, &IUser::ListDevices, "ListDevices"},
 | 
				
			||||||
@@ -50,7 +50,7 @@ class ISystem final : public Interface {
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") {
 | 
					    explicit ISystem(Core::System& system_) : Interface(system_, "NFP:ISystem") {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfoTyped<ISystem> functions[] = {
 | 
				
			||||||
            {0, &ISystem::InitializeSystem, "InitializeSystem"},
 | 
					            {0, &ISystem::InitializeSystem, "InitializeSystem"},
 | 
				
			||||||
            {1, &ISystem::FinalizeSystem, "FinalizeSystem"},
 | 
					            {1, &ISystem::FinalizeSystem, "FinalizeSystem"},
 | 
				
			||||||
            {2, &ISystem::ListDevices, "ListDevices"},
 | 
					            {2, &ISystem::ListDevices, "ListDevices"},
 | 
				
			||||||
@@ -89,7 +89,7 @@ class IDebug final : public Interface {
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit IDebug(Core::System& system_) : Interface(system_, "NFP:IDebug") {
 | 
					    explicit IDebug(Core::System& system_) : Interface(system_, "NFP:IDebug") {
 | 
				
			||||||
        // clang-format off
 | 
					        // clang-format off
 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					        static const FunctionInfoTyped<IDebug> functions[] = {
 | 
				
			||||||
            {0, &IDebug::InitializeDebug, "InitializeDebug"},
 | 
					            {0, &IDebug::InitializeDebug, "InitializeDebug"},
 | 
				
			||||||
            {1, &IDebug::FinalizeDebug, "FinalizeDebug"},
 | 
					            {1, &IDebug::FinalizeDebug, "FinalizeDebug"},
 | 
				
			||||||
            {2, &IDebug::ListDevices, "ListDevices"},
 | 
					            {2, &IDebug::ListDevices, "ListDevices"},
 | 
				
			||||||
@@ -126,9 +126,9 @@ public:
 | 
				
			|||||||
            {201, &IDebug::SetAll, "SetAll"},
 | 
					            {201, &IDebug::SetAll, "SetAll"},
 | 
				
			||||||
            {202, &IDebug::FlushDebug, "FlushDebug"},
 | 
					            {202, &IDebug::FlushDebug, "FlushDebug"},
 | 
				
			||||||
            {203, &IDebug::BreakTag, "BreakTag"},
 | 
					            {203, &IDebug::BreakTag, "BreakTag"},
 | 
				
			||||||
            {204, nullptr, "ReadBackupData"},
 | 
					            {204, &IDebug::ReadBackupData, "ReadBackupData"},
 | 
				
			||||||
            {205, nullptr, "WriteBackupData"},
 | 
					            {205, &IDebug::WriteBackupData, "WriteBackupData"},
 | 
				
			||||||
            {206, nullptr, "WriteNtf"},
 | 
					            {206, &IDebug::WriteNtf, "WriteNtf"},
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        // clang-format on
 | 
					        // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -152,16 +152,10 @@ private:
 | 
				
			|||||||
    void CreateUserInterface(HLERequestContext& ctx) {
 | 
					    void CreateUserInterface(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_DEBUG(Service_NFP, "called");
 | 
					        LOG_DEBUG(Service_NFP, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (user_interface == nullptr) {
 | 
					 | 
				
			||||||
            user_interface = std::make_shared<IUser>(system);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					        rb.Push(ResultSuccess);
 | 
				
			||||||
        rb.PushIpcInterface<IUser>(user_interface);
 | 
					        rb.PushIpcInterface<IUser>(system);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::shared_ptr<IUser> user_interface;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ISystemManager final : public ServiceFramework<ISystemManager> {
 | 
					class ISystemManager final : public ServiceFramework<ISystemManager> {
 | 
				
			||||||
@@ -180,16 +174,10 @@ private:
 | 
				
			|||||||
    void CreateSystemInterface(HLERequestContext& ctx) {
 | 
					    void CreateSystemInterface(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_DEBUG(Service_NFP, "called");
 | 
					        LOG_DEBUG(Service_NFP, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (system_interface == nullptr) {
 | 
					 | 
				
			||||||
            system_interface = std::make_shared<ISystem>(system);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					        rb.Push(ResultSuccess);
 | 
				
			||||||
        rb.PushIpcInterface<ISystem>(system_interface);
 | 
					        rb.PushIpcInterface<ISystem>(system);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::shared_ptr<ISystem> system_interface;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IDebugManager final : public ServiceFramework<IDebugManager> {
 | 
					class IDebugManager final : public ServiceFramework<IDebugManager> {
 | 
				
			||||||
@@ -208,16 +196,10 @@ private:
 | 
				
			|||||||
    void CreateDebugInterface(HLERequestContext& ctx) {
 | 
					    void CreateDebugInterface(HLERequestContext& ctx) {
 | 
				
			||||||
        LOG_DEBUG(Service_NFP, "called");
 | 
					        LOG_DEBUG(Service_NFP, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (system_interface == nullptr) {
 | 
					 | 
				
			||||||
            system_interface = std::make_shared<IDebug>(system);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					        rb.Push(ResultSuccess);
 | 
				
			||||||
        rb.PushIpcInterface<IDebug>(system_interface);
 | 
					        rb.PushIpcInterface<IDebug>(system);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::shared_ptr<IDebug> system_interface;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LoopProcess(Core::System& system) {
 | 
					void LoopProcess(Core::System& system) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,120 +0,0 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
					 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <span>
 | 
					 | 
				
			||||||
#include <vector>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "common/common_types.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/kernel_helpers.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/nfp/nfp_types.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/service.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Kernel {
 | 
					 | 
				
			||||||
class KEvent;
 | 
					 | 
				
			||||||
class KReadableEvent;
 | 
					 | 
				
			||||||
} // namespace Kernel
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Core {
 | 
					 | 
				
			||||||
class System;
 | 
					 | 
				
			||||||
} // namespace Core
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Core::HID {
 | 
					 | 
				
			||||||
class EmulatedController;
 | 
					 | 
				
			||||||
enum class ControllerTriggerType;
 | 
					 | 
				
			||||||
enum class NpadIdType : u32;
 | 
					 | 
				
			||||||
} // namespace Core::HID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Service::NFP {
 | 
					 | 
				
			||||||
class NfpDevice {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    NfpDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
 | 
					 | 
				
			||||||
              KernelHelpers::ServiceContext& service_context_,
 | 
					 | 
				
			||||||
              Kernel::KEvent* availability_change_event_);
 | 
					 | 
				
			||||||
    ~NfpDevice();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void Initialize();
 | 
					 | 
				
			||||||
    void Finalize();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result StartDetection(TagProtocol allowed_protocol);
 | 
					 | 
				
			||||||
    Result StopDetection();
 | 
					 | 
				
			||||||
    Result Mount(MountTarget mount_target);
 | 
					 | 
				
			||||||
    Result Unmount();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result Flush();
 | 
					 | 
				
			||||||
    Result FlushDebug();
 | 
					 | 
				
			||||||
    Result FlushWithBreak(BreakType break_type);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result GetTagInfo(TagInfo& tag_info) const;
 | 
					 | 
				
			||||||
    Result GetCommonInfo(CommonInfo& common_info) const;
 | 
					 | 
				
			||||||
    Result GetModelInfo(ModelInfo& model_info) const;
 | 
					 | 
				
			||||||
    Result GetRegisterInfo(RegisterInfo& register_info) const;
 | 
					 | 
				
			||||||
    Result GetRegisterInfoPrivate(RegisterInfoPrivate& register_info) const;
 | 
					 | 
				
			||||||
    Result GetAdminInfo(AdminInfo& admin_info) const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result DeleteRegisterInfo();
 | 
					 | 
				
			||||||
    Result SetRegisterInfoPrivate(const AmiiboName& amiibo_name);
 | 
					 | 
				
			||||||
    Result RestoreAmiibo();
 | 
					 | 
				
			||||||
    Result Format();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result OpenApplicationArea(u32 access_id);
 | 
					 | 
				
			||||||
    Result GetApplicationAreaId(u32& application_area_id) const;
 | 
					 | 
				
			||||||
    Result GetApplicationArea(std::vector<u8>& data) const;
 | 
					 | 
				
			||||||
    Result SetApplicationArea(std::span<const u8> data);
 | 
					 | 
				
			||||||
    Result CreateApplicationArea(u32 access_id, std::span<const u8> data);
 | 
					 | 
				
			||||||
    Result RecreateApplicationArea(u32 access_id, std::span<const u8> data);
 | 
					 | 
				
			||||||
    Result DeleteApplicationArea();
 | 
					 | 
				
			||||||
    Result ExistApplicationArea(bool& has_application_area);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Result GetAll(NfpData& data) const;
 | 
					 | 
				
			||||||
    Result SetAll(const NfpData& data);
 | 
					 | 
				
			||||||
    Result BreakTag(BreakType break_type);
 | 
					 | 
				
			||||||
    Result ReadBackupData();
 | 
					 | 
				
			||||||
    Result WriteBackupData();
 | 
					 | 
				
			||||||
    Result WriteNtf();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    u64 GetHandle() const;
 | 
					 | 
				
			||||||
    u32 GetApplicationAreaSize() const;
 | 
					 | 
				
			||||||
    DeviceState GetCurrentState() const;
 | 
					 | 
				
			||||||
    Core::HID::NpadIdType GetNpadId() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Kernel::KReadableEvent& GetActivateEvent() const;
 | 
					 | 
				
			||||||
    Kernel::KReadableEvent& GetDeactivateEvent() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    void NpadUpdate(Core::HID::ControllerTriggerType type);
 | 
					 | 
				
			||||||
    bool LoadAmiibo(std::span<const u8> data);
 | 
					 | 
				
			||||||
    void CloseAmiibo();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    AmiiboName GetAmiiboName(const AmiiboSettings& settings) const;
 | 
					 | 
				
			||||||
    void SetAmiiboName(AmiiboSettings& settings, const AmiiboName& amiibo_name);
 | 
					 | 
				
			||||||
    AmiiboDate GetAmiiboDate(s64 posix_time) const;
 | 
					 | 
				
			||||||
    u64 RemoveVersionByte(u64 application_id) const;
 | 
					 | 
				
			||||||
    void UpdateSettingsCrc();
 | 
					 | 
				
			||||||
    void UpdateRegisterInfoCrc();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool is_controller_set{};
 | 
					 | 
				
			||||||
    int callback_key;
 | 
					 | 
				
			||||||
    const Core::HID::NpadIdType npad_id;
 | 
					 | 
				
			||||||
    Core::System& system;
 | 
					 | 
				
			||||||
    Core::HID::EmulatedController* npad_device = nullptr;
 | 
					 | 
				
			||||||
    KernelHelpers::ServiceContext& service_context;
 | 
					 | 
				
			||||||
    Kernel::KEvent* activate_event = nullptr;
 | 
					 | 
				
			||||||
    Kernel::KEvent* deactivate_event = nullptr;
 | 
					 | 
				
			||||||
    Kernel::KEvent* availability_change_event = nullptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool is_initalized{};
 | 
					 | 
				
			||||||
    bool is_data_moddified{};
 | 
					 | 
				
			||||||
    bool is_app_area_open{};
 | 
					 | 
				
			||||||
    bool is_plain_amiibo{};
 | 
					 | 
				
			||||||
    TagProtocol allowed_protocols{};
 | 
					 | 
				
			||||||
    s64 current_posix_time{};
 | 
					 | 
				
			||||||
    MountTarget mount_target{MountTarget::None};
 | 
					 | 
				
			||||||
    DeviceState device_state{DeviceState::Unavailable};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    NTAG215File tag_data{};
 | 
					 | 
				
			||||||
    EncryptedNTAG215File encrypted_tag_data{};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::NFP
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,32 +1,23 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <array>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					 | 
				
			||||||
#include <optional>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "core/hle/service/kernel_helpers.h"
 | 
					#include "core/hle/service/kernel_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_interface.h"
 | 
				
			||||||
#include "core/hle/service/service.h"
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP {
 | 
					namespace Service::NFP {
 | 
				
			||||||
class NfpDevice;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Interface : public ServiceFramework<Interface> {
 | 
					class Interface : public NFC::NfcInterface {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit Interface(Core::System& system_, const char* name);
 | 
					    explicit Interface(Core::System& system_, const char* name);
 | 
				
			||||||
    ~Interface() override;
 | 
					    ~Interface() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Initialize(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void InitializeSystem(HLERequestContext& ctx);
 | 
					    void InitializeSystem(HLERequestContext& ctx);
 | 
				
			||||||
    void InitializeDebug(HLERequestContext& ctx);
 | 
					    void InitializeDebug(HLERequestContext& ctx);
 | 
				
			||||||
    void Finalize(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void FinalizeSystem(HLERequestContext& ctx);
 | 
					    void FinalizeSystem(HLERequestContext& ctx);
 | 
				
			||||||
    void FinalizeDebug(HLERequestContext& ctx);
 | 
					    void FinalizeDebug(HLERequestContext& ctx);
 | 
				
			||||||
    void ListDevices(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void StartDetection(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void StopDetection(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void Mount(HLERequestContext& ctx);
 | 
					    void Mount(HLERequestContext& ctx);
 | 
				
			||||||
    void Unmount(HLERequestContext& ctx);
 | 
					    void Unmount(HLERequestContext& ctx);
 | 
				
			||||||
    void OpenApplicationArea(HLERequestContext& ctx);
 | 
					    void OpenApplicationArea(HLERequestContext& ctx);
 | 
				
			||||||
@@ -35,17 +26,10 @@ public:
 | 
				
			|||||||
    void Flush(HLERequestContext& ctx);
 | 
					    void Flush(HLERequestContext& ctx);
 | 
				
			||||||
    void Restore(HLERequestContext& ctx);
 | 
					    void Restore(HLERequestContext& ctx);
 | 
				
			||||||
    void CreateApplicationArea(HLERequestContext& ctx);
 | 
					    void CreateApplicationArea(HLERequestContext& ctx);
 | 
				
			||||||
    void GetTagInfo(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetRegisterInfo(HLERequestContext& ctx);
 | 
					    void GetRegisterInfo(HLERequestContext& ctx);
 | 
				
			||||||
    void GetCommonInfo(HLERequestContext& ctx);
 | 
					    void GetCommonInfo(HLERequestContext& ctx);
 | 
				
			||||||
    void GetModelInfo(HLERequestContext& ctx);
 | 
					    void GetModelInfo(HLERequestContext& ctx);
 | 
				
			||||||
    void AttachActivateEvent(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void AttachDeactivateEvent(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetState(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetDeviceState(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetNpadId(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void GetApplicationAreaSize(HLERequestContext& ctx);
 | 
					    void GetApplicationAreaSize(HLERequestContext& ctx);
 | 
				
			||||||
    void AttachAvailabilityChangeEvent(HLERequestContext& ctx);
 | 
					 | 
				
			||||||
    void RecreateApplicationArea(HLERequestContext& ctx);
 | 
					    void RecreateApplicationArea(HLERequestContext& ctx);
 | 
				
			||||||
    void Format(HLERequestContext& ctx);
 | 
					    void Format(HLERequestContext& ctx);
 | 
				
			||||||
    void GetAdminInfo(HLERequestContext& ctx);
 | 
					    void GetAdminInfo(HLERequestContext& ctx);
 | 
				
			||||||
@@ -61,21 +45,6 @@ public:
 | 
				
			|||||||
    void ReadBackupData(HLERequestContext& ctx);
 | 
					    void ReadBackupData(HLERequestContext& ctx);
 | 
				
			||||||
    void WriteBackupData(HLERequestContext& ctx);
 | 
					    void WriteBackupData(HLERequestContext& ctx);
 | 
				
			||||||
    void WriteNtf(HLERequestContext& ctx);
 | 
					    void WriteNtf(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    enum class State : u32 {
 | 
					 | 
				
			||||||
        NonInitialized,
 | 
					 | 
				
			||||||
        Initialized,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::optional<std::shared_ptr<NfpDevice>> GetNfpDevice(u64 handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    KernelHelpers::ServiceContext service_context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::array<std::shared_ptr<NfpDevice>, 10> devices{};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    State state{State::NonInitialized};
 | 
					 | 
				
			||||||
    Kernel::KEvent* availability_change_event;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::NFP
 | 
					} // namespace Service::NFP
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
					// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | 
				
			||||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7,18 +7,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP {
 | 
					namespace Service::NFP {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr Result DeviceNotFound(ErrorModule::NFP, 64);
 | 
					constexpr Result ResultDeviceNotFound(ErrorModule::NFP, 64);
 | 
				
			||||||
constexpr Result InvalidArgument(ErrorModule::NFP, 65);
 | 
					constexpr Result ResultInvalidArgument(ErrorModule::NFP, 65);
 | 
				
			||||||
constexpr Result WrongApplicationAreaSize(ErrorModule::NFP, 68);
 | 
					constexpr Result ResultWrongApplicationAreaSize(ErrorModule::NFP, 68);
 | 
				
			||||||
constexpr Result WrongDeviceState(ErrorModule::NFP, 73);
 | 
					constexpr Result ResultWrongDeviceState(ErrorModule::NFP, 73);
 | 
				
			||||||
constexpr Result NfcDisabled(ErrorModule::NFP, 80);
 | 
					constexpr Result ResultUnknown74(ErrorModule::NFC, 74);
 | 
				
			||||||
constexpr Result WriteAmiiboFailed(ErrorModule::NFP, 88);
 | 
					constexpr Result ResultNfcDisabled(ErrorModule::NFP, 80);
 | 
				
			||||||
constexpr Result TagRemoved(ErrorModule::NFP, 97);
 | 
					constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFP, 88);
 | 
				
			||||||
constexpr Result RegistrationIsNotInitialized(ErrorModule::NFP, 120);
 | 
					constexpr Result ResultTagRemoved(ErrorModule::NFP, 97);
 | 
				
			||||||
constexpr Result ApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
 | 
					constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFP, 120);
 | 
				
			||||||
constexpr Result CorruptedData(ErrorModule::NFP, 144);
 | 
					constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
 | 
				
			||||||
constexpr Result WrongApplicationAreaId(ErrorModule::NFP, 152);
 | 
					constexpr Result ResultCorruptedData(ErrorModule::NFP, 144);
 | 
				
			||||||
constexpr Result ApplicationAreaExist(ErrorModule::NFP, 168);
 | 
					constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFP, 152);
 | 
				
			||||||
constexpr Result NotAnAmiibo(ErrorModule::NFP, 178);
 | 
					constexpr Result ResultApplicationAreaExist(ErrorModule::NFP, 168);
 | 
				
			||||||
 | 
					constexpr Result ResultNotAnAmiibo(ErrorModule::NFP, 178);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::NFP
 | 
					} // namespace Service::NFP
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,32 +7,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "common/swap.h"
 | 
					#include "common/swap.h"
 | 
				
			||||||
#include "core/hle/service/mii/types.h"
 | 
					#include "core/hle/service/mii/types.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/nfc/nfc_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP {
 | 
					namespace Service::NFP {
 | 
				
			||||||
static constexpr std::size_t amiibo_name_length = 0xA;
 | 
					static constexpr std::size_t amiibo_name_length = 0xA;
 | 
				
			||||||
static constexpr std::size_t application_id_version_offset = 0x1c;
 | 
					static constexpr std::size_t application_id_version_offset = 0x1c;
 | 
				
			||||||
static constexpr std::size_t counter_limit = 0xffff;
 | 
					static constexpr std::size_t counter_limit = 0xffff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class ServiceType : u32 {
 | 
					// This is nn::nfp::ModelType
 | 
				
			||||||
    User,
 | 
					 | 
				
			||||||
    Debug,
 | 
					 | 
				
			||||||
    System,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum class DeviceState : u32 {
 | 
					 | 
				
			||||||
    Initialized,
 | 
					 | 
				
			||||||
    SearchingForTag,
 | 
					 | 
				
			||||||
    TagFound,
 | 
					 | 
				
			||||||
    TagRemoved,
 | 
					 | 
				
			||||||
    TagMounted,
 | 
					 | 
				
			||||||
    Unavailable,
 | 
					 | 
				
			||||||
    Finalized,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum class ModelType : u32 {
 | 
					enum class ModelType : u32 {
 | 
				
			||||||
    Amiibo,
 | 
					    Amiibo,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfp::MountTarget
 | 
				
			||||||
enum class MountTarget : u32 {
 | 
					enum class MountTarget : u32 {
 | 
				
			||||||
    None,
 | 
					    None,
 | 
				
			||||||
    Rom,
 | 
					    Rom,
 | 
				
			||||||
@@ -72,35 +59,6 @@ enum class AmiiboSeries : u8 {
 | 
				
			|||||||
    Diablo,
 | 
					    Diablo,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class TagType : u32 {
 | 
					 | 
				
			||||||
    None,
 | 
					 | 
				
			||||||
    Type1, // ISO14443A RW 96-2k bytes 106kbit/s
 | 
					 | 
				
			||||||
    Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
 | 
					 | 
				
			||||||
    Type3, // Sony Felica RW/RO 2k bytes 212kbit/s
 | 
					 | 
				
			||||||
    Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
 | 
					 | 
				
			||||||
    Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum class PackedTagType : u8 {
 | 
					 | 
				
			||||||
    None,
 | 
					 | 
				
			||||||
    Type1, // ISO14443A RW 96-2k bytes 106kbit/s
 | 
					 | 
				
			||||||
    Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
 | 
					 | 
				
			||||||
    Type3, // Sony Felica RW/RO 2k bytes 212kbit/s
 | 
					 | 
				
			||||||
    Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
 | 
					 | 
				
			||||||
    Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Verify this enum. It might be completely wrong default protocol is 0x48
 | 
					 | 
				
			||||||
enum class TagProtocol : u32 {
 | 
					 | 
				
			||||||
    None,
 | 
					 | 
				
			||||||
    TypeA = 1U << 0, // ISO14443A
 | 
					 | 
				
			||||||
    TypeB = 1U << 1, // ISO14443B
 | 
					 | 
				
			||||||
    TypeF = 1U << 2, // Sony Felica
 | 
					 | 
				
			||||||
    Unknown1 = 1U << 3,
 | 
					 | 
				
			||||||
    Unknown2 = 1U << 5,
 | 
					 | 
				
			||||||
    All = 0xFFFFFFFFU,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum class AppAreaVersion : u8 {
 | 
					enum class AppAreaVersion : u8 {
 | 
				
			||||||
    Nintendo3DS = 0,
 | 
					    Nintendo3DS = 0,
 | 
				
			||||||
    NintendoWiiU = 1,
 | 
					    NintendoWiiU = 1,
 | 
				
			||||||
@@ -115,6 +73,11 @@ enum class BreakType : u32 {
 | 
				
			|||||||
    Unknown2,
 | 
					    Unknown2,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class WriteType : u32 {
 | 
				
			||||||
 | 
					    Unknown0,
 | 
				
			||||||
 | 
					    Unknown1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class CabinetMode : u8 {
 | 
					enum class CabinetMode : u8 {
 | 
				
			||||||
    StartNicknameAndOwnerSettings,
 | 
					    StartNicknameAndOwnerSettings,
 | 
				
			||||||
    StartGameDataEraser,
 | 
					    StartGameDataEraser,
 | 
				
			||||||
@@ -122,27 +85,16 @@ enum class CabinetMode : u8 {
 | 
				
			|||||||
    StartFormatter,
 | 
					    StartFormatter,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class MifareCmd : u8 {
 | 
					 | 
				
			||||||
    AuthA = 0x60,
 | 
					 | 
				
			||||||
    AuthB = 0x61,
 | 
					 | 
				
			||||||
    Read = 0x30,
 | 
					 | 
				
			||||||
    Write = 0xA0,
 | 
					 | 
				
			||||||
    Transfer = 0xB0,
 | 
					 | 
				
			||||||
    Decrement = 0xC0,
 | 
					 | 
				
			||||||
    Increment = 0xC1,
 | 
					 | 
				
			||||||
    Store = 0xC2
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using UniqueSerialNumber = std::array<u8, 7>;
 | 
					 | 
				
			||||||
using LockBytes = std::array<u8, 2>;
 | 
					using LockBytes = std::array<u8, 2>;
 | 
				
			||||||
using HashData = std::array<u8, 0x20>;
 | 
					using HashData = std::array<u8, 0x20>;
 | 
				
			||||||
using ApplicationArea = std::array<u8, 0xD8>;
 | 
					using ApplicationArea = std::array<u8, 0xD8>;
 | 
				
			||||||
using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>;
 | 
					using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>;
 | 
				
			||||||
using DataBlock = std::array<u8, 0x10>;
 | 
					
 | 
				
			||||||
using KeyData = std::array<u8, 0x6>;
 | 
					// This is nn::nfp::TagInfo
 | 
				
			||||||
 | 
					using TagInfo = NFC::TagInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TagUuid {
 | 
					struct TagUuid {
 | 
				
			||||||
    UniqueSerialNumber uid;
 | 
					    NFC::UniqueSerialNumber uid;
 | 
				
			||||||
    u8 nintendo_id;
 | 
					    u8 nintendo_id;
 | 
				
			||||||
    LockBytes lock_bytes;
 | 
					    LockBytes lock_bytes;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -243,7 +195,7 @@ struct AmiiboModelInfo {
 | 
				
			|||||||
    AmiiboType amiibo_type;
 | 
					    AmiiboType amiibo_type;
 | 
				
			||||||
    u16_be model_number;
 | 
					    u16_be model_number;
 | 
				
			||||||
    AmiiboSeries series;
 | 
					    AmiiboSeries series;
 | 
				
			||||||
    PackedTagType tag_type;
 | 
					    NFC::PackedTagType tag_type;
 | 
				
			||||||
    INSERT_PADDING_BYTES(0x4); // Unknown
 | 
					    INSERT_PADDING_BYTES(0x4); // Unknown
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static_assert(sizeof(AmiiboModelInfo) == 0xC, "AmiiboModelInfo is an invalid size");
 | 
					static_assert(sizeof(AmiiboModelInfo) == 0xC, "AmiiboModelInfo is an invalid size");
 | 
				
			||||||
@@ -298,7 +250,7 @@ struct NTAG215File {
 | 
				
			|||||||
    u32_be register_info_crc;
 | 
					    u32_be register_info_crc;
 | 
				
			||||||
    ApplicationArea application_area; // Encrypted Game data
 | 
					    ApplicationArea application_area; // Encrypted Game data
 | 
				
			||||||
    HashData hmac_tag;                // Hash
 | 
					    HashData hmac_tag;                // Hash
 | 
				
			||||||
    UniqueSerialNumber uid;           // Unique serial number
 | 
					    NFC::UniqueSerialNumber uid;      // Unique serial number
 | 
				
			||||||
    u8 nintendo_id;                   // Tag UUID
 | 
					    u8 nintendo_id;                   // Tag UUID
 | 
				
			||||||
    AmiiboModelInfo model_info;
 | 
					    AmiiboModelInfo model_info;
 | 
				
			||||||
    HashData keygen_salt;     // Salt
 | 
					    HashData keygen_salt;     // Salt
 | 
				
			||||||
@@ -326,17 +278,7 @@ static_assert(sizeof(EncryptedNTAG215File) == sizeof(NTAG215File),
 | 
				
			|||||||
static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>,
 | 
					static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>,
 | 
				
			||||||
              "EncryptedNTAG215File must be trivially copyable.");
 | 
					              "EncryptedNTAG215File must be trivially copyable.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TagInfo {
 | 
					// This is nn::nfp::CommonInfo
 | 
				
			||||||
    UniqueSerialNumber uuid;
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x3);
 | 
					 | 
				
			||||||
    u8 uuid_length;
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x15);
 | 
					 | 
				
			||||||
    TagProtocol protocol;
 | 
					 | 
				
			||||||
    TagType tag_type;
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x30);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct CommonInfo {
 | 
					struct CommonInfo {
 | 
				
			||||||
    WriteDate last_write_date;
 | 
					    WriteDate last_write_date;
 | 
				
			||||||
    u16 write_counter;
 | 
					    u16 write_counter;
 | 
				
			||||||
@@ -347,6 +289,7 @@ struct CommonInfo {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
 | 
					static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfp::ModelInfo
 | 
				
			||||||
struct ModelInfo {
 | 
					struct ModelInfo {
 | 
				
			||||||
    u16 character_id;
 | 
					    u16 character_id;
 | 
				
			||||||
    u8 character_variant;
 | 
					    u8 character_variant;
 | 
				
			||||||
@@ -357,6 +300,7 @@ struct ModelInfo {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
 | 
					static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfp::RegisterInfo
 | 
				
			||||||
struct RegisterInfo {
 | 
					struct RegisterInfo {
 | 
				
			||||||
    Service::Mii::CharInfo mii_char_info;
 | 
					    Service::Mii::CharInfo mii_char_info;
 | 
				
			||||||
    WriteDate creation_date;
 | 
					    WriteDate creation_date;
 | 
				
			||||||
@@ -366,6 +310,7 @@ struct RegisterInfo {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
 | 
					static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfp::RegisterInfoPrivate
 | 
				
			||||||
struct RegisterInfoPrivate {
 | 
					struct RegisterInfoPrivate {
 | 
				
			||||||
    Service::Mii::MiiStoreData mii_store_data;
 | 
					    Service::Mii::MiiStoreData mii_store_data;
 | 
				
			||||||
    WriteDate creation_date;
 | 
					    WriteDate creation_date;
 | 
				
			||||||
@@ -375,12 +320,13 @@ struct RegisterInfoPrivate {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
static_assert(sizeof(RegisterInfoPrivate) == 0x100, "RegisterInfoPrivate is an invalid size");
 | 
					static_assert(sizeof(RegisterInfoPrivate) == 0x100, "RegisterInfoPrivate is an invalid size");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is nn::nfp::AdminInfo
 | 
				
			||||||
struct AdminInfo {
 | 
					struct AdminInfo {
 | 
				
			||||||
    u64 application_id;
 | 
					    u64 application_id;
 | 
				
			||||||
    u32 application_area_id;
 | 
					    u32 application_area_id;
 | 
				
			||||||
    u16 crc_change_counter;
 | 
					    u16 crc_change_counter;
 | 
				
			||||||
    u8 flags;
 | 
					    u8 flags;
 | 
				
			||||||
    PackedTagType tag_type;
 | 
					    NFC::PackedTagType tag_type;
 | 
				
			||||||
    AppAreaVersion app_area_version;
 | 
					    AppAreaVersion app_area_version;
 | 
				
			||||||
    INSERT_PADDING_BYTES(0x7);
 | 
					    INSERT_PADDING_BYTES(0x7);
 | 
				
			||||||
    INSERT_PADDING_BYTES(0x28);
 | 
					    INSERT_PADDING_BYTES(0x28);
 | 
				
			||||||
@@ -411,7 +357,7 @@ struct NfpData {
 | 
				
			|||||||
    u32 access_id;
 | 
					    u32 access_id;
 | 
				
			||||||
    u16 settings_crc_counter;
 | 
					    u16 settings_crc_counter;
 | 
				
			||||||
    u8 font_region;
 | 
					    u8 font_region;
 | 
				
			||||||
    PackedTagType tag_type;
 | 
					    NFC::PackedTagType tag_type;
 | 
				
			||||||
    AppAreaVersion console_type;
 | 
					    AppAreaVersion console_type;
 | 
				
			||||||
    u8 application_id_byte;
 | 
					    u8 application_id_byte;
 | 
				
			||||||
    INSERT_PADDING_BYTES(0x2E);
 | 
					    INSERT_PADDING_BYTES(0x2E);
 | 
				
			||||||
@@ -420,37 +366,4 @@ struct NfpData {
 | 
				
			|||||||
static_assert(sizeof(NfpData) == 0x298, "NfpData is an invalid size");
 | 
					static_assert(sizeof(NfpData) == 0x298, "NfpData is an invalid size");
 | 
				
			||||||
#pragma pack()
 | 
					#pragma pack()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SectorKey {
 | 
					 | 
				
			||||||
    MifareCmd command;
 | 
					 | 
				
			||||||
    u8 unknown; // Usually 1
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x6);
 | 
					 | 
				
			||||||
    KeyData sector_key;
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x2);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct MifareReadBlockParameter {
 | 
					 | 
				
			||||||
    u8 sector_number;
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x7);
 | 
					 | 
				
			||||||
    SectorKey sector_key;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static_assert(sizeof(MifareReadBlockParameter) == 0x18,
 | 
					 | 
				
			||||||
              "MifareReadBlockParameter is an invalid size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct MifareReadBlockData {
 | 
					 | 
				
			||||||
    DataBlock data;
 | 
					 | 
				
			||||||
    u8 sector_number;
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x7);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct MifareWriteBlockParameter {
 | 
					 | 
				
			||||||
    DataBlock data;
 | 
					 | 
				
			||||||
    u8 sector_number;
 | 
					 | 
				
			||||||
    INSERT_PADDING_BYTES(0x7);
 | 
					 | 
				
			||||||
    SectorKey sector_key;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static_assert(sizeof(MifareWriteBlockParameter) == 0x28,
 | 
					 | 
				
			||||||
              "MifareWriteBlockParameter is an invalid size");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::NFP
 | 
					} // namespace Service::NFP
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,7 +142,8 @@ template <typename Self>
 | 
				
			|||||||
class ServiceFramework : public ServiceFrameworkBase {
 | 
					class ServiceFramework : public ServiceFrameworkBase {
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    /// Contains information about a request type which is handled by the service.
 | 
					    /// Contains information about a request type which is handled by the service.
 | 
				
			||||||
    struct FunctionInfo : FunctionInfoBase {
 | 
					    template <typename T>
 | 
				
			||||||
 | 
					    struct FunctionInfoTyped : FunctionInfoBase {
 | 
				
			||||||
        // TODO(yuriks): This function could be constexpr, but clang is the only compiler that
 | 
					        // TODO(yuriks): This function could be constexpr, but clang is the only compiler that
 | 
				
			||||||
        // doesn't emit an ICE or a wrong diagnostic because of the static_cast.
 | 
					        // doesn't emit an ICE or a wrong diagnostic because of the static_cast.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -155,12 +156,13 @@ protected:
 | 
				
			|||||||
         *     the request
 | 
					         *     the request
 | 
				
			||||||
         * @param name_ human-friendly name for the request. Used mostly for logging purposes.
 | 
					         * @param name_ human-friendly name for the request. Used mostly for logging purposes.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        FunctionInfo(u32 expected_header_, HandlerFnP<Self> handler_callback_, const char* name_)
 | 
					        FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_)
 | 
				
			||||||
            : FunctionInfoBase{
 | 
					            : FunctionInfoBase{
 | 
				
			||||||
                  expected_header_,
 | 
					                  expected_header_,
 | 
				
			||||||
                  // Type-erase member function pointer by casting it down to the base class.
 | 
					                  // Type-erase member function pointer by casting it down to the base class.
 | 
				
			||||||
                  static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {}
 | 
					                  static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {}
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					    using FunctionInfo = FunctionInfoTyped<Self>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Initializes the handler with no functions installed.
 | 
					     * Initializes the handler with no functions installed.
 | 
				
			||||||
@@ -175,8 +177,8 @@ protected:
 | 
				
			|||||||
        : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {}
 | 
					        : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Registers handlers in the service.
 | 
					    /// Registers handlers in the service.
 | 
				
			||||||
    template <std::size_t N>
 | 
					    template <typename T = Self, std::size_t N>
 | 
				
			||||||
    void RegisterHandlers(const FunctionInfo (&functions)[N]) {
 | 
					    void RegisterHandlers(const FunctionInfoTyped<T> (&functions)[N]) {
 | 
				
			||||||
        RegisterHandlers(functions, N);
 | 
					        RegisterHandlers(functions, N);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -184,13 +186,14 @@ protected:
 | 
				
			|||||||
     * Registers handlers in the service. Usually prefer using the other RegisterHandlers
 | 
					     * Registers handlers in the service. Usually prefer using the other RegisterHandlers
 | 
				
			||||||
     * overload in order to avoid needing to specify the array size.
 | 
					     * overload in order to avoid needing to specify the array size.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void RegisterHandlers(const FunctionInfo* functions, std::size_t n) {
 | 
					    template <typename T = Self>
 | 
				
			||||||
 | 
					    void RegisterHandlers(const FunctionInfoTyped<T>* functions, std::size_t n) {
 | 
				
			||||||
        RegisterHandlersBase(functions, n);
 | 
					        RegisterHandlersBase(functions, n);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Registers handlers in the service.
 | 
					    /// Registers handlers in the service.
 | 
				
			||||||
    template <std::size_t N>
 | 
					    template <typename T = Self, std::size_t N>
 | 
				
			||||||
    void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) {
 | 
					    void RegisterHandlersTipc(const FunctionInfoTyped<T> (&functions)[N]) {
 | 
				
			||||||
        RegisterHandlersTipc(functions, N);
 | 
					        RegisterHandlersTipc(functions, N);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -198,7 +201,8 @@ protected:
 | 
				
			|||||||
     * Registers handlers in the service. Usually prefer using the other RegisterHandlers
 | 
					     * Registers handlers in the service. Usually prefer using the other RegisterHandlers
 | 
				
			||||||
     * overload in order to avoid needing to specify the array size.
 | 
					     * overload in order to avoid needing to specify the array size.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) {
 | 
					    template <typename T = Self>
 | 
				
			||||||
 | 
					    void RegisterHandlersTipc(const FunctionInfoTyped<T>* functions, std::size_t n) {
 | 
				
			||||||
        RegisterHandlersBaseTipc(functions, n);
 | 
					        RegisterHandlersBaseTipc(functions, n);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "common/assert.h"
 | 
					#include "common/assert.h"
 | 
				
			||||||
#include "common/string_util.h"
 | 
					#include "common/string_util.h"
 | 
				
			||||||
#include "core/hle/service/nfp/nfp_device.h"
 | 
					#include "core/hle/service/nfc/common/device.h"
 | 
				
			||||||
#include "core/hle/service/nfp/nfp_result.h"
 | 
					#include "core/hle/service/nfp/nfp_result.h"
 | 
				
			||||||
#include "input_common/drivers/virtual_amiibo.h"
 | 
					#include "input_common/drivers/virtual_amiibo.h"
 | 
				
			||||||
#include "input_common/main.h"
 | 
					#include "input_common/main.h"
 | 
				
			||||||
@@ -22,7 +22,7 @@
 | 
				
			|||||||
QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent,
 | 
					QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent,
 | 
				
			||||||
                                               Core::Frontend::CabinetParameters parameters_,
 | 
					                                               Core::Frontend::CabinetParameters parameters_,
 | 
				
			||||||
                                               InputCommon::InputSubsystem* input_subsystem_,
 | 
					                                               InputCommon::InputSubsystem* input_subsystem_,
 | 
				
			||||||
                                               std::shared_ptr<Service::NFP::NfpDevice> nfp_device_)
 | 
					                                               std::shared_ptr<Service::NFC::NfcDevice> nfp_device_)
 | 
				
			||||||
    : QDialog(parent), ui(std::make_unique<Ui::QtAmiiboSettingsDialog>()),
 | 
					    : QDialog(parent), ui(std::make_unique<Ui::QtAmiiboSettingsDialog>()),
 | 
				
			||||||
      input_subsystem{input_subsystem_}, nfp_device{std::move(nfp_device_)},
 | 
					      input_subsystem{input_subsystem_}, nfp_device{std::move(nfp_device_)},
 | 
				
			||||||
      parameters(std::move(parameters_)) {
 | 
					      parameters(std::move(parameters_)) {
 | 
				
			||||||
@@ -52,11 +52,11 @@ void QtAmiiboSettingsDialog::LoadInfo() {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound &&
 | 
					    if (nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagFound &&
 | 
				
			||||||
        nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) {
 | 
					        nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagMounted) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    nfp_device->Mount(Service::NFP::MountTarget::All);
 | 
					    nfp_device->Mount(Service::NFP::ModelType::Amiibo, Service::NFP::MountTarget::All);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LoadAmiiboInfo();
 | 
					    LoadAmiiboInfo();
 | 
				
			||||||
    LoadAmiiboData();
 | 
					    LoadAmiiboData();
 | 
				
			||||||
@@ -261,7 +261,7 @@ void QtAmiiboSettings::Close() const {
 | 
				
			|||||||
void QtAmiiboSettings::ShowCabinetApplet(
 | 
					void QtAmiiboSettings::ShowCabinetApplet(
 | 
				
			||||||
    const Core::Frontend::CabinetCallback& callback_,
 | 
					    const Core::Frontend::CabinetCallback& callback_,
 | 
				
			||||||
    const Core::Frontend::CabinetParameters& parameters,
 | 
					    const Core::Frontend::CabinetParameters& parameters,
 | 
				
			||||||
    std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const {
 | 
					    std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const {
 | 
				
			||||||
    callback = std::move(callback_);
 | 
					    callback = std::move(callback_);
 | 
				
			||||||
    emit MainWindowShowAmiiboSettings(parameters, nfp_device);
 | 
					    emit MainWindowShowAmiiboSettings(parameters, nfp_device);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,9 +23,9 @@ namespace Ui {
 | 
				
			|||||||
class QtAmiiboSettingsDialog;
 | 
					class QtAmiiboSettingsDialog;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP {
 | 
					namespace Service::NFC {
 | 
				
			||||||
class NfpDevice;
 | 
					class NfcDevice;
 | 
				
			||||||
} // namespace Service::NFP
 | 
					} // namespace Service::NFC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QtAmiiboSettingsDialog final : public QDialog {
 | 
					class QtAmiiboSettingsDialog final : public QDialog {
 | 
				
			||||||
    Q_OBJECT
 | 
					    Q_OBJECT
 | 
				
			||||||
@@ -33,7 +33,7 @@ class QtAmiiboSettingsDialog final : public QDialog {
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit QtAmiiboSettingsDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_,
 | 
					    explicit QtAmiiboSettingsDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_,
 | 
				
			||||||
                                    InputCommon::InputSubsystem* input_subsystem_,
 | 
					                                    InputCommon::InputSubsystem* input_subsystem_,
 | 
				
			||||||
                                    std::shared_ptr<Service::NFP::NfpDevice> nfp_device_);
 | 
					                                    std::shared_ptr<Service::NFC::NfcDevice> nfp_device_);
 | 
				
			||||||
    ~QtAmiiboSettingsDialog() override;
 | 
					    ~QtAmiiboSettingsDialog() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int exec() override;
 | 
					    int exec() override;
 | 
				
			||||||
@@ -52,7 +52,7 @@ private:
 | 
				
			|||||||
    std::unique_ptr<Ui::QtAmiiboSettingsDialog> ui;
 | 
					    std::unique_ptr<Ui::QtAmiiboSettingsDialog> ui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    InputCommon::InputSubsystem* input_subsystem;
 | 
					    InputCommon::InputSubsystem* input_subsystem;
 | 
				
			||||||
    std::shared_ptr<Service::NFP::NfpDevice> nfp_device;
 | 
					    std::shared_ptr<Service::NFC::NfcDevice> nfp_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Parameters sent in from the backend HLE applet.
 | 
					    // Parameters sent in from the backend HLE applet.
 | 
				
			||||||
    Core::Frontend::CabinetParameters parameters;
 | 
					    Core::Frontend::CabinetParameters parameters;
 | 
				
			||||||
@@ -71,11 +71,11 @@ public:
 | 
				
			|||||||
    void Close() const override;
 | 
					    void Close() const override;
 | 
				
			||||||
    void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_,
 | 
					    void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_,
 | 
				
			||||||
                           const Core::Frontend::CabinetParameters& parameters,
 | 
					                           const Core::Frontend::CabinetParameters& parameters,
 | 
				
			||||||
                           std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override;
 | 
					                           std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
    void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters,
 | 
					    void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters,
 | 
				
			||||||
                                      std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const;
 | 
					                                      std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const;
 | 
				
			||||||
    void MainWindowRequestExit() const;
 | 
					    void MainWindowRequestExit() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -571,8 +571,8 @@ void GMainWindow::RegisterMetaTypes() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Cabinet Applet
 | 
					    // Cabinet Applet
 | 
				
			||||||
    qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters");
 | 
					    qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters");
 | 
				
			||||||
    qRegisterMetaType<std::shared_ptr<Service::NFP::NfpDevice>>(
 | 
					    qRegisterMetaType<std::shared_ptr<Service::NFC::NfcDevice>>(
 | 
				
			||||||
        "std::shared_ptr<Service::NFP::NfpDevice>");
 | 
					        "std::shared_ptr<Service::NFC::NfcDevice>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Controller Applet
 | 
					    // Controller Applet
 | 
				
			||||||
    qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
 | 
					    qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
 | 
				
			||||||
@@ -600,7 +600,7 @@ void GMainWindow::RegisterMetaTypes() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
 | 
					void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
 | 
				
			||||||
                                           std::shared_ptr<Service::NFP::NfpDevice> nfp_device) {
 | 
					                                           std::shared_ptr<Service::NFC::NfcDevice> nfp_device) {
 | 
				
			||||||
    cabinet_applet =
 | 
					    cabinet_applet =
 | 
				
			||||||
        new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device);
 | 
					        new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device);
 | 
				
			||||||
    SCOPE_EXIT({
 | 
					    SCOPE_EXIT({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,9 +93,9 @@ enum class SwkbdReplyType : u32;
 | 
				
			|||||||
enum class WebExitReason : u32;
 | 
					enum class WebExitReason : u32;
 | 
				
			||||||
} // namespace Service::AM::Applets
 | 
					} // namespace Service::AM::Applets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Service::NFP {
 | 
					namespace Service::NFC {
 | 
				
			||||||
class NfpDevice;
 | 
					class NfcDevice;
 | 
				
			||||||
} // namespace Service::NFP
 | 
					} // namespace Service::NFC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ui {
 | 
					namespace Ui {
 | 
				
			||||||
class MainWindow;
 | 
					class MainWindow;
 | 
				
			||||||
@@ -188,7 +188,7 @@ public slots:
 | 
				
			|||||||
    void OnExit();
 | 
					    void OnExit();
 | 
				
			||||||
    void OnSaveConfig();
 | 
					    void OnSaveConfig();
 | 
				
			||||||
    void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
 | 
					    void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
 | 
				
			||||||
                                  std::shared_ptr<Service::NFP::NfpDevice> nfp_device);
 | 
					                                  std::shared_ptr<Service::NFC::NfcDevice> nfp_device);
 | 
				
			||||||
    void AmiiboSettingsRequestExit();
 | 
					    void AmiiboSettingsRequestExit();
 | 
				
			||||||
    void ControllerSelectorReconfigureControllers(
 | 
					    void ControllerSelectorReconfigureControllers(
 | 
				
			||||||
        const Core::Frontend::ControllerParameters& parameters);
 | 
					        const Core::Frontend::ControllerParameters& parameters);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user