summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nfp/nfp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/nfp/nfp.h')
-rw-r--r--src/core/hle/service/nfp/nfp.h242
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