diff options
Diffstat (limited to 'src/core/hle/service/nfp/nfp.h')
-rw-r--r-- | src/core/hle/service/nfp/nfp.h | 242 |
1 files changed, 228 insertions, 14 deletions
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h index 95c127efb..022f13b29 100644 --- a/src/core/hle/service/nfp/nfp.h +++ b/src/core/hle/service/nfp/nfp.h @@ -7,15 +7,132 @@ #include <array> #include <vector> +#include "common/common_funcs.h" #include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/mii/mii_manager.h" #include "core/hle/service/service.h" namespace Kernel { class KEvent; -} +class KReadableEvent; +} // namespace Kernel + +namespace Core::HID { +enum class NpadIdType : u32; +} // namespace Core::HID namespace Service::NFP { +enum class ServiceType : u32 { + User, + Debug, + System, +}; + +enum class State : u32 { + NonInitialized, + Initialized, +}; + +enum class DeviceState : u32 { + Initialized, + SearchingForTag, + TagFound, + TagRemoved, + TagMounted, + Unaviable, + Finalized, +}; + +enum class ModelType : u32 { + Amiibo, +}; + +enum class MountTarget : u32 { + Rom, + Ram, + All, +}; + +enum class AmiiboType : u8 { + Figure, + Card, + Yarn, +}; + +enum class AmiiboSeries : u8 { + SuperSmashBros, + SuperMario, + ChibiRobo, + YoshiWoollyWorld, + Splatoon, + AnimalCrossing, + EightBitMario, + Skylanders, + Unknown8, + TheLegendOfZelda, + ShovelKnight, + Unknown11, + Kiby, + Pokemon, + MarioSportsSuperstars, + MonsterHunter, + BoxBoy, + Pikmin, + FireEmblem, + Metroid, + Others, + MegaMan, + Diablo +}; + +using TagUuid = std::array<u8, 10>; + +struct TagInfo { + TagUuid uuid; + u8 uuid_length; + INSERT_PADDING_BYTES(0x15); + s32 protocol; + u32 tag_type; + INSERT_PADDING_BYTES(0x30); +}; +static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size"); + +struct CommonInfo { + u16 last_write_year; + u8 last_write_month; + u8 last_write_day; + u16 write_counter; + u16 version; + u32 application_area_size; + INSERT_PADDING_BYTES(0x34); +}; +static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size"); + +struct ModelInfo { + u16 character_id; + u8 character_variant; + AmiiboType amiibo_type; + u16 model_number; + AmiiboSeries series; + u8 fixed; // Must be 02 + INSERT_PADDING_BYTES(0x4); // Unknown + INSERT_PADDING_BYTES(0x20); // Probably a SHA256-(HMAC?) hash + INSERT_PADDING_BYTES(0x14); // SHA256-HMAC +}; +static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size"); + +struct RegisterInfo { + Service::Mii::MiiInfo mii_char_info; + u16 first_write_year; + u8 first_write_month; + u8 first_write_day; + std::array<u8, 11> amiibo_name; + u8 unknown; + INSERT_PADDING_BYTES(0x98); +}; +static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); + class Module final { public: class Interface : public ServiceFramework<Interface> { @@ -24,34 +141,131 @@ public: const char* name); ~Interface() override; - struct ModelInfo { - std::array<u8, 0x8> amiibo_identification_block; - INSERT_PADDING_BYTES(0x38); + struct EncryptedAmiiboFile { + u16 crypto_init; // Must be A5 XX + u16 write_count; // Number of times the amiibo has been written? + INSERT_PADDING_BYTES(0x20); // System crypts + INSERT_PADDING_BYTES(0x20); // SHA256-(HMAC?) hash + ModelInfo model_info; // This struct is bigger than documentation + INSERT_PADDING_BYTES(0xC); // SHA256-HMAC + INSERT_PADDING_BYTES(0x114); // section 1 encrypted buffer + INSERT_PADDING_BYTES(0x54); // section 2 encrypted buffer + }; + static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size"); + + struct NTAG215Password { + u32 PWD; // Password to allow write access + u16 PACK; // Password acknowledge reply + u16 RFUI; // Reserved for future use }; - static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size"); + static_assert(sizeof(NTAG215Password) == 0x8, "NTAG215Password is an invalid size"); - struct AmiiboFile { - std::array<u8, 10> uuid; - INSERT_PADDING_BYTES(0x4a); - ModelInfo model_info; + struct NTAG215File { + TagUuid uuid; // Unique serial number + u16 lock_bytes; // Set defined pages as read only + u32 compability_container; // Defines available memory + EncryptedAmiiboFile user_memory; // Writable data + u32 dynamic_lock; // Dynamic lock + u32 CFG0; // Defines memory protected by password + u32 CFG1; // Defines number of verification attempts + NTAG215Password password; // Password data }; - static_assert(sizeof(AmiiboFile) == 0x94, "AmiiboFile is an invalid size"); + static_assert(sizeof(NTAG215File) == 0x21C, "NTAG215File is an invalid size"); void CreateUserInterface(Kernel::HLERequestContext& ctx); bool LoadAmiibo(const std::vector<u8>& buffer); - Kernel::KReadableEvent& GetNFCEvent(); - const AmiiboFile& GetAmiiboBuffer() const; + void CloseAmiibo(); + + void Initialize(); + void Finalize(); + + ResultCode StartDetection(s32 protocol_); + ResultCode StopDetection(); + ResultCode Mount(); + ResultCode Unmount(); + + ResultCode GetTagInfo(TagInfo& tag_info) const; + ResultCode GetCommonInfo(CommonInfo& common_info) const; + ResultCode GetModelInfo(ModelInfo& model_info) const; + ResultCode GetRegisterInfo(RegisterInfo& register_info) const; + + ResultCode OpenApplicationArea(u32 access_id); + ResultCode GetApplicationArea(std::vector<u8>& data) const; + ResultCode SetApplicationArea(const std::vector<u8>& data); + ResultCode CreateApplicationArea(u32 access_id, const std::vector<u8>& data); + + u64 GetHandle() const; + DeviceState GetCurrentState() const; + Core::HID::NpadIdType GetNpadId() const; + + Kernel::KReadableEvent& GetActivateEvent() const; + Kernel::KReadableEvent& GetDeactivateEvent() const; protected: std::shared_ptr<Module> module; private: + /// Validates that the amiibo file is not corrupted + bool IsAmiiboValid() const; + + bool AmiiboApplicationDataExist(u32 access_id) const; + std::vector<u8> LoadAmiiboApplicationData(u32 access_id) const; + void SaveAmiiboApplicationData(u32 access_id, const std::vector<u8>& data) const; + + /// return password needed to allow write access to protected memory + u32 GetTagPassword(const TagUuid& uuid) const; + + const Core::HID::NpadIdType npad_id; + + DeviceState device_state{DeviceState::Unaviable}; KernelHelpers::ServiceContext service_context; - Kernel::KEvent* nfc_tag_load; - AmiiboFile amiibo{}; + Kernel::KEvent* activate_event; + Kernel::KEvent* deactivate_event; + NTAG215File tag_data{}; + s32 protocol; + bool is_application_area_initialized{}; + u32 application_area_id; + std::vector<u8> application_area_data; }; }; +class IUser final : public ServiceFramework<IUser> { +public: + explicit IUser(Module::Interface& nfp_interface_, Core::System& system_); + +private: + void Initialize(Kernel::HLERequestContext& ctx); + void Finalize(Kernel::HLERequestContext& ctx); + void ListDevices(Kernel::HLERequestContext& ctx); + void StartDetection(Kernel::HLERequestContext& ctx); + void StopDetection(Kernel::HLERequestContext& ctx); + void Mount(Kernel::HLERequestContext& ctx); + void Unmount(Kernel::HLERequestContext& ctx); + void OpenApplicationArea(Kernel::HLERequestContext& ctx); + void GetApplicationArea(Kernel::HLERequestContext& ctx); + void SetApplicationArea(Kernel::HLERequestContext& ctx); + void CreateApplicationArea(Kernel::HLERequestContext& ctx); + void GetTagInfo(Kernel::HLERequestContext& ctx); + void GetRegisterInfo(Kernel::HLERequestContext& ctx); + void GetCommonInfo(Kernel::HLERequestContext& ctx); + void GetModelInfo(Kernel::HLERequestContext& ctx); + void AttachActivateEvent(Kernel::HLERequestContext& ctx); + void AttachDeactivateEvent(Kernel::HLERequestContext& ctx); + void GetState(Kernel::HLERequestContext& ctx); + void GetDeviceState(Kernel::HLERequestContext& ctx); + void GetNpadId(Kernel::HLERequestContext& ctx); + void GetApplicationAreaSize(Kernel::HLERequestContext& ctx); + void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx); + + KernelHelpers::ServiceContext service_context; + + // TODO(german77): We should have a vector of interfaces + Module::Interface& nfp_interface; + + State state{State::NonInitialized}; + Kernel::KEvent* availability_change_event; +}; + void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); } // namespace Service::NFP |