forked from eden-emu/eden
		
	service: nfc: Merge device interfaces and create the device manager
This commit is contained in:
		
							parent
							
								
									5e16fe4579
								
							
						
					
					
						commit
						94151097b9
					
				
					 32 changed files with 2086 additions and 2465 deletions
				
			
		|  | @ -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
 | ||||||
|  | @ -1,382 +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_interface.h" |  | ||||||
| #include "core/hle/service/nfc/nfc_device.h" |  | ||||||
| #include "core/hle/service/nfc/nfc_result.h" |  | ||||||
| 
 |  | ||||||
| namespace Service::NFC { |  | ||||||
| 
 |  | ||||||
| MFInterface::MFInterface(Core::System& system_, const char* name) |  | ||||||
|     : ServiceFramework{system_, name}, service_context{system_, service_name} { |  | ||||||
|     availability_change_event = service_context.CreateEvent("MFInterface: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); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| MFInterface ::~MFInterface() { |  | ||||||
|     availability_change_event->Close(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::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 MFInterface::GetState(HLERequestContext& ctx) { |  | ||||||
|     LOG_DEBUG(Service_NFC, "called"); |  | ||||||
| 
 |  | ||||||
|     IPC::ResponseBuilder rb{ctx, 3}; |  | ||||||
|     rb.Push(ResultSuccess); |  | ||||||
|     rb.PushEnum(state); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MFInterface::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 MFInterface::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 MFInterface::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>> MFInterface::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 MFInterface : public ServiceFramework<MFInterface> { |  | ||||||
| public: |  | ||||||
|     explicit MFInterface(Core::System& system_, const char* name); |  | ||||||
|     ~MFInterface(); |  | ||||||
| 
 |  | ||||||
|     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); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     enum class State : u32 { |  | ||||||
|         NonInitialized, |  | ||||||
|         Initialized, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     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
 |  | ||||||
							
								
								
									
										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
 | ||||||
|  | @ -6,7 +6,6 @@ | ||||||
| #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_interface.h" |  | ||||||
| #include "core/hle/service/nfc/nfc.h" | #include "core/hle/service/nfc/nfc.h" | ||||||
| #include "core/hle/service/nfc/nfc_interface.h" | #include "core/hle/service/nfc/nfc_interface.h" | ||||||
| #include "core/hle/service/server_manager.h" | #include "core/hle/service/server_manager.h" | ||||||
|  | @ -14,31 +13,31 @@ | ||||||
| 
 | 
 | ||||||
| namespace Service::NFC { | namespace Service::NFC { | ||||||
| 
 | 
 | ||||||
| class IUser final : public Interface { | class IUser final : public NfcInterface { | ||||||
| public: | public: | ||||||
|     explicit IUser(Core::System& system_) : Interface(system_, "NFC::IUser") { |     explicit IUser(Core::System& system_) : NfcInterface(system_, "NFC::IUser", BackendType::Nfc) { | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, &Interface::Initialize, "InitializeOld"}, |             {0, &NfcInterface::Initialize, "InitializeOld"}, | ||||||
|             {1, &Interface::Finalize, "FinalizeOld"}, |             {1, &NfcInterface::Finalize, "FinalizeOld"}, | ||||||
|             {2, &Interface::GetState, "GetStateOld"}, |             {2, &NfcInterface::GetState, "GetStateOld"}, | ||||||
|             {3, &Interface::IsNfcEnabled, "IsNfcEnabledOld"}, |             {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"}, | ||||||
|             {400, &Interface::Initialize, "Initialize"}, |             {400, &NfcInterface::Initialize, "Initialize"}, | ||||||
|             {401, &Interface::Finalize, "Finalize"}, |             {401, &NfcInterface::Finalize, "Finalize"}, | ||||||
|             {402, &Interface::GetState, "GetState"}, |             {402, &NfcInterface::GetState, "GetState"}, | ||||||
|             {403, &Interface::IsNfcEnabled, "IsNfcEnabled"}, |             {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"}, | ||||||
|             {404, &Interface::ListDevices, "ListDevices"}, |             {404, &NfcInterface::ListDevices, "ListDevices"}, | ||||||
|             {405, &Interface::GetDeviceState, "GetDeviceState"}, |             {405, &NfcInterface::GetDeviceState, "GetDeviceState"}, | ||||||
|             {406, &Interface::GetNpadId, "GetNpadId"}, |             {406, &NfcInterface::GetNpadId, "GetNpadId"}, | ||||||
|             {407, &Interface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, |             {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, | ||||||
|             {408, &Interface::StartDetection, "StartDetection"}, |             {408, &NfcInterface::StartDetection, "StartDetection"}, | ||||||
|             {409, &Interface::StopDetection, "StopDetection"}, |             {409, &NfcInterface::StopDetection, "StopDetection"}, | ||||||
|             {410, &Interface::GetTagInfo, "GetTagInfo"}, |             {410, &NfcInterface::GetTagInfo, "GetTagInfo"}, | ||||||
|             {411, &Interface::AttachActivateEvent, "AttachActivateEvent"}, |             {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"}, | ||||||
|             {412, &Interface::AttachDeactivateEvent, "AttachDeactivateEvent"}, |             {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"}, | ||||||
|             {1000, nullptr, "ReadMifare"}, |             {1000, &NfcInterface::ReadMifare, "ReadMifare"}, | ||||||
|             {1001, nullptr, "WriteMifare"}, |             {1001, &NfcInterface::WriteMifare ,"WriteMifare"}, | ||||||
|             {1300, &Interface::SendCommandByPassThrough, "SendCommandByPassThrough"}, |             {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"}, | ||||||
|             {1301, nullptr, "KeepPassThroughSession"}, |             {1301, nullptr, "KeepPassThroughSession"}, | ||||||
|             {1302, nullptr, "ReleasePassThroughSession"}, |             {1302, nullptr, "ReleasePassThroughSession"}, | ||||||
|         }; |         }; | ||||||
|  | @ -48,34 +47,35 @@ public: | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class ISystem final : public Interface { | class ISystem final : public NfcInterface { | ||||||
| public: | public: | ||||||
|     explicit ISystem(Core::System& system_) : Interface{system_, "NFC::ISystem"} { |     explicit ISystem(Core::System& system_) | ||||||
|  |         : NfcInterface{system_, "NFC::ISystem", BackendType::Nfc} { | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, &Interface::Initialize, "InitializeOld"}, |             {0, &NfcInterface::Initialize, "InitializeOld"}, | ||||||
|             {1, &Interface::Finalize, "FinalizeOld"}, |             {1, &NfcInterface::Finalize, "FinalizeOld"}, | ||||||
|             {2, &Interface::GetState, "GetStateOld"}, |             {2, &NfcInterface::GetState, "GetStateOld"}, | ||||||
|             {3, &Interface::IsNfcEnabled, "IsNfcEnabledOld"}, |             {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"}, | ||||||
|             {100, nullptr, "SetNfcEnabledOld"}, |             {100, nullptr, "SetNfcEnabledOld"}, | ||||||
|             {400, &Interface::Initialize, "Initialize"}, |             {400, &NfcInterface::Initialize, "Initialize"}, | ||||||
|             {401, &Interface::Finalize, "Finalize"}, |             {401, &NfcInterface::Finalize, "Finalize"}, | ||||||
|             {402, &Interface::GetState, "GetState"}, |             {402, &NfcInterface::GetState, "GetState"}, | ||||||
|             {403, &Interface::IsNfcEnabled, "IsNfcEnabled"}, |             {403, &NfcInterface::IsNfcEnabled, "IsNfcEnabled"}, | ||||||
|             {404, &Interface::ListDevices, "ListDevices"}, |             {404, &NfcInterface::ListDevices, "ListDevices"}, | ||||||
|             {405, &Interface::GetDeviceState, "GetDeviceState"}, |             {405, &NfcInterface::GetDeviceState, "GetDeviceState"}, | ||||||
|             {406, &Interface::GetNpadId, "GetNpadId"}, |             {406, &NfcInterface::GetNpadId, "GetNpadId"}, | ||||||
|             {407, &Interface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, |             {407, &NfcInterface::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, | ||||||
|             {408, &Interface::StartDetection, "StartDetection"}, |             {408, &NfcInterface::StartDetection, "StartDetection"}, | ||||||
|             {409, &Interface::StopDetection, "StopDetection"}, |             {409, &NfcInterface::StopDetection, "StopDetection"}, | ||||||
|             {410, &Interface::GetTagInfo, "GetTagInfo"}, |             {410, &NfcInterface::GetTagInfo, "GetTagInfo"}, | ||||||
|             {411, &Interface::AttachActivateEvent, "AttachActivateEvent"}, |             {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"}, | ||||||
|             {412, &Interface::AttachDeactivateEvent, "AttachDeactivateEvent"}, |             {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"}, | ||||||
|             {500, nullptr, "SetNfcEnabled"}, |             {500, nullptr, "SetNfcEnabled"}, | ||||||
|             {510, nullptr, "OutputTestWave"}, |             {510, nullptr, "OutputTestWave"}, | ||||||
|             {1000, nullptr, "ReadMifare"}, |             {1000, &NfcInterface::ReadMifare, "ReadMifare"}, | ||||||
|             {1001, nullptr, "WriteMifare"}, |             {1001, &NfcInterface::WriteMifare, "WriteMifare"}, | ||||||
|             {1300, &Interface::SendCommandByPassThrough, "SendCommandByPassThrough"}, |             {1300, &NfcInterface::SendCommandByPassThrough, "SendCommandByPassThrough"}, | ||||||
|             {1301, nullptr, "KeepPassThroughSession"}, |             {1301, nullptr, "KeepPassThroughSession"}, | ||||||
|             {1302, nullptr, "ReleasePassThroughSession"}, |             {1302, nullptr, "ReleasePassThroughSession"}, | ||||||
|         }; |         }; | ||||||
|  | @ -85,25 +85,29 @@ public: | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // 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 { | class MFIUser final : public MFInterface { | ||||||
| public: | public: | ||||||
|     explicit MFIUser(Core::System& system_) : MFInterface{system_, "NFC::MFInterface"} { |     explicit MFIUser(Core::System& system_) | ||||||
|  |         : MFInterface{system_, "NFC::MFInterface", BackendType::Mifare} { | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfoTyped<MFIUser> functions[] = { | ||||||
|             {0, &MFIUser::Initialize, "Initialize"}, |             {0, &MFIUser::Initialize, "Initialize"}, | ||||||
|             {1, &MFIUser::Finalize, "Finalize"}, |             {1, &MFIUser::Finalize, "Finalize"}, | ||||||
|             {2, &MFIUser::ListDevices, "ListDevices"}, |             {2, &MFIUser::ListDevices, "ListDevices"}, | ||||||
|             {3, &MFIUser::StartDetection, "StartDetection"}, |             {3, &MFIUser::StartDetection, "StartDetection"}, | ||||||
|             {4, &MFIUser::StopDetection, "StopDetection"}, |             {4, &MFIUser::StopDetection, "StopDetection"}, | ||||||
|             {5, &MFIUser::Read, "Read"}, |             {5, &MFIUser::ReadMifare, "Read"}, | ||||||
|             {6, &MFIUser::Write, "Write"}, |             {6, &MFIUser::WriteMifare, "Write"}, | ||||||
|             {7, &MFIUser::GetTagInfo, "GetTagInfo"}, |             {7, &MFIUser::GetTagInfo, "GetTagInfo"}, | ||||||
|             {8, &MFIUser::GetActivateEventHandle, "GetActivateEventHandle"}, |             {8, &MFIUser::AttachActivateEvent, "GetActivateEventHandle"}, | ||||||
|             {9, &MFIUser::GetDeactivateEventHandle, "GetDeactivateEventHandle"}, |             {9, &MFIUser::AttachDeactivateEvent, "GetDeactivateEventHandle"}, | ||||||
|             {10, &MFIUser::GetState, "GetState"}, |             {10, &MFIUser::GetState, "GetState"}, | ||||||
|             {11, &MFIUser::GetDeviceState, "GetDeviceState"}, |             {11, &MFIUser::GetDeviceState, "GetDeviceState"}, | ||||||
|             {12, &MFIUser::GetNpadId, "GetNpadId"}, |             {12, &MFIUser::GetNpadId, "GetNpadId"}, | ||||||
|             {13, &MFIUser::GetAvailabilityChangeEventHandle, "GetAvailabilityChangeEventHandle"}, |             {13, &MFIUser::AttachAvailabilityChangeEvent, "GetAvailabilityChangeEventHandle"}, | ||||||
|         }; |         }; | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
| 
 | 
 | ||||||
|  | @ -131,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
 | ||||||
| 
 | 
 | ||||||
|  | @ -139,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}; | ||||||
|  | @ -153,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
 | ||||||
| 
 | 
 | ||||||
|  | @ -161,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}; | ||||||
|  | @ -175,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
 | ||||||
| 
 | 
 | ||||||
|  | @ -183,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}; | ||||||
|  | @ -197,7 +201,7 @@ 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
 | ||||||
| 
 | 
 | ||||||
|  | @ -205,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}; | ||||||
|  | @ -221,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,287 +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" |  | ||||||
| 
 |  | ||||||
| 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
 |  | ||||||
|  | @ -6,55 +6,56 @@ | ||||||
| #include "core/hid/hid_types.h" | #include "core/hid/hid_types.h" | ||||||
| #include "core/hle/kernel/k_event.h" | #include "core/hle/kernel/k_event.h" | ||||||
| #include "core/hle/service/ipc_helpers.h" | #include "core/hle/service/ipc_helpers.h" | ||||||
| #include "core/hle/service/nfc/nfc_device.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_interface.h" | ||||||
| #include "core/hle/service/nfc/nfc_result.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" | #include "core/hle/service/time/clock_types.h" | ||||||
| 
 | 
 | ||||||
| namespace Service::NFC { | namespace Service::NFC { | ||||||
| 
 | 
 | ||||||
| Interface::Interface(Core::System& system_, const char* name) | NfcInterface::NfcInterface(Core::System& system_, const char* name, BackendType service_backend) | ||||||
|     : ServiceFramework{system_, name}, service_context{system_, service_name} { |     : ServiceFramework{system_, name}, service_context{system_, service_name}, | ||||||
|     availability_change_event = service_context.CreateEvent("Interface:AvailabilityChangeEvent"); |       backend_type{service_backend} {} | ||||||
| 
 | 
 | ||||||
|     for (u32 device_index = 0; device_index < 10; device_index++) { | NfcInterface ::~NfcInterface() = default; | ||||||
|         devices[device_index] = |  | ||||||
|             std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, |  | ||||||
|                                         service_context, availability_change_event); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| Interface ::~Interface() { | void NfcInterface::Initialize(HLERequestContext& ctx) { | ||||||
|     availability_change_event->Close(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Interface::Initialize(HLERequestContext& ctx) { |  | ||||||
|     LOG_INFO(Service_NFC, "called"); |     LOG_INFO(Service_NFC, "called"); | ||||||
| 
 | 
 | ||||||
|     state = State::Initialized; |     auto manager = GetManager(); | ||||||
|  |     auto result = manager->Initialize(); | ||||||
| 
 | 
 | ||||||
|     for (auto& device : devices) { |     if (result.IsSuccess()) { | ||||||
|         device->Initialize(); |         state = State::Initialized; | ||||||
|  |     } else { | ||||||
|  |         manager->Finalize(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 2, 0}; |     IPC::ResponseBuilder rb{ctx, 2, 0}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::Finalize(HLERequestContext& ctx) { | void NfcInterface::Finalize(HLERequestContext& ctx) { | ||||||
|     LOG_INFO(Service_NFC, "called"); |     LOG_INFO(Service_NFC, "called"); | ||||||
| 
 | 
 | ||||||
|     state = State::NonInitialized; |     if (state != State::NonInitialized) { | ||||||
| 
 |         if (GetBackendType() != BackendType::None) { | ||||||
|     for (auto& device : devices) { |             GetManager()->Finalize(); | ||||||
|         device->Finalize(); |         } | ||||||
|  |         device_manager = nullptr; | ||||||
|  |         state = State::NonInitialized; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 2}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::GetState(HLERequestContext& ctx) { | void NfcInterface::GetState(HLERequestContext& ctx) { | ||||||
|     LOG_DEBUG(Service_NFC, "called"); |     LOG_DEBUG(Service_NFC, "called"); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 3}; |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|  | @ -62,50 +63,28 @@ void Interface::GetState(HLERequestContext& ctx) { | ||||||
|     rb.PushEnum(state); |     rb.PushEnum(state); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::IsNfcEnabled(HLERequestContext& ctx) { | void NfcInterface::IsNfcEnabled(HLERequestContext& ctx) { | ||||||
|     LOG_DEBUG(Service_NFC, "called"); |     LOG_DEBUG(Service_NFC, "called"); | ||||||
| 
 | 
 | ||||||
|  |     // TODO: This calls nn::settings::detail::GetNfcEnableFlag
 | ||||||
|  |     const bool is_enabled = true; | ||||||
|  | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 3}; |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|     rb.Push(state != State::NonInitialized); |     rb.Push(is_enabled); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::ListDevices(HLERequestContext& ctx) { | void NfcInterface::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; |     std::vector<u64> nfp_devices; | ||||||
|     const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); |     const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); | ||||||
|  |     LOG_DEBUG(Service_NFC, "called"); | ||||||
| 
 | 
 | ||||||
|     for (auto& device : devices) { |     auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices); | ||||||
|         if (nfp_devices.size() >= max_allowed_devices) { |     result = TranslateResultToServiceError(result); | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|         if (device->GetCurrentState() != NFP::DeviceState::Unavailable) { |  | ||||||
|             nfp_devices.push_back(device->GetHandle()); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (nfp_devices.empty()) { |     if (result.IsError()) { | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(DeviceNotFound); |         rb.Push(result); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -116,210 +95,177 @@ void Interface::ListDevices(HLERequestContext& ctx) { | ||||||
|     rb.Push(static_cast<s32>(nfp_devices.size())); |     rb.Push(static_cast<s32>(nfp_devices.size())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::GetDeviceState(HLERequestContext& ctx) { | void NfcInterface::GetDeviceState(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); |     LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); | ||||||
| 
 | 
 | ||||||
|     auto device = GetNfcDevice(device_handle); |     const auto device_state = GetManager()->GetDeviceState(device_handle); | ||||||
| 
 | 
 | ||||||
|     if (!device.has_value()) { |     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}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(DeviceNotFound); |         rb.Push(result); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 3}; |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|     rb.PushEnum(device.value()->GetCurrentState()); |     rb.PushEnum(npad_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::GetNpadId(HLERequestContext& ctx) { | void NfcInterface::AttachAvailabilityChangeEvent(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 Interface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) { |  | ||||||
|     LOG_INFO(Service_NFC, "called"); |     LOG_INFO(Service_NFC, "called"); | ||||||
| 
 | 
 | ||||||
|     if (state == State::NonInitialized) { |  | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |  | ||||||
|         rb.Push(NfcDisabled); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     IPC::ResponseBuilder rb{ctx, 2, 1}; |     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|     rb.PushCopyObjects(availability_change_event->GetReadableEvent()); |     rb.PushCopyObjects(GetManager()->AttachAvailabilityChangeEvent()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::StartDetection(HLERequestContext& ctx) { | void NfcInterface::StartDetection(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     const auto nfp_protocol{rp.PopEnum<NFP::TagProtocol>()}; |     const auto tag_protocol{rp.PopEnum<NfcProtocol>()}; | ||||||
|     LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); |     LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol); | ||||||
| 
 | 
 | ||||||
|     if (state == State::NonInitialized) { |     auto result = GetManager()->StartDetection(device_handle, tag_protocol); | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |     result = TranslateResultToServiceError(result); | ||||||
|         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}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::StopDetection(HLERequestContext& ctx) { | void NfcInterface::StopDetection(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); |     LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); | ||||||
| 
 | 
 | ||||||
|     if (state == State::NonInitialized) { |     auto result = GetManager()->StopDetection(device_handle); | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |     result = TranslateResultToServiceError(result); | ||||||
|         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}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::GetTagInfo(HLERequestContext& ctx) { | void NfcInterface::GetTagInfo(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); |     LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); | ||||||
| 
 | 
 | ||||||
|     if (state == State::NonInitialized) { |     TagInfo tag_info{}; | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |     auto result = | ||||||
|         rb.Push(NfcDisabled); |         GetManager()->GetTagInfo(device_handle, tag_info, backend_type == BackendType::Mifare); | ||||||
|         return; |     result = TranslateResultToServiceError(result); | ||||||
|  | 
 | ||||||
|  |     if (result.IsSuccess()) { | ||||||
|  |         ctx.WriteBuffer(tag_info); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     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}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::AttachActivateEvent(HLERequestContext& ctx) { | void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); |     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}; |     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|     rb.PushCopyObjects(device.value()->GetActivateEvent()); |     rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::AttachDeactivateEvent(HLERequestContext& ctx) { | void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); |     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}; |     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|     rb.PushCopyObjects(device.value()->GetDeactivateEvent()); |     rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Interface::SendCommandByPassThrough(HLERequestContext& ctx) { | 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}; |     IPC::RequestParser rp{ctx}; | ||||||
|     const auto device_handle{rp.Pop<u64>()}; |     const auto device_handle{rp.Pop<u64>()}; | ||||||
|     const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()}; |     const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()}; | ||||||
|     const auto command_data{ctx.ReadBuffer()}; |     const auto command_data{ctx.ReadBuffer()}; | ||||||
| 
 |  | ||||||
|     LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}", |     LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}", | ||||||
|              device_handle, timeout.ToSeconds(), command_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); |     std::vector<u8> out_data(1); | ||||||
|     // TODO: Request data from nfc device
 |     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); |     ctx.WriteBuffer(out_data); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 3}; |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|  | @ -327,13 +273,110 @@ void Interface::SendCommandByPassThrough(HLERequestContext& ctx) { | ||||||
|     rb.Push(static_cast<u32>(out_data.size())); |     rb.Push(static_cast<u32>(out_data.size())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::optional<std::shared_ptr<NfcDevice>> Interface::GetNfcDevice(u64 handle) { | std::shared_ptr<DeviceManager> NfcInterface::GetManager() { | ||||||
|     for (auto& device : devices) { |     if (device_manager == nullptr) { | ||||||
|         if (device->GetHandle() == handle) { |         device_manager = std::make_shared<DeviceManager>(system, service_context); | ||||||
|             return device; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     return std::nullopt; |     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
 | } // namespace Service::NFC
 | ||||||
|  |  | ||||||
|  | @ -3,20 +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 Interface : public ServiceFramework<Interface> { | class NfcInterface : public ServiceFramework<NfcInterface> { | ||||||
| public: | public: | ||||||
|     explicit Interface(Core::System& system_, const char* name); |     explicit NfcInterface(Core::System& system_, const char* name, BackendType service_backend); | ||||||
|     ~Interface(); |     ~NfcInterface(); | ||||||
| 
 | 
 | ||||||
|     void Initialize(HLERequestContext& ctx); |     void Initialize(HLERequestContext& ctx); | ||||||
|     void Finalize(HLERequestContext& ctx); |     void Finalize(HLERequestContext& ctx); | ||||||
|  | @ -31,22 +28,22 @@ public: | ||||||
|     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); | ||||||
| 
 | 
 | ||||||
| private: | protected: | ||||||
|     enum class State : u32 { |     std::shared_ptr<DeviceManager> GetManager(); | ||||||
|         NonInitialized, |     BackendType GetBackendType() const; | ||||||
|         Initialized, |     Result TranslateResultToServiceError(Result result) const; | ||||||
|     }; |     Result TranslateResultToNfp(Result result) const; | ||||||
| 
 |     Result TranslateResultToMifare(Result result) const; | ||||||
|     std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); |  | ||||||
| 
 | 
 | ||||||
|     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
 | ||||||
|  | @ -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
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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: | ||||||
|  |  | ||||||
|  | @ -570,8 +570,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"); | ||||||
|  | @ -599,7 +599,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); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Narr the Reg
						Narr the Reg