nfp.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include <vector>
  7. #include "core/hle/service/kernel_helpers.h"
  8. #include "core/hle/service/mii/mii_manager.h"
  9. #include "core/hle/service/service.h"
  10. namespace Kernel {
  11. class KEvent;
  12. class KReadableEvent;
  13. } // namespace Kernel
  14. namespace Core::HID {
  15. enum class NpadIdType : u32;
  16. } // namespace Core::HID
  17. namespace Service::NFP {
  18. enum class ServiceType : u32 {
  19. User,
  20. Debug,
  21. System,
  22. };
  23. enum class State : u32 {
  24. NonInitialized,
  25. Initialized,
  26. };
  27. enum class DeviceState : u32 {
  28. Initialized,
  29. SearchingForTag,
  30. TagFound,
  31. TagRemoved,
  32. TagMounted,
  33. Unaviable,
  34. Finalized,
  35. };
  36. enum class ModelType : u32 {
  37. Amiibo,
  38. };
  39. enum class MountTarget : u32 {
  40. Rom,
  41. Ram,
  42. All,
  43. };
  44. enum class AmiiboType : u8 {
  45. Figure,
  46. Card,
  47. Yarn,
  48. };
  49. enum class AmiiboSeries : u8 {
  50. SuperSmashBros,
  51. SuperMario,
  52. ChibiRobo,
  53. YoshiWoollyWorld,
  54. Splatoon,
  55. AnimalCrossing,
  56. EightBitMario,
  57. Skylanders,
  58. Unknown8,
  59. TheLegendOfZelda,
  60. ShovelKnight,
  61. Unknown11,
  62. Kiby,
  63. Pokemon,
  64. MarioSportsSuperstars,
  65. MonsterHunter,
  66. BoxBoy,
  67. Pikmin,
  68. FireEmblem,
  69. Metroid,
  70. Others,
  71. MegaMan,
  72. Diablo
  73. };
  74. struct TagInfo {
  75. std::array<u8, 10> uuid;
  76. u8 uuid_length;
  77. INSERT_PADDING_BYTES(0x15);
  78. s32 protocol;
  79. u32 tag_type;
  80. INSERT_PADDING_BYTES(0x30);
  81. };
  82. static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size");
  83. struct CommonInfo {
  84. u16 last_write_year;
  85. u8 last_write_month;
  86. u8 last_write_day;
  87. u16 write_counter;
  88. u16 version;
  89. u32 application_area_size;
  90. INSERT_PADDING_BYTES(0x34);
  91. };
  92. static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
  93. struct ModelInfo {
  94. u16 character_id;
  95. u8 character_variant;
  96. AmiiboType amiibo_type;
  97. u16 model_number;
  98. AmiiboSeries series;
  99. u8 fixed; // Must be 02
  100. INSERT_PADDING_BYTES(0x4); // Unknown
  101. INSERT_PADDING_BYTES(0x20); // Probably a SHA256-(HMAC?) hash
  102. INSERT_PADDING_BYTES(0x14); // SHA256-HMAC
  103. };
  104. static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
  105. struct RegisterInfo {
  106. Service::Mii::MiiInfo mii_char_info;
  107. u16 first_write_year;
  108. u8 first_write_month;
  109. u8 first_write_day;
  110. std::array<u8, 11> amiibo_name;
  111. u8 unknown;
  112. INSERT_PADDING_BYTES(0x98);
  113. };
  114. static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
  115. class Module final {
  116. public:
  117. class Interface : public ServiceFramework<Interface> {
  118. public:
  119. explicit Interface(std::shared_ptr<Module> module_, Core::System& system_,
  120. const char* name);
  121. ~Interface() override;
  122. struct AmiiboFile {
  123. std::array<u8, 10> uuid;
  124. u16 uuid_lock; // Must be 0F E0
  125. u32 compability_container; // Must be F1 10 FF EE
  126. u16 crypto_init; // Must be A5 XX
  127. u16 write_count; // Number of times the amiibo has been written?
  128. INSERT_PADDING_BYTES(0x20); // System crypts
  129. INSERT_PADDING_BYTES(0x20); // SHA256-(HMAC?) hash
  130. ModelInfo model_info; // This struct is bigger than documentation
  131. INSERT_PADDING_BYTES(0xC); // SHA256-HMAC
  132. INSERT_PADDING_BYTES(0x114); // section 1 encrypted buffer
  133. INSERT_PADDING_BYTES(0x54); // section 2 encrypted buffer
  134. u32 tag_dynamic_lock; // Must be 01 00 0F XX
  135. u32 tag_CFG0; // Must be 00 00 00 04
  136. u32 tag_CFG1; // Must be 50 00 00 00
  137. };
  138. static_assert(sizeof(AmiiboFile) == 0x214, "AmiiboFile is an invalid size");
  139. void CreateUserInterface(Kernel::HLERequestContext& ctx);
  140. bool LoadAmiibo(const std::vector<u8>& buffer);
  141. void CloseAmiibo();
  142. void Initialize();
  143. void Finalize();
  144. ResultCode StartDetection(s32 protocol_);
  145. ResultCode StopDetection();
  146. ResultCode Mount();
  147. ResultCode Unmount();
  148. ResultCode GetTagInfo(TagInfo& tag_info) const;
  149. ResultCode GetCommonInfo(CommonInfo& common_info) const;
  150. ResultCode GetModelInfo(ModelInfo& model_info) const;
  151. ResultCode GetRegisterInfo(RegisterInfo& register_info) const;
  152. ResultCode OpenApplicationArea(u32 access_id);
  153. ResultCode GetApplicationArea(std::vector<u8>& data) const;
  154. ResultCode SetApplicationArea(const std::vector<u8>& data);
  155. ResultCode CreateApplicationArea(u32 access_id, const std::vector<u8>& data);
  156. u64 GetHandle() const;
  157. DeviceState GetCurrentState() const;
  158. Core::HID::NpadIdType GetNpadId() const;
  159. Kernel::KReadableEvent& GetActivateEvent() const;
  160. Kernel::KReadableEvent& GetDeactivateEvent() const;
  161. protected:
  162. std::shared_ptr<Module> module;
  163. private:
  164. /// Validates that the amiibo file is not corrupted
  165. bool IsAmiiboValid() const;
  166. bool AmiiboApplicationDataExist(u32 access_id) const;
  167. const std::vector<u8> LoadAmiiboApplicationData(u32 access_id) const;
  168. void SaveAmiiboApplicationData(u32 access_id, const std::vector<u8>& data) const;
  169. const Core::HID::NpadIdType npad_id;
  170. DeviceState device_state{DeviceState::Unaviable};
  171. KernelHelpers::ServiceContext service_context;
  172. Kernel::KEvent* activate_event;
  173. Kernel::KEvent* deactivate_event;
  174. AmiiboFile amiibo{};
  175. s32 protocol;
  176. bool is_application_area_initialized{};
  177. u32 application_area_id;
  178. std::vector<u8> application_area_data;
  179. };
  180. };
  181. class IUser final : public ServiceFramework<IUser> {
  182. public:
  183. explicit IUser(Module::Interface& nfp_interface_, Core::System& system_);
  184. private:
  185. void Initialize(Kernel::HLERequestContext& ctx);
  186. void Finalize(Kernel::HLERequestContext& ctx);
  187. void ListDevices(Kernel::HLERequestContext& ctx);
  188. void StartDetection(Kernel::HLERequestContext& ctx);
  189. void StopDetection(Kernel::HLERequestContext& ctx);
  190. void Mount(Kernel::HLERequestContext& ctx);
  191. void Unmount(Kernel::HLERequestContext& ctx);
  192. void OpenApplicationArea(Kernel::HLERequestContext& ctx);
  193. void GetApplicationArea(Kernel::HLERequestContext& ctx);
  194. void SetApplicationArea(Kernel::HLERequestContext& ctx);
  195. void CreateApplicationArea(Kernel::HLERequestContext& ctx);
  196. void GetTagInfo(Kernel::HLERequestContext& ctx);
  197. void GetRegisterInfo(Kernel::HLERequestContext& ctx);
  198. void GetCommonInfo(Kernel::HLERequestContext& ctx);
  199. void GetModelInfo(Kernel::HLERequestContext& ctx);
  200. void AttachActivateEvent(Kernel::HLERequestContext& ctx);
  201. void AttachDeactivateEvent(Kernel::HLERequestContext& ctx);
  202. void GetState(Kernel::HLERequestContext& ctx);
  203. void GetDeviceState(Kernel::HLERequestContext& ctx);
  204. void GetNpadId(Kernel::HLERequestContext& ctx);
  205. void GetApplicationAreaSize(Kernel::HLERequestContext& ctx);
  206. void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx);
  207. KernelHelpers::ServiceContext service_context;
  208. // TODO(german77): We should have a vector of interfaces
  209. Module::Interface& nfp_interface;
  210. State state{State::NonInitialized};
  211. Kernel::KEvent* availability_change_event;
  212. };
  213. void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
  214. } // namespace Service::NFP