1 // Copyright 2016 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <atomic> 8 #include <memory> 9 #include <boost/serialization/binary_object.hpp> 10 #include "common/common_types.h" 11 #include "core/hle/service/service.h" 12 13 namespace Core { 14 class System; 15 } 16 17 namespace Kernel { 18 class Event; 19 } // namespace Kernel 20 21 namespace Service::NFC { 22 23 namespace ErrCodes { 24 enum { 25 CommandInvalidForState = 512, 26 }; 27 } // namespace ErrCodes 28 29 // TODO(FearlessTobi): Add more members to this struct 30 struct AmiiboData { 31 std::array<u8, 7> uuid; 32 INSERT_PADDING_BYTES(0x4D); 33 u16_le char_id; 34 u8 char_variant; 35 u8 figure_type; 36 u16_be model_number; 37 u8 series; 38 INSERT_PADDING_BYTES(0x1C1); 39 40 private: 41 template <class Archive> serializeAmiiboData42 void serialize(Archive& ar, const unsigned int) { 43 ar& boost::serialization::make_binary_object(this, sizeof(AmiiboData)); 44 } 45 friend class boost::serialization::access; 46 }; 47 static_assert(sizeof(AmiiboData) == 0x21C, "AmiiboData is an invalid size"); 48 49 enum class TagState : u8 { 50 NotInitialized = 0, 51 NotScanning = 1, 52 Scanning = 2, 53 TagInRange = 3, 54 TagOutOfRange = 4, 55 TagDataLoaded = 5, 56 Unknown6 = 6, 57 }; 58 59 enum class CommunicationStatus : u8 { 60 AttemptInitialize = 1, 61 NfcInitialized = 2, 62 }; 63 64 class Module final { 65 public: 66 explicit Module(Core::System& system); 67 ~Module(); 68 69 class Interface : public ServiceFramework<Interface> { 70 public: 71 Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session); 72 ~Interface(); 73 74 std::shared_ptr<Module> GetModule() const; 75 76 void LoadAmiibo(const AmiiboData& amiibo_data); 77 78 void RemoveAmiibo(); 79 80 protected: 81 /** 82 * NFC::Initialize service function 83 * Inputs: 84 * 0 : Header code [0x00010040] 85 * 1 : (u8) unknown parameter. Can be either value 0x1 or 0x2 86 * Outputs: 87 * 1 : Result of function, 0 on success, otherwise error code 88 */ 89 void Initialize(Kernel::HLERequestContext& ctx); 90 91 /** 92 * NFC::Shutdown service function 93 * Inputs: 94 * 0 : Header code [0x00020040] 95 * 1 : (u8) unknown parameter 96 * Outputs: 97 * 1 : Result of function, 0 on success, otherwise error code 98 */ 99 void Shutdown(Kernel::HLERequestContext& ctx); 100 101 /** 102 * NFC::StartCommunication service function 103 * Inputs: 104 * 0 : Header code [0x00030000] 105 * Outputs: 106 * 1 : Result of function, 0 on success, otherwise error code 107 */ 108 void StartCommunication(Kernel::HLERequestContext& ctx); 109 110 /** 111 * NFC::StopCommunication service function 112 * Inputs: 113 * 0 : Header code [0x00040000] 114 * Outputs: 115 * 1 : Result of function, 0 on success, otherwise error code 116 */ 117 void StopCommunication(Kernel::HLERequestContext& ctx); 118 119 /** 120 * NFC::StartTagScanning service function 121 * Inputs: 122 * 0 : Header code [0x00050040] 123 * 1 : (u16) unknown. This is normally 0x0 124 * Outputs: 125 * 1 : Result of function, 0 on success, otherwise error code 126 */ 127 void StartTagScanning(Kernel::HLERequestContext& ctx); 128 129 /** 130 * NFC::StopTagScanning service function 131 * Inputs: 132 * 0 : Header code [0x00060000] 133 * Outputs: 134 * 1 : Result of function, 0 on success, otherwise error code 135 */ 136 void StopTagScanning(Kernel::HLERequestContext& ctx); 137 138 /** 139 * NFC::LoadAmiiboData service function 140 * Inputs: 141 * 0 : Header code [0x00070000] 142 * Outputs: 143 * 1 : Result of function, 0 on success, otherwise error code 144 */ 145 void LoadAmiiboData(Kernel::HLERequestContext& ctx); 146 147 /** 148 * NFC::ResetTagScanState service function 149 * Inputs: 150 * 0 : Header code [0x00080000] 151 * Outputs: 152 * 1 : Result of function, 0 on success, otherwise error code 153 */ 154 void ResetTagScanState(Kernel::HLERequestContext& ctx); 155 156 /** 157 * NFC::GetTagInRangeEvent service function 158 * Inputs: 159 * 0 : Header code [0x000B0000] 160 * Outputs: 161 * 1 : Result of function, 0 on success, otherwise error code 162 * 2 : Copy handle descriptor 163 * 3 : Event Handle 164 */ 165 void GetTagInRangeEvent(Kernel::HLERequestContext& ctx); 166 167 /** 168 * NFC::GetTagOutOfRangeEvent service function 169 * Inputs: 170 * 0 : Header code [0x000C0000] 171 * Outputs: 172 * 1 : Result of function, 0 on success, otherwise error code 173 * 2 : Copy handle descriptor 174 * 3 : Event Handle 175 */ 176 void GetTagOutOfRangeEvent(Kernel::HLERequestContext& ctx); 177 178 /** 179 * NFC::GetTagState service function 180 * Inputs: 181 * 0 : Header code [0x000D0000] 182 * Outputs: 183 * 1 : Result of function, 0 on success, otherwise error code 184 * 2 : (u8) Tag state 185 */ 186 void GetTagState(Kernel::HLERequestContext& ctx); 187 188 /** 189 * NFC::CommunicationGetStatus service function 190 * Inputs: 191 * 0 : Header code [0x000F0000] 192 * Outputs: 193 * 1 : Result of function, 0 on success, otherwise error code 194 * 2 : (u8) Communication state 195 */ 196 void CommunicationGetStatus(Kernel::HLERequestContext& ctx); 197 198 /** 199 * NFC::GetTagInfo service function 200 * Inputs: 201 * 0 : Header code [0x00110000] 202 * Outputs: 203 * 1 : Result of function, 0 on success, otherwise error code 204 * 2-12 : 0x2C-byte struct 205 */ 206 void GetTagInfo(Kernel::HLERequestContext& ctx); 207 208 /** 209 * NFC::GetAmiiboConfig service function 210 * Inputs: 211 * 0 : Header code [0x00180000] 212 * Outputs: 213 * 1 : Result of function, 0 on success, otherwise error code 214 * 2-17 : 0x40-byte config struct 215 */ 216 void GetAmiiboConfig(Kernel::HLERequestContext& ctx); 217 218 /** 219 * NFC::Unknown0x1A service function 220 * Inputs: 221 * 0 : Header code [0x001A0000] 222 * Outputs: 223 * 1 : Result of function, 0 on success, otherwise error code 224 */ 225 void Unknown0x1A(Kernel::HLERequestContext& ctx); 226 227 /** 228 * NFC::GetIdentificationBlock service function 229 * Inputs: 230 * 0 : Header code [0x001B0000] 231 * Outputs: 232 * 1 : Result of function, 0 on success, otherwise error code 233 * 2-31 : 0x36-byte struct 234 */ 235 void GetIdentificationBlock(Kernel::HLERequestContext& ctx); 236 237 protected: 238 std::shared_ptr<Module> nfc; 239 }; 240 241 private: 242 // Sync nfc_tag_state with amiibo_in_range and signal events on state change. 243 void SyncTagState(); 244 245 std::shared_ptr<Kernel::Event> tag_in_range_event; 246 std::shared_ptr<Kernel::Event> tag_out_of_range_event; 247 TagState nfc_tag_state = TagState::NotInitialized; 248 CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized; 249 250 AmiiboData amiibo_data{}; 251 bool amiibo_in_range = false; 252 253 template <class Archive> 254 void serialize(Archive& ar, const unsigned int); 255 friend class boost::serialization::access; 256 }; 257 258 void InstallInterfaces(Core::System& system); 259 260 } // namespace Service::NFC 261 262 SERVICE_CONSTRUCT(Service::NFC::Module) 263 BOOST_CLASS_EXPORT_KEY(Service::NFC::Module) 264