summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hid/emulated_controller.cpp6
-rw-r--r--src/core/hid/emulated_controller.h2
-rw-r--r--src/core/hle/service/nfp/nfp.cpp664
-rw-r--r--src/core/hle/service/nfp/nfp.h189
4 files changed, 672 insertions, 189 deletions
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index a7cdf45e6..61ceea629 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -884,6 +884,12 @@ bool EmulatedController::TestVibration(std::size_t device_index) {
884 return SetVibration(device_index, DEFAULT_VIBRATION_VALUE); 884 return SetVibration(device_index, DEFAULT_VIBRATION_VALUE);
885} 885}
886 886
887bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) {
888 LOG_INFO(Service_HID, "Set polling mode {}", polling_mode);
889 auto& output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
890 return output_device->SetPollingMode(polling_mode) == Common::Input::PollingError::None;
891}
892
887void EmulatedController::SetLedPattern() { 893void EmulatedController::SetLedPattern() {
888 for (auto& device : output_devices) { 894 for (auto& device : output_devices) {
889 if (!device) { 895 if (!device) {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index d8642c5b3..7785e6110 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -309,6 +309,8 @@ public:
309 */ 309 */
310 bool TestVibration(std::size_t device_index); 310 bool TestVibration(std::size_t device_index);
311 311
312 bool SetPollingMode(Common::Input::PollingMode polling_mode);
313
312 /// Returns the led pattern corresponding to this emulated controller 314 /// Returns the led pattern corresponding to this emulated controller
313 LedPattern GetLedPattern() const; 315 LedPattern GetLedPattern() const;
314 316
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index cedade5c2..7f1fb3a71 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -7,6 +7,9 @@
7 7
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hid/emulated_controller.h"
11#include "core/hid/hid_core.h"
12#include "core/hid/hid_types.h"
10#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
11#include "core/hle/kernel/k_event.h" 14#include "core/hle/kernel/k_event.h"
12#include "core/hle/service/nfp/nfp.h" 15#include "core/hle/service/nfp/nfp.h"
@@ -14,12 +17,18 @@
14 17
15namespace Service::NFP { 18namespace Service::NFP {
16namespace ErrCodes { 19namespace ErrCodes {
17constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152); 20constexpr ResultCode DeviceNotFound(ErrorModule::NFP, 64);
21constexpr ResultCode WrongDeviceState(ErrorModule::NFP, 73);
22constexpr ResultCode ApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
23constexpr ResultCode NoApplicationArea(ErrorModule::NFP, 152);
24constexpr ResultCode ApplicationAreaExist(ErrorModule::NFP, 168);
18} // namespace ErrCodes 25} // namespace ErrCodes
19 26
27constexpr u32 ApplicationAreaSize = 0xD8;
28
20IUser::IUser(Module::Interface& nfp_interface_, Core::System& system_) 29IUser::IUser(Module::Interface& nfp_interface_, Core::System& system_)
21 : ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_}, 30 : ServiceFramework{system_, "NFP::IUser"}, service_context{system_, service_name},
22 deactivate_event{system.Kernel()}, availability_change_event{system.Kernel()} { 31 nfp_interface{nfp_interface_} {
23 static const FunctionInfo functions[] = { 32 static const FunctionInfo functions[] = {
24 {0, &IUser::Initialize, "Initialize"}, 33 {0, &IUser::Initialize, "Initialize"},
25 {1, &IUser::Finalize, "Finalize"}, 34 {1, &IUser::Finalize, "Finalize"},
@@ -30,10 +39,10 @@ IUser::IUser(Module::Interface& nfp_interface_, Core::System& system_)
30 {6, &IUser::Unmount, "Unmount"}, 39 {6, &IUser::Unmount, "Unmount"},
31 {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, 40 {7, &IUser::OpenApplicationArea, "OpenApplicationArea"},
32 {8, &IUser::GetApplicationArea, "GetApplicationArea"}, 41 {8, &IUser::GetApplicationArea, "GetApplicationArea"},
33 {9, nullptr, "SetApplicationArea"}, 42 {9, &IUser::SetApplicationArea, "SetApplicationArea"},
34 {10, nullptr, "Flush"}, 43 {10, nullptr, "Flush"},
35 {11, nullptr, "Restore"}, 44 {11, nullptr, "Restore"},
36 {12, nullptr, "CreateApplicationArea"}, 45 {12, &IUser::CreateApplicationArea, "CreateApplicationArea"},
37 {13, &IUser::GetTagInfo, "GetTagInfo"}, 46 {13, &IUser::GetTagInfo, "GetTagInfo"},
38 {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, 47 {14, &IUser::GetRegisterInfo, "GetRegisterInfo"},
39 {15, &IUser::GetCommonInfo, "GetCommonInfo"}, 48 {15, &IUser::GetCommonInfo, "GetCommonInfo"},
@@ -49,220 +58,416 @@ IUser::IUser(Module::Interface& nfp_interface_, Core::System& system_)
49 }; 58 };
50 RegisterHandlers(functions); 59 RegisterHandlers(functions);
51 60
52 Kernel::KAutoObject::Create(std::addressof(deactivate_event)); 61 availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent");
53 Kernel::KAutoObject::Create(std::addressof(availability_change_event));
54
55 deactivate_event.Initialize("IUser:DeactivateEvent");
56 availability_change_event.Initialize("IUser:AvailabilityChangeEvent");
57} 62}
58 63
59void IUser::Initialize(Kernel::HLERequestContext& ctx) { 64void IUser::Initialize(Kernel::HLERequestContext& ctx) {
60 LOG_DEBUG(Service_NFC, "called"); 65 LOG_INFO(Service_NFC, "called");
66
67 state = State::Initialized;
68
69 // TODO(german77): Loop through all interfaces
70 nfp_interface.Initialize();
61 71
62 IPC::ResponseBuilder rb{ctx, 2, 0}; 72 IPC::ResponseBuilder rb{ctx, 2, 0};
63 rb.Push(ResultSuccess); 73 rb.Push(ResultSuccess);
64
65 state = State::Initialized;
66} 74}
67 75
68void IUser::Finalize(Kernel::HLERequestContext& ctx) { 76void IUser::Finalize(Kernel::HLERequestContext& ctx) {
69 LOG_DEBUG(Service_NFP, "called"); 77 LOG_INFO(Service_NFP, "called");
78
79 state = State::NonInitialized;
70 80
71 device_state = DeviceState::Finalized; 81 // TODO(german77): Loop through all interfaces
82 nfp_interface.Finalize();
72 83
73 IPC::ResponseBuilder rb{ctx, 2}; 84 IPC::ResponseBuilder rb{ctx, 2};
74 rb.Push(ResultSuccess); 85 rb.Push(ResultSuccess);
75} 86}
76 87
77void IUser::ListDevices(Kernel::HLERequestContext& ctx) { 88void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
78 IPC::RequestParser rp{ctx}; 89 LOG_INFO(Service_NFP, "called");
79 const u32 array_size = rp.Pop<u32>(); 90
80 LOG_DEBUG(Service_NFP, "called, array_size={}", array_size); 91 std::vector<u64> devices;
92
93 // TODO(german77): Loop through all interfaces
94 devices.push_back(nfp_interface.GetHandle());
81 95
82 ctx.WriteBuffer(device_handle); 96 ctx.WriteBuffer(devices);
83 97
84 IPC::ResponseBuilder rb{ctx, 3}; 98 IPC::ResponseBuilder rb{ctx, 3};
85 rb.Push(ResultSuccess); 99 rb.Push(ResultSuccess);
86 rb.Push<u32>(1); 100 rb.Push(devices.size());
87} 101}
88 102
89void IUser::StartDetection(Kernel::HLERequestContext& ctx) { 103void IUser::StartDetection(Kernel::HLERequestContext& ctx) {
90 LOG_DEBUG(Service_NFP, "called"); 104 IPC::RequestParser rp{ctx};
91 105 const auto device_handle{rp.Pop<u64>()};
92 if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { 106 const auto nfp_protocol{rp.Pop<s32>()};
93 device_state = DeviceState::SearchingForTag; 107 LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol);
108
109 // TODO(german77): Loop through all interfaces
110 if (device_handle == nfp_interface.GetHandle()) {
111 const auto result = nfp_interface.StartDetection();
112 IPC::ResponseBuilder rb{ctx, 2};
113 rb.Push(result);
114 return;
94 } 115 }
116
117 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
118
95 IPC::ResponseBuilder rb{ctx, 2}; 119 IPC::ResponseBuilder rb{ctx, 2};
96 rb.Push(ResultSuccess); 120 rb.Push(ErrCodes::DeviceNotFound);
97} 121}
98 122
99void IUser::StopDetection(Kernel::HLERequestContext& ctx) { 123void IUser::StopDetection(Kernel::HLERequestContext& ctx) {
100 LOG_DEBUG(Service_NFP, "called"); 124 IPC::RequestParser rp{ctx};
101 125 const auto device_handle{rp.Pop<u64>()};
102 switch (device_state) { 126 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
103 case DeviceState::TagFound: 127
104 case DeviceState::TagMounted: 128 // TODO(german77): Loop through all interfaces
105 deactivate_event.GetWritableEvent().Signal(); 129 if (device_handle == nfp_interface.GetHandle()) {
106 device_state = DeviceState::Initialized; 130 const auto result = nfp_interface.StopDetection();
107 break; 131 IPC::ResponseBuilder rb{ctx, 2};
108 case DeviceState::SearchingForTag: 132 rb.Push(result);
109 case DeviceState::TagRemoved: 133 return;
110 device_state = DeviceState::Initialized;
111 break;
112 default:
113 break;
114 } 134 }
135
136 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
137
115 IPC::ResponseBuilder rb{ctx, 2}; 138 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(ResultSuccess); 139 rb.Push(ErrCodes::DeviceNotFound);
117} 140}
118 141
119void IUser::Mount(Kernel::HLERequestContext& ctx) { 142void IUser::Mount(Kernel::HLERequestContext& ctx) {
120 LOG_DEBUG(Service_NFP, "called"); 143 IPC::RequestParser rp{ctx};
144 const auto device_handle{rp.Pop<u64>()};
145 const auto model_type{rp.PopEnum<ModelType>()};
146 const auto mount_target{rp.PopEnum<MountTarget>()};
147 LOG_INFO(Service_NFP, "called, device_handle={}, model_type={}, mount_target={}", device_handle,
148 model_type, mount_target);
149
150 // TODO(german77): Loop through all interfaces
151 if (device_handle == nfp_interface.GetHandle()) {
152 const auto result = nfp_interface.Mount();
153 IPC::ResponseBuilder rb{ctx, 2};
154 rb.Push(result);
155 return;
156 }
157
158 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
121 159
122 device_state = DeviceState::TagMounted;
123 IPC::ResponseBuilder rb{ctx, 2}; 160 IPC::ResponseBuilder rb{ctx, 2};
124 rb.Push(ResultSuccess); 161 rb.Push(ErrCodes::DeviceNotFound);
125} 162}
126 163
127void IUser::Unmount(Kernel::HLERequestContext& ctx) { 164void IUser::Unmount(Kernel::HLERequestContext& ctx) {
128 LOG_DEBUG(Service_NFP, "called"); 165 IPC::RequestParser rp{ctx};
166 const auto device_handle{rp.Pop<u64>()};
167 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
168
169 // TODO(german77): Loop through all interfaces
170 if (device_handle == nfp_interface.GetHandle()) {
171 const auto result = nfp_interface.Unmount();
172 IPC::ResponseBuilder rb{ctx, 2};
173 rb.Push(result);
174 return;
175 }
129 176
130 device_state = DeviceState::TagFound; 177 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
131 178
132 IPC::ResponseBuilder rb{ctx, 2}; 179 IPC::ResponseBuilder rb{ctx, 2};
133 rb.Push(ResultSuccess); 180 rb.Push(ErrCodes::DeviceNotFound);
134} 181}
135 182
136void IUser::OpenApplicationArea(Kernel::HLERequestContext& ctx) { 183void IUser::OpenApplicationArea(Kernel::HLERequestContext& ctx) {
137 LOG_WARNING(Service_NFP, "(STUBBED) called"); 184 IPC::RequestParser rp{ctx};
185 const auto device_handle{rp.Pop<u64>()};
186 const auto access_id{rp.Pop<u32>()};
187 LOG_INFO(Service_NFP, "called, device_handle={}, access_id={}", device_handle, access_id);
188
189 // TODO(german77): Loop through all interfaces
190 if (device_handle == nfp_interface.GetHandle()) {
191 const auto result = nfp_interface.OpenApplicationArea(access_id);
192 IPC::ResponseBuilder rb{ctx, 2};
193 rb.Push(result);
194 return;
195 }
196
197 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
198
138 IPC::ResponseBuilder rb{ctx, 2}; 199 IPC::ResponseBuilder rb{ctx, 2};
139 rb.Push(ErrCodes::ERR_NO_APPLICATION_AREA); 200 rb.Push(ErrCodes::DeviceNotFound);
140} 201}
141 202
142void IUser::GetApplicationArea(Kernel::HLERequestContext& ctx) { 203void IUser::GetApplicationArea(Kernel::HLERequestContext& ctx) {
143 LOG_WARNING(Service_NFP, "(STUBBED) called"); 204 IPC::RequestParser rp{ctx};
205 const auto device_handle{rp.Pop<u64>()};
206 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
207
208 // TODO(german77): Loop through all interfaces
209 if (device_handle == nfp_interface.GetHandle()) {
210 std::vector<u8> data{};
211 const auto result = nfp_interface.GetApplicationArea(data);
212
213 ctx.WriteBuffer(data);
214 IPC::ResponseBuilder rb{ctx, 3};
215 rb.Push(result);
216 rb.PushRaw<u32>(data.size());
217 return;
218 }
144 219
145 // TODO(ogniK): Pull application area from amiibo 220 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
146 221
147 IPC::ResponseBuilder rb{ctx, 3}; 222 IPC::ResponseBuilder rb{ctx, 2};
148 rb.Push(ResultSuccess); 223 rb.Push(ErrCodes::DeviceNotFound);
149 rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub 224}
225
226void IUser::SetApplicationArea(Kernel::HLERequestContext& ctx) {
227 IPC::RequestParser rp{ctx};
228 const auto device_handle{rp.Pop<u64>()};
229 const auto data{ctx.ReadBuffer()};
230 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}", device_handle, data.size());
231
232 // TODO(german77): Loop through all interfaces
233 if (device_handle == nfp_interface.GetHandle()) {
234 const auto result = nfp_interface.SetApplicationArea(data);
235
236 IPC::ResponseBuilder rb{ctx, 2};
237 rb.Push(result);
238 return;
239 }
240
241 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
242
243 IPC::ResponseBuilder rb{ctx, 2};
244 rb.Push(ErrCodes::DeviceNotFound);
245}
246
247void IUser::CreateApplicationArea(Kernel::HLERequestContext& ctx) {
248 IPC::RequestParser rp{ctx};
249 const auto device_handle{rp.Pop<u64>()};
250 const auto access_id{rp.Pop<u32>()};
251 const auto data{ctx.ReadBuffer()};
252 LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle,
253 access_id, data.size());
254
255 // TODO(german77): Loop through all interfaces
256 if (device_handle == nfp_interface.GetHandle()) {
257 const auto result = nfp_interface.CreateApplicationArea(access_id, data);
258
259 IPC::ResponseBuilder rb{ctx, 2};
260 rb.Push(result);
261 return;
262 }
263
264 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
265
266 IPC::ResponseBuilder rb{ctx, 2};
267 rb.Push(ErrCodes::DeviceNotFound);
150} 268}
151 269
152void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) { 270void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) {
153 LOG_DEBUG(Service_NFP, "called"); 271 IPC::RequestParser rp{ctx};
272 const auto device_handle{rp.Pop<u64>()};
273 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
274
275 // TODO(german77): Loop through all interfaces
276 if (device_handle == nfp_interface.GetHandle()) {
277 TagInfo tag_info{};
278 const auto result = nfp_interface.GetTagInfo(tag_info);
279 ctx.WriteBuffer(tag_info);
280 IPC::ResponseBuilder rb{ctx, 2};
281 rb.Push(result);
282 return;
283 }
284
285 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
154 286
155 IPC::ResponseBuilder rb{ctx, 2}; 287 IPC::ResponseBuilder rb{ctx, 2};
156 const auto& amiibo = nfp_interface.GetAmiiboBuffer(); 288 rb.Push(ErrCodes::DeviceNotFound);
157 const TagInfo tag_info{
158 .uuid = amiibo.uuid,
159 .uuid_length = static_cast<u8>(amiibo.uuid.size()),
160 .protocol = 1, // TODO(ogniK): Figure out actual values
161 .tag_type = 2,
162 };
163 ctx.WriteBuffer(tag_info);
164 rb.Push(ResultSuccess);
165} 289}
166 290
167void IUser::GetRegisterInfo(Kernel::HLERequestContext& ctx) { 291void IUser::GetRegisterInfo(Kernel::HLERequestContext& ctx) {
168 LOG_WARNING(Service_NFP, "(STUBBED) called"); 292 IPC::RequestParser rp{ctx};
293 const auto device_handle{rp.Pop<u64>()};
294 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
295
296 // TODO(german77): Loop through all interfaces
297 if (device_handle == nfp_interface.GetHandle()) {
298 RegisterInfo register_info{};
299 const auto result = nfp_interface.GetRegisterInfo(register_info);
300 ctx.WriteBuffer(register_info);
301 IPC::ResponseBuilder rb{ctx, 2};
302 rb.Push(result);
303 return;
304 }
169 305
170 // TODO(ogniK): Pull Mii and owner data from amiibo 306 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
171 307
172 IPC::ResponseBuilder rb{ctx, 2}; 308 IPC::ResponseBuilder rb{ctx, 2};
173 rb.Push(ResultSuccess); 309 rb.Push(ErrCodes::DeviceNotFound);
174} 310}
175 311
176void IUser::GetCommonInfo(Kernel::HLERequestContext& ctx) { 312void IUser::GetCommonInfo(Kernel::HLERequestContext& ctx) {
177 LOG_WARNING(Service_NFP, "(STUBBED) called"); 313 IPC::RequestParser rp{ctx};
178 314 const auto device_handle{rp.Pop<u64>()};
179 // TODO(ogniK): Pull common information from amiibo 315 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
316
317 // TODO(german77): Loop through all interfaces
318 if (device_handle == nfp_interface.GetHandle()) {
319 CommonInfo common_info{};
320 const auto result = nfp_interface.GetCommonInfo(common_info);
321 ctx.WriteBuffer(common_info);
322 IPC::ResponseBuilder rb{ctx, 2};
323 rb.Push(result);
324 return;
325 }
180 326
181 CommonInfo common_info{}; 327 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
182 common_info.application_area_size = 0;
183 ctx.WriteBuffer(common_info);
184 328
185 IPC::ResponseBuilder rb{ctx, 2}; 329 IPC::ResponseBuilder rb{ctx, 2};
186 rb.Push(ResultSuccess); 330 rb.Push(ErrCodes::DeviceNotFound);
187} 331}
188 332
189void IUser::GetModelInfo(Kernel::HLERequestContext& ctx) { 333void IUser::GetModelInfo(Kernel::HLERequestContext& ctx) {
190 LOG_DEBUG(Service_NFP, "called"); 334 IPC::RequestParser rp{ctx};
335 const auto device_handle{rp.Pop<u64>()};
336 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
337
338 // TODO(german77): Loop through all interfaces
339 if (device_handle == nfp_interface.GetHandle()) {
340 ModelInfo model_info{};
341 const auto result = nfp_interface.GetModelInfo(model_info);
342 ctx.WriteBuffer(model_info);
343 IPC::ResponseBuilder rb{ctx, 2};
344 rb.Push(ResultSuccess);
345 return;
346 }
347
348 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
191 349
192 IPC::ResponseBuilder rb{ctx, 2}; 350 IPC::ResponseBuilder rb{ctx, 2};
193 const auto& amiibo = nfp_interface.GetAmiiboBuffer(); 351 rb.Push(ErrCodes::DeviceNotFound);
194 ctx.WriteBuffer(amiibo.model_info);
195 rb.Push(ResultSuccess);
196} 352}
197 353
198void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) { 354void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) {
199 IPC::RequestParser rp{ctx}; 355 IPC::RequestParser rp{ctx};
200 const u64 dev_handle = rp.Pop<u64>(); 356 const auto device_handle{rp.Pop<u64>()};
201 LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); 357 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
358
359 // TODO(german77): Loop through all interfaces
360 if (device_handle == nfp_interface.GetHandle()) {
361 IPC::ResponseBuilder rb{ctx, 2, 1};
362 rb.Push(ResultSuccess);
363 rb.PushCopyObjects(nfp_interface.GetActivateEvent());
364 return;
365 }
202 366
203 IPC::ResponseBuilder rb{ctx, 2, 1}; 367 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
204 rb.Push(ResultSuccess); 368
205 rb.PushCopyObjects(nfp_interface.GetNFCEvent()); 369 IPC::ResponseBuilder rb{ctx, 2};
206 has_attached_handle = true; 370 rb.Push(ErrCodes::DeviceNotFound);
207} 371}
208 372
209void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { 373void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) {
210 IPC::RequestParser rp{ctx}; 374 IPC::RequestParser rp{ctx};
211 const u64 dev_handle = rp.Pop<u64>(); 375 const auto device_handle{rp.Pop<u64>()};
212 LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); 376 LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
377
378 // TODO(german77): Loop through all interfaces
379 if (device_handle == nfp_interface.GetHandle()) {
380 IPC::ResponseBuilder rb{ctx, 2, 1};
381 rb.Push(ResultSuccess);
382 rb.PushCopyObjects(nfp_interface.GetDeactivateEvent());
383 return;
384 }
213 385
214 IPC::ResponseBuilder rb{ctx, 2, 1}; 386 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
215 rb.Push(ResultSuccess); 387
216 rb.PushCopyObjects(deactivate_event.GetReadableEvent()); 388 IPC::ResponseBuilder rb{ctx, 2};
389 rb.Push(ErrCodes::DeviceNotFound);
217} 390}
218 391
219void IUser::GetState(Kernel::HLERequestContext& ctx) { 392void IUser::GetState(Kernel::HLERequestContext& ctx) {
220 LOG_DEBUG(Service_NFC, "called"); 393 LOG_INFO(Service_NFC, "called");
221 394
222 IPC::ResponseBuilder rb{ctx, 3, 0}; 395 IPC::ResponseBuilder rb{ctx, 3, 0};
223 rb.Push(ResultSuccess); 396 rb.Push(ResultSuccess);
224 rb.PushRaw<u32>(static_cast<u32>(state)); 397 rb.PushEnum(state);
225} 398}
226 399
227void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) { 400void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) {
228 LOG_DEBUG(Service_NFP, "called"); 401 IPC::RequestParser rp{ctx};
402 const auto device_handle{rp.Pop<u64>()};
403 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
404
405 // TODO(german77): Loop through all interfaces
406 if (device_handle == nfp_interface.GetHandle()) {
407 IPC::ResponseBuilder rb{ctx, 3};
408 rb.Push(ResultSuccess);
409 rb.PushEnum(nfp_interface.GetCurrentState());
410 return;
411 }
229 412
230 IPC::ResponseBuilder rb{ctx, 3}; 413 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
231 rb.Push(ResultSuccess); 414
232 rb.Push<u32>(static_cast<u32>(device_state)); 415 IPC::ResponseBuilder rb{ctx, 2};
416 rb.Push(ErrCodes::DeviceNotFound);
233} 417}
234 418
235void IUser::GetNpadId(Kernel::HLERequestContext& ctx) { 419void IUser::GetNpadId(Kernel::HLERequestContext& ctx) {
236 IPC::RequestParser rp{ctx}; 420 IPC::RequestParser rp{ctx};
237 const u64 dev_handle = rp.Pop<u64>(); 421 const auto device_handle{rp.Pop<u64>()};
238 LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); 422 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
423
424 // TODO(german77): Loop through all interfaces
425 if (device_handle == nfp_interface.GetHandle()) {
426 IPC::ResponseBuilder rb{ctx, 3};
427 rb.Push(ResultSuccess);
428 rb.PushEnum(nfp_interface.GetNpadId());
429 return;
430 }
239 431
240 IPC::ResponseBuilder rb{ctx, 3}; 432 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
241 rb.Push(ResultSuccess); 433
242 rb.Push<u32>(npad_id); 434 IPC::ResponseBuilder rb{ctx, 2};
435 rb.Push(ErrCodes::DeviceNotFound);
243} 436}
244 437
245void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) { 438void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) {
246 LOG_WARNING(Service_NFP, "(STUBBED) called"); 439 IPC::RequestParser rp{ctx};
247 // We don't need to worry about this since we can just open the file 440 const auto device_handle{rp.Pop<u64>()};
248 IPC::ResponseBuilder rb{ctx, 3}; 441 LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
249 rb.Push(ResultSuccess); 442
250 rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub 443 // TODO(german77): Loop through all interfaces
444 if (device_handle == nfp_interface.GetHandle()) {
445 IPC::ResponseBuilder rb{ctx, 3};
446 rb.Push(ResultSuccess);
447 rb.Push(ApplicationAreaSize);
448 return;
449 }
450
451 LOG_ERROR(Service_NFP, "Handle not found, device_handle={}", device_handle);
452
453 IPC::ResponseBuilder rb{ctx, 2};
454 rb.Push(ErrCodes::DeviceNotFound);
251} 455}
252 456
253void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { 457void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) {
254 LOG_WARNING(Service_NFP, "(STUBBED) called"); 458 LOG_DEBUG(Service_NFP, "(STUBBED) called");
255 459
256 IPC::ResponseBuilder rb{ctx, 2, 1}; 460 IPC::ResponseBuilder rb{ctx, 2, 1};
257 rb.Push(ResultSuccess); 461 rb.Push(ResultSuccess);
258 rb.PushCopyObjects(availability_change_event.GetReadableEvent()); 462 rb.PushCopyObjects(availability_change_event->GetReadableEvent());
259} 463}
260 464
261Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, 465Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_,
262 const char* name) 466 const char* name)
263 : ServiceFramework{system_, name}, nfc_tag_load{system.Kernel()}, module{std::move(module_)} { 467 : ServiceFramework{system_, name}, module{std::move(module_)},
264 Kernel::KAutoObject::Create(std::addressof(nfc_tag_load)); 468 npad_id{Core::HID::NpadIdType::Player1}, service_context{system_, service_name} {
265 nfc_tag_load.Initialize("IUser:NFCTagDetected"); 469 activate_event = service_context.CreateEvent("IUser:NFPActivateEvent");
470 deactivate_event = service_context.CreateEvent("IUser:NFPDeactivateEvent");
266} 471}
267 472
268Module::Interface::~Interface() = default; 473Module::Interface::~Interface() = default;
@@ -272,25 +477,254 @@ void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
272 477
273 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 478 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
274 rb.Push(ResultSuccess); 479 rb.Push(ResultSuccess);
275 rb.PushIpcInterface<IUser>(*this, system, service_context); 480 rb.PushIpcInterface<IUser>(*this, system);
276} 481}
277 482
278bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) { 483bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
279 if (buffer.size() < sizeof(AmiiboFile)) { 484 if (buffer.size() < sizeof(AmiiboFile)) {
485 LOG_ERROR(Service_NFP, "Wrong file size");
280 return false; 486 return false;
281 } 487 }
282 488
489 if (device_state != DeviceState::SearchingForTag) {
490 LOG_ERROR(Service_NFP, "Game is not looking for amiibos, current state {}", device_state);
491 return false;
492 }
493
494 LOG_INFO(Service_NFP, "New Amiibo detected");
283 std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); 495 std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
284 nfc_tag_load->GetWritableEvent().Signal(); 496 device_state = DeviceState::TagFound;
497 activate_event->GetWritableEvent().Signal();
285 return true; 498 return true;
286} 499}
287 500
288Kernel::KReadableEvent& Module::Interface::GetNFCEvent() { 501void Module::Interface::CloseAmiibo() {
289 return nfc_tag_load->GetReadableEvent(); 502 LOG_INFO(Service_NFP, "Remove amiibo");
503 device_state = DeviceState::TagRemoved;
504 write_counter = 0;
505 is_application_area_initialized = false;
506 application_area_id = 0;
507 application_area_data.clear();
508 deactivate_event->GetWritableEvent().Signal();
509}
510
511Kernel::KReadableEvent& Module::Interface::GetActivateEvent() const {
512 return activate_event->GetReadableEvent();
513}
514
515Kernel::KReadableEvent& Module::Interface::GetDeactivateEvent() const {
516 return deactivate_event->GetReadableEvent();
517}
518
519void Module::Interface::Initialize() {
520 device_state = DeviceState::Initialized;
521}
522
523void Module::Interface::Finalize() {
524 device_state = DeviceState::Unaviable;
525 write_counter = 0;
526 is_application_area_initialized = false;
527 application_area_id = 0;
528 application_area_data.clear();
529}
530
531ResultCode Module::Interface::StartDetection() {
532 auto npad_device = system.HIDCore().GetEmulatedController(npad_id);
533
534 // TODO(german77): Add callback for when nfc data is available
535
536 if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
537 npad_device->SetPollingMode(Common::Input::PollingMode::NFC);
538 device_state = DeviceState::SearchingForTag;
539 return ResultSuccess;
540 }
541
542 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
543 return ErrCodes::WrongDeviceState;
544}
545
546ResultCode Module::Interface::StopDetection() {
547 auto npad_device = system.HIDCore().GetEmulatedController(npad_id);
548 npad_device->SetPollingMode(Common::Input::PollingMode::Active);
549
550 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
551 CloseAmiibo();
552 return ResultSuccess;
553 }
554 if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {
555 device_state = DeviceState::Initialized;
556 return ResultSuccess;
557 }
558
559 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
560 return ErrCodes::WrongDeviceState;
561}
562
563ResultCode Module::Interface::Mount() {
564 if (device_state == DeviceState::TagFound) {
565 device_state = DeviceState::TagMounted;
566 return ResultSuccess;
567 }
568
569 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
570 return ErrCodes::WrongDeviceState;
571}
572
573ResultCode Module::Interface::Unmount() {
574 if (device_state == DeviceState::TagMounted) {
575 is_application_area_initialized = false;
576 application_area_id = 0;
577 application_area_data.clear();
578 device_state = DeviceState::TagFound;
579 return ResultSuccess;
580 }
581
582 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
583 return ErrCodes::WrongDeviceState;
584}
585
586ResultCode Module::Interface::GetTagInfo(TagInfo& tag_info) const {
587 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
588 // Read this data from the amiibo save file
589 tag_info = {
590 .uuid = amiibo.uuid,
591 .uuid_length = static_cast<u8>(amiibo.uuid.size()),
592 .protocol = 0xFFFFFFFF, // TODO(ogniK): Figure out actual values
593 .tag_type = 0xFFFFFFFF,
594 };
595 return ResultSuccess;
596 }
597
598 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
599 return ErrCodes::WrongDeviceState;
600}
601
602ResultCode Module::Interface::GetCommonInfo(CommonInfo& common_info) const {
603 if (device_state != DeviceState::TagMounted) {
604 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
605 return ErrCodes::WrongDeviceState;
606 }
607
608 // Read this data from the amiibo save file
609 common_info = {
610 .last_write_year = 2022,
611 .last_write_month = 2,
612 .last_write_day = 7,
613 .write_counter = write_counter,
614 .version = 1,
615 .application_area_size = ApplicationAreaSize,
616 };
617 return ResultSuccess;
618}
619
620ResultCode Module::Interface::GetModelInfo(ModelInfo& model_info) const {
621 if (device_state != DeviceState::TagMounted) {
622 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
623 return ErrCodes::WrongDeviceState;
624 }
625
626 model_info = amiibo.model_info;
627 return ResultSuccess;
628}
629
630ResultCode Module::Interface::GetRegisterInfo(RegisterInfo& register_info) const {
631 if (device_state != DeviceState::TagMounted) {
632 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
633 return ErrCodes::WrongDeviceState;
634 }
635
636 Service::Mii::MiiManager manager;
637
638 // Read this data from the amiibo save file
639 register_info = {
640 .mii_char_info = manager.BuildDefault(0),
641 .first_write_year = 2022,
642 .first_write_month = 2,
643 .first_write_day = 7,
644 .amiibo_name = {'Y', 'u', 'z', 'u', 'A', 'm', 'i', 'i', 'b', 'o', 0},
645 .unknown = {},
646 };
647 return ResultSuccess;
648}
649
650ResultCode Module::Interface::OpenApplicationArea(u32 access_id) {
651 if (device_state != DeviceState::TagMounted) {
652 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
653 return ErrCodes::WrongDeviceState;
654 }
655 // if (AmiiboApplicationDataExist(access_id)) {
656 // application_area_data = LoadAmiiboApplicationData(access_id);
657 // application_area_id = access_id;
658 // is_application_area_initialized = true;
659 // }
660 if (!is_application_area_initialized) {
661 LOG_ERROR(Service_NFP, "Application area is not initialized");
662 return ErrCodes::ApplicationAreaIsNotInitialized;
663 }
664 return ResultSuccess;
665}
666
667ResultCode Module::Interface::GetApplicationArea(std::vector<u8>& data) const {
668 if (device_state != DeviceState::TagMounted) {
669 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
670 return ErrCodes::WrongDeviceState;
671 }
672 if (!is_application_area_initialized) {
673 LOG_ERROR(Service_NFP, "Application area is not initialized");
674 return ErrCodes::ApplicationAreaIsNotInitialized;
675 }
676
677 data = application_area_data;
678
679 return ResultSuccess;
680}
681
682ResultCode Module::Interface::SetApplicationArea(const std::vector<u8>& data) {
683 if (device_state != DeviceState::TagMounted) {
684 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
685 return ErrCodes::WrongDeviceState;
686 }
687 if (!is_application_area_initialized) {
688 LOG_ERROR(Service_NFP, "Application area is not initialized");
689 return ErrCodes::ApplicationAreaIsNotInitialized;
690 }
691 application_area_data = data;
692 write_counter++;
693 // SaveAmiiboApplicationData(application_area_id,application_area_data);
694 return ResultSuccess;
695}
696
697ResultCode Module::Interface::CreateApplicationArea(u32 access_id, const std::vector<u8>& data) {
698 if (device_state != DeviceState::TagMounted) {
699 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
700 return ErrCodes::WrongDeviceState;
701 }
702 // if (AmiiboApplicationDataExist(access_id)) {
703 // LOG_ERROR(Service_NFP, "Application area already exist");
704 // return ErrCodes::ApplicationAreaExist;
705 // }
706 // if (LoadAmiiboApplicationData(access_id,data)) {
707 // is_application_area_initialized = true;
708 // application_area_id = access_id;
709 // }
710 application_area_data = data;
711 application_area_id = access_id;
712 write_counter = 0;
713 // SaveAmiiboApplicationData(application_area_id,application_area_data);
714 return ResultSuccess;
715}
716
717u64 Module::Interface::GetHandle() const {
718 // Generate a handle based of the npad id
719 return static_cast<u64>(npad_id);
720}
721
722DeviceState Module::Interface::GetCurrentState() const {
723 return device_state;
290} 724}
291 725
292const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const { 726Core::HID::NpadIdType Module::Interface::GetNpadId() const {
293 return amiibo; 727 return npad_id;
294} 728}
295 729
296void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { 730void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 8d9db880a..4642ed634 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -8,79 +8,155 @@
8#include <vector> 8#include <vector>
9 9
10#include "core/hle/service/kernel_helpers.h" 10#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/kernel/k_event.h" 11#include "core/hle/service/mii/mii_manager.h"
12#include "core/hle/service/mii/manager.h"
13#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
14 13
15namespace Kernel { 14namespace Kernel {
16class KEvent; 15class KEvent;
17} 16class KReadableEvent;
17} // namespace Kernel
18
19namespace Core::HID {
20enum class NpadIdType : u32;
21} // namespace Core::HID
18 22
19namespace Service::NFP { 23namespace Service::NFP {
20 24
21enum class ServiceType : u32 { 25enum class ServiceType : u32 {
22 User = 0, 26 User,
23 Debug = 1, 27 Debug,
24 System = 2, 28 System,
25}; 29};
26 30
27enum class State : u32 { 31enum class State : u32 {
28 NonInitialized = 0, 32 NonInitialized,
29 Initialized = 1, 33 Initialized,
30}; 34};
31 35
32enum class DeviceState : u32 { 36enum class DeviceState : u32 {
33 Initialized = 0, 37 Initialized,
34 SearchingForTag = 1, 38 SearchingForTag,
35 TagFound = 2, 39 TagFound,
36 TagRemoved = 3, 40 TagRemoved,
37 TagMounted = 4, 41 TagMounted,
38 Unaviable = 5, 42 Unaviable,
39 Finalized = 6 43 Finalized,
44};
45
46enum class ModelType : u32 {
47 Amiibo,
40}; 48};
41 49
42enum class MountTarget : u32 { 50enum class MountTarget : u32 {
43 Rom = 1, 51 Rom,
44 Ram = 2, 52 Ram,
45 All = 3, 53 All,
46}; 54};
47 55
48struct TagInfo { 56struct TagInfo {
49 std::array<u8, 10> uuid; 57 std::array<u8, 10> uuid;
50 u8 uuid_length; 58 u8 uuid_length;
51 INSERT_PADDING_BYTES(0x15); 59 INSERT_PADDING_BYTES(0x15);
52 u32_le protocol; 60 u32 protocol;
53 u32_le tag_type; 61 u32 tag_type;
54 INSERT_PADDING_BYTES(0x2c); 62 INSERT_PADDING_BYTES(0x30);
55}; 63};
56static_assert(sizeof(TagInfo) == 0x54, "TagInfo is an invalid size"); 64static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size");
57 65
58struct CommonInfo { 66struct CommonInfo {
59 u16_be last_write_year; 67 u16 last_write_year;
60 u8 last_write_month; 68 u8 last_write_month;
61 u8 last_write_day; 69 u8 last_write_day;
62 u16_be write_counter; 70 u16 write_counter;
63 u16_be version; 71 u16 version;
64 u32_be application_area_size; 72 u32 application_area_size;
65 INSERT_PADDING_BYTES(0x34); 73 INSERT_PADDING_BYTES(0x34);
66}; 74};
67static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size"); 75static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size");
68 76
69struct ModelInfo { 77struct ModelInfo {
70 std::array<u8, 0x8> ammibo_id; 78 u16 character_id;
71 INSERT_PADDING_BYTES(0x38); 79 u8 character_variant;
80 u8 figure_type;
81 u16 model_number;
82 u8 series;
83 INSERT_PADDING_BYTES(0x39);
72}; 84};
73static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size"); 85static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
74 86
75struct RegisterInfo { 87struct RegisterInfo {
76 Service::Mii::MiiInfo mii; 88 Service::Mii::MiiInfo mii_char_info;
77 u16_be first_write_year; 89 u16 first_write_year;
78 u8 first_write_month; 90 u8 first_write_month;
79 u8 first_write_day; 91 u8 first_write_day;
80 std::array<u8, 11> amiibo_name; 92 std::array<u8, 11> amiibo_name;
81 INSERT_PADDING_BYTES(0x99); 93 u8 unknown;
94 INSERT_PADDING_BYTES(0x98);
95};
96static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
97
98class Module final {
99public:
100 class Interface : public ServiceFramework<Interface> {
101 public:
102 explicit Interface(std::shared_ptr<Module> module_, Core::System& system_,
103 const char* name);
104 ~Interface() override;
105
106 struct AmiiboFile {
107 std::array<u8, 10> uuid;
108 INSERT_PADDING_BYTES(0x4); // Compability container
109 INSERT_PADDING_BYTES(0x46);
110 ModelInfo model_info;
111 };
112 static_assert(sizeof(AmiiboFile) == 0x94, "AmiiboFile is an invalid size");
113
114 void CreateUserInterface(Kernel::HLERequestContext& ctx);
115 bool LoadAmiibo(const std::vector<u8>& buffer);
116 void CloseAmiibo();
117
118 void Initialize();
119 void Finalize();
120
121 ResultCode StartDetection();
122 ResultCode StopDetection();
123 ResultCode Mount();
124 ResultCode Unmount();
125
126 ResultCode GetTagInfo(TagInfo& tag_info) const;
127 ResultCode GetCommonInfo(CommonInfo& common_info) const;
128 ResultCode GetModelInfo(ModelInfo& model_info) const;
129 ResultCode GetRegisterInfo(RegisterInfo& register_info) const;
130
131 ResultCode OpenApplicationArea(u32 access_id);
132 ResultCode GetApplicationArea(std::vector<u8>& data) const;
133 ResultCode SetApplicationArea(const std::vector<u8>& data);
134 ResultCode CreateApplicationArea(u32 access_id, const std::vector<u8>& data);
135
136 u64 GetHandle() const;
137 DeviceState GetCurrentState() const;
138 Core::HID::NpadIdType GetNpadId() const;
139
140 Kernel::KReadableEvent& GetActivateEvent() const;
141 Kernel::KReadableEvent& GetDeactivateEvent() const;
142
143 protected:
144 std::shared_ptr<Module> module;
145
146 private:
147 const Core::HID::NpadIdType npad_id;
148
149 DeviceState device_state{DeviceState::Unaviable};
150 KernelHelpers::ServiceContext service_context;
151 Kernel::KEvent* activate_event;
152 Kernel::KEvent* deactivate_event;
153 AmiiboFile amiibo{};
154 u16 write_counter{};
155 bool is_application_area_initialized{};
156 u32 application_area_id;
157 std::vector<u8> application_area_data;
158 };
82}; 159};
83// static_assert(sizeof(RegisterInfo) == 0x106, "RegisterInfo is an invalid size");
84 160
85class IUser final : public ServiceFramework<IUser> { 161class IUser final : public ServiceFramework<IUser> {
86public: 162public:
@@ -96,6 +172,8 @@ private:
96 void Unmount(Kernel::HLERequestContext& ctx); 172 void Unmount(Kernel::HLERequestContext& ctx);
97 void OpenApplicationArea(Kernel::HLERequestContext& ctx); 173 void OpenApplicationArea(Kernel::HLERequestContext& ctx);
98 void GetApplicationArea(Kernel::HLERequestContext& ctx); 174 void GetApplicationArea(Kernel::HLERequestContext& ctx);
175 void SetApplicationArea(Kernel::HLERequestContext& ctx);
176 void CreateApplicationArea(Kernel::HLERequestContext& ctx);
99 void GetTagInfo(Kernel::HLERequestContext& ctx); 177 void GetTagInfo(Kernel::HLERequestContext& ctx);
100 void GetRegisterInfo(Kernel::HLERequestContext& ctx); 178 void GetRegisterInfo(Kernel::HLERequestContext& ctx);
101 void GetCommonInfo(Kernel::HLERequestContext& ctx); 179 void GetCommonInfo(Kernel::HLERequestContext& ctx);
@@ -108,50 +186,13 @@ private:
108 void GetApplicationAreaSize(Kernel::HLERequestContext& ctx); 186 void GetApplicationAreaSize(Kernel::HLERequestContext& ctx);
109 void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx); 187 void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx);
110 188
111 bool has_attached_handle{}; 189 KernelHelpers::ServiceContext service_context;
112 const u64 device_handle{0}; // Npad device 1
113 const u32 npad_id{0}; // Player 1 controller
114 State state{State::NonInitialized};
115 DeviceState device_state{DeviceState::Initialized};
116 Module::Interface& nfp_interface;
117 Kernel::KEvent deactivate_event;
118 Kernel::KEvent availability_change_event;
119};
120 190
121class Module final { 191 // TODO(german77): We should have a vector of interfaces
122public: 192 Module::Interface& nfp_interface;
123 class Interface : public ServiceFramework<Interface> {
124 public:
125 explicit Interface(std::shared_ptr<Module> module_, Core::System& system_,
126 const char* name);
127 ~Interface() override;
128
129 struct ModelInfo {
130 std::array<u8, 0x8> amiibo_identification_block;
131 INSERT_PADDING_BYTES(0x38);
132 };
133 static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size");
134
135 struct AmiiboFile {
136 std::array<u8, 10> uuid;
137 INSERT_PADDING_BYTES(0x4a);
138 ModelInfo model_info;
139 };
140 static_assert(sizeof(AmiiboFile) == 0x94, "AmiiboFile is an invalid size");
141
142 void CreateUserInterface(Kernel::HLERequestContext& ctx);
143 bool LoadAmiibo(const std::vector<u8>& buffer);
144 Kernel::KReadableEvent& GetNFCEvent();
145 const AmiiboFile& GetAmiiboBuffer() const;
146
147 protected:
148 std::shared_ptr<Module> module;
149 193
150 private: 194 State state{State::NonInitialized};
151 KernelHelpers::ServiceContext service_context; 195 Kernel::KEvent* availability_change_event;
152 Kernel::KEvent* nfc_tag_load;
153 AmiiboFile amiibo{};
154 };
155}; 196};
156 197
157void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); 198void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);