nfp_user.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <array>
  4. #include <atomic>
  5. #include "common/logging/log.h"
  6. #include "core/core.h"
  7. #include "core/hid/hid_types.h"
  8. #include "core/hle/ipc_helpers.h"
  9. #include "core/hle/kernel/k_event.h"
  10. #include "core/hle/service/nfp/nfp_device.h"
  11. #include "core/hle/service/nfp/nfp_result.h"
  12. #include "core/hle/service/nfp/nfp_user.h"
  13. namespace Service::NFP {
  14. IUser::IUser(Core::System& system_)
  15. : ServiceFramework{system_, "NFP::IUser"}, service_context{system_, service_name} {
  16. static const FunctionInfo functions[] = {
  17. {0, &IUser::Initialize, "Initialize"},
  18. {1, &IUser::Finalize, "Finalize"},
  19. {2, &IUser::ListDevices, "ListDevices"},
  20. {3, &IUser::StartDetection, "StartDetection"},
  21. {4, &IUser::StopDetection, "StopDetection"},
  22. {5, &IUser::Mount, "Mount"},
  23. {6, &IUser::Unmount, "Unmount"},
  24. {7, &IUser::OpenApplicationArea, "OpenApplicationArea"},
  25. {8, &IUser::GetApplicationArea, "GetApplicationArea"},
  26. {9, &IUser::SetApplicationArea, "SetApplicationArea"},
  27. {10, &IUser::Flush, "Flush"},
  28. {11, &IUser::Restore, "Restore"},
  29. {12, &IUser::CreateApplicationArea, "CreateApplicationArea"},
  30. {13, &IUser::GetTagInfo, "GetTagInfo"},
  31. {14, &IUser::GetRegisterInfo, "GetRegisterInfo"},
  32. {15, &IUser::GetCommonInfo, "GetCommonInfo"},
  33. {16, &IUser::GetModelInfo, "GetModelInfo"},
  34. {17, &IUser::AttachActivateEvent, "AttachActivateEvent"},
  35. {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"},
  36. {19, &IUser::GetState, "GetState"},
  37. {20, &IUser::GetDeviceState, "GetDeviceState"},
  38. {21, &IUser::GetNpadId, "GetNpadId"},
  39. {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"},
  40. {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"},
  41. {24, &IUser::RecreateApplicationArea, "RecreateApplicationArea"},
  42. };
  43. RegisterHandlers(functions);
  44. availability_change_event = service_context.CreateEvent("IUser:AvailabilityChangeEvent");
  45. for (u32 device_index = 0; device_index < 10; device_index++) {
  46. devices[device_index] =
  47. std::make_shared<NfpDevice>(Core::HID::IndexToNpadIdType(device_index), system,
  48. service_context, availability_change_event);
  49. }
  50. }
  51. void IUser::Initialize(Kernel::HLERequestContext& ctx) {
  52. LOG_INFO(Service_NFC, "called");
  53. state = State::Initialized;
  54. for (auto& device : devices) {
  55. device->Initialize();
  56. }
  57. IPC::ResponseBuilder rb{ctx, 2, 0};
  58. rb.Push(ResultSuccess);
  59. }
  60. void IUser::Finalize(Kernel::HLERequestContext& ctx) {
  61. LOG_INFO(Service_NFP, "called");
  62. state = State::NonInitialized;
  63. for (auto& device : devices) {
  64. device->Finalize();
  65. }
  66. IPC::ResponseBuilder rb{ctx, 2};
  67. rb.Push(ResultSuccess);
  68. }
  69. void IUser::ListDevices(Kernel::HLERequestContext& ctx) {
  70. LOG_INFO(Service_NFP, "called");
  71. if (state == State::NonInitialized) {
  72. IPC::ResponseBuilder rb{ctx, 2};
  73. rb.Push(NfcDisabled);
  74. return;
  75. }
  76. if (!ctx.CanWriteBuffer()) {
  77. IPC::ResponseBuilder rb{ctx, 2};
  78. rb.Push(InvalidArgument);
  79. return;
  80. }
  81. if (ctx.GetWriteBufferSize() == 0) {
  82. IPC::ResponseBuilder rb{ctx, 2};
  83. rb.Push(InvalidArgument);
  84. return;
  85. }
  86. std::vector<u64> nfp_devices;
  87. const std::size_t max_allowed_devices = ctx.GetWriteBufferSize() / sizeof(u64);
  88. for (auto& device : devices) {
  89. if (nfp_devices.size() >= max_allowed_devices) {
  90. continue;
  91. }
  92. if (device->GetCurrentState() != DeviceState::Unavailable) {
  93. nfp_devices.push_back(device->GetHandle());
  94. }
  95. }
  96. if (nfp_devices.size() == 0) {
  97. IPC::ResponseBuilder rb{ctx, 2};
  98. rb.Push(DeviceNotFound);
  99. return;
  100. }
  101. ctx.WriteBuffer(nfp_devices);
  102. IPC::ResponseBuilder rb{ctx, 3};
  103. rb.Push(ResultSuccess);
  104. rb.Push(static_cast<s32>(nfp_devices.size()));
  105. }
  106. void IUser::StartDetection(Kernel::HLERequestContext& ctx) {
  107. IPC::RequestParser rp{ctx};
  108. const auto device_handle{rp.Pop<u64>()};
  109. const auto nfp_protocol{rp.PopEnum<TagProtocol>()};
  110. LOG_INFO(Service_NFP, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol);
  111. if (state == State::NonInitialized) {
  112. IPC::ResponseBuilder rb{ctx, 2};
  113. rb.Push(NfcDisabled);
  114. return;
  115. }
  116. auto device = GetNfpDevice(device_handle);
  117. if (!device.has_value()) {
  118. IPC::ResponseBuilder rb{ctx, 2};
  119. rb.Push(DeviceNotFound);
  120. return;
  121. }
  122. const auto result = device.value()->StartDetection(nfp_protocol);
  123. IPC::ResponseBuilder rb{ctx, 2};
  124. rb.Push(result);
  125. }
  126. void IUser::StopDetection(Kernel::HLERequestContext& ctx) {
  127. IPC::RequestParser rp{ctx};
  128. const auto device_handle{rp.Pop<u64>()};
  129. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  130. if (state == State::NonInitialized) {
  131. IPC::ResponseBuilder rb{ctx, 2};
  132. rb.Push(NfcDisabled);
  133. return;
  134. }
  135. auto device = GetNfpDevice(device_handle);
  136. if (!device.has_value()) {
  137. IPC::ResponseBuilder rb{ctx, 2};
  138. rb.Push(DeviceNotFound);
  139. return;
  140. }
  141. const auto result = device.value()->StopDetection();
  142. IPC::ResponseBuilder rb{ctx, 2};
  143. rb.Push(result);
  144. }
  145. void IUser::Mount(Kernel::HLERequestContext& ctx) {
  146. IPC::RequestParser rp{ctx};
  147. const auto device_handle{rp.Pop<u64>()};
  148. const auto model_type{rp.PopEnum<ModelType>()};
  149. const auto mount_target{rp.PopEnum<MountTarget>()};
  150. LOG_INFO(Service_NFP, "called, device_handle={}, model_type={}, mount_target={}", device_handle,
  151. model_type, mount_target);
  152. if (state == State::NonInitialized) {
  153. IPC::ResponseBuilder rb{ctx, 2};
  154. rb.Push(NfcDisabled);
  155. return;
  156. }
  157. auto device = GetNfpDevice(device_handle);
  158. if (!device.has_value()) {
  159. IPC::ResponseBuilder rb{ctx, 2};
  160. rb.Push(DeviceNotFound);
  161. return;
  162. }
  163. const auto result = device.value()->Mount(mount_target);
  164. IPC::ResponseBuilder rb{ctx, 2};
  165. rb.Push(result);
  166. }
  167. void IUser::Unmount(Kernel::HLERequestContext& ctx) {
  168. IPC::RequestParser rp{ctx};
  169. const auto device_handle{rp.Pop<u64>()};
  170. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  171. if (state == State::NonInitialized) {
  172. IPC::ResponseBuilder rb{ctx, 2};
  173. rb.Push(NfcDisabled);
  174. return;
  175. }
  176. auto device = GetNfpDevice(device_handle);
  177. if (!device.has_value()) {
  178. IPC::ResponseBuilder rb{ctx, 2};
  179. rb.Push(DeviceNotFound);
  180. return;
  181. }
  182. const auto result = device.value()->Unmount();
  183. IPC::ResponseBuilder rb{ctx, 2};
  184. rb.Push(result);
  185. }
  186. void IUser::OpenApplicationArea(Kernel::HLERequestContext& ctx) {
  187. IPC::RequestParser rp{ctx};
  188. const auto device_handle{rp.Pop<u64>()};
  189. const auto access_id{rp.Pop<u32>()};
  190. LOG_INFO(Service_NFP, "called, device_handle={}, access_id={}", device_handle, access_id);
  191. if (state == State::NonInitialized) {
  192. IPC::ResponseBuilder rb{ctx, 2};
  193. rb.Push(NfcDisabled);
  194. return;
  195. }
  196. auto device = GetNfpDevice(device_handle);
  197. if (!device.has_value()) {
  198. IPC::ResponseBuilder rb{ctx, 2};
  199. rb.Push(DeviceNotFound);
  200. return;
  201. }
  202. const auto result = device.value()->OpenApplicationArea(access_id);
  203. IPC::ResponseBuilder rb{ctx, 2};
  204. rb.Push(result);
  205. }
  206. void IUser::GetApplicationArea(Kernel::HLERequestContext& ctx) {
  207. IPC::RequestParser rp{ctx};
  208. const auto device_handle{rp.Pop<u64>()};
  209. const auto data_size = ctx.GetWriteBufferSize();
  210. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  211. if (state == State::NonInitialized) {
  212. IPC::ResponseBuilder rb{ctx, 2};
  213. rb.Push(NfcDisabled);
  214. return;
  215. }
  216. if (!ctx.CanWriteBuffer()) {
  217. IPC::ResponseBuilder rb{ctx, 2};
  218. rb.Push(InvalidArgument);
  219. return;
  220. }
  221. auto device = GetNfpDevice(device_handle);
  222. if (!device.has_value()) {
  223. IPC::ResponseBuilder rb{ctx, 2};
  224. rb.Push(DeviceNotFound);
  225. return;
  226. }
  227. std::vector<u8> data(data_size);
  228. const auto result = device.value()->GetApplicationArea(data);
  229. ctx.WriteBuffer(data);
  230. IPC::ResponseBuilder rb{ctx, 3};
  231. rb.Push(result);
  232. rb.Push(static_cast<u32>(data_size));
  233. }
  234. void IUser::SetApplicationArea(Kernel::HLERequestContext& ctx) {
  235. IPC::RequestParser rp{ctx};
  236. const auto device_handle{rp.Pop<u64>()};
  237. const auto data{ctx.ReadBuffer()};
  238. LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}", device_handle, data.size());
  239. if (state == State::NonInitialized) {
  240. IPC::ResponseBuilder rb{ctx, 2};
  241. rb.Push(NfcDisabled);
  242. return;
  243. }
  244. if (!ctx.CanReadBuffer()) {
  245. IPC::ResponseBuilder rb{ctx, 2};
  246. rb.Push(InvalidArgument);
  247. return;
  248. }
  249. auto device = GetNfpDevice(device_handle);
  250. if (!device.has_value()) {
  251. IPC::ResponseBuilder rb{ctx, 2};
  252. rb.Push(DeviceNotFound);
  253. return;
  254. }
  255. const auto result = device.value()->SetApplicationArea(data);
  256. IPC::ResponseBuilder rb{ctx, 2};
  257. rb.Push(result);
  258. }
  259. void IUser::Flush(Kernel::HLERequestContext& ctx) {
  260. IPC::RequestParser rp{ctx};
  261. const auto device_handle{rp.Pop<u64>()};
  262. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  263. if (state == State::NonInitialized) {
  264. IPC::ResponseBuilder rb{ctx, 2};
  265. rb.Push(NfcDisabled);
  266. return;
  267. }
  268. auto device = GetNfpDevice(device_handle);
  269. if (!device.has_value()) {
  270. IPC::ResponseBuilder rb{ctx, 2};
  271. rb.Push(DeviceNotFound);
  272. return;
  273. }
  274. const auto result = device.value()->Flush();
  275. IPC::ResponseBuilder rb{ctx, 2};
  276. rb.Push(result);
  277. }
  278. void IUser::Restore(Kernel::HLERequestContext& ctx) {
  279. IPC::RequestParser rp{ctx};
  280. const auto device_handle{rp.Pop<u64>()};
  281. LOG_WARNING(Service_NFP, "(STUBBED) called, device_handle={}", device_handle);
  282. if (state == State::NonInitialized) {
  283. IPC::ResponseBuilder rb{ctx, 2};
  284. rb.Push(NfcDisabled);
  285. return;
  286. }
  287. auto device = GetNfpDevice(device_handle);
  288. if (!device.has_value()) {
  289. IPC::ResponseBuilder rb{ctx, 2};
  290. rb.Push(DeviceNotFound);
  291. return;
  292. }
  293. const auto result = device.value()->RestoreAmiibo();
  294. IPC::ResponseBuilder rb{ctx, 2};
  295. rb.Push(result);
  296. }
  297. void IUser::CreateApplicationArea(Kernel::HLERequestContext& ctx) {
  298. IPC::RequestParser rp{ctx};
  299. const auto device_handle{rp.Pop<u64>()};
  300. const auto access_id{rp.Pop<u32>()};
  301. const auto data{ctx.ReadBuffer()};
  302. LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle,
  303. access_id, data.size());
  304. if (state == State::NonInitialized) {
  305. IPC::ResponseBuilder rb{ctx, 2};
  306. rb.Push(NfcDisabled);
  307. return;
  308. }
  309. if (!ctx.CanReadBuffer()) {
  310. IPC::ResponseBuilder rb{ctx, 2};
  311. rb.Push(InvalidArgument);
  312. return;
  313. }
  314. auto device = GetNfpDevice(device_handle);
  315. if (!device.has_value()) {
  316. IPC::ResponseBuilder rb{ctx, 2};
  317. rb.Push(DeviceNotFound);
  318. return;
  319. }
  320. const auto result = device.value()->CreateApplicationArea(access_id, data);
  321. IPC::ResponseBuilder rb{ctx, 2};
  322. rb.Push(result);
  323. }
  324. void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) {
  325. IPC::RequestParser rp{ctx};
  326. const auto device_handle{rp.Pop<u64>()};
  327. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  328. if (state == State::NonInitialized) {
  329. IPC::ResponseBuilder rb{ctx, 2};
  330. rb.Push(NfcDisabled);
  331. return;
  332. }
  333. auto device = GetNfpDevice(device_handle);
  334. if (!device.has_value()) {
  335. IPC::ResponseBuilder rb{ctx, 2};
  336. rb.Push(DeviceNotFound);
  337. return;
  338. }
  339. TagInfo tag_info{};
  340. const auto result = device.value()->GetTagInfo(tag_info);
  341. ctx.WriteBuffer(tag_info);
  342. IPC::ResponseBuilder rb{ctx, 2};
  343. rb.Push(result);
  344. }
  345. void IUser::GetRegisterInfo(Kernel::HLERequestContext& ctx) {
  346. IPC::RequestParser rp{ctx};
  347. const auto device_handle{rp.Pop<u64>()};
  348. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  349. if (state == State::NonInitialized) {
  350. IPC::ResponseBuilder rb{ctx, 2};
  351. rb.Push(NfcDisabled);
  352. return;
  353. }
  354. auto device = GetNfpDevice(device_handle);
  355. if (!device.has_value()) {
  356. IPC::ResponseBuilder rb{ctx, 2};
  357. rb.Push(DeviceNotFound);
  358. return;
  359. }
  360. RegisterInfo register_info{};
  361. const auto result = device.value()->GetRegisterInfo(register_info);
  362. ctx.WriteBuffer(register_info);
  363. IPC::ResponseBuilder rb{ctx, 2};
  364. rb.Push(result);
  365. }
  366. void IUser::GetCommonInfo(Kernel::HLERequestContext& ctx) {
  367. IPC::RequestParser rp{ctx};
  368. const auto device_handle{rp.Pop<u64>()};
  369. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  370. if (state == State::NonInitialized) {
  371. IPC::ResponseBuilder rb{ctx, 2};
  372. rb.Push(NfcDisabled);
  373. return;
  374. }
  375. auto device = GetNfpDevice(device_handle);
  376. if (!device.has_value()) {
  377. IPC::ResponseBuilder rb{ctx, 2};
  378. rb.Push(DeviceNotFound);
  379. return;
  380. }
  381. CommonInfo common_info{};
  382. const auto result = device.value()->GetCommonInfo(common_info);
  383. ctx.WriteBuffer(common_info);
  384. IPC::ResponseBuilder rb{ctx, 2};
  385. rb.Push(result);
  386. }
  387. void IUser::GetModelInfo(Kernel::HLERequestContext& ctx) {
  388. IPC::RequestParser rp{ctx};
  389. const auto device_handle{rp.Pop<u64>()};
  390. LOG_INFO(Service_NFP, "called, device_handle={}", device_handle);
  391. if (state == State::NonInitialized) {
  392. IPC::ResponseBuilder rb{ctx, 2};
  393. rb.Push(NfcDisabled);
  394. return;
  395. }
  396. auto device = GetNfpDevice(device_handle);
  397. if (!device.has_value()) {
  398. IPC::ResponseBuilder rb{ctx, 2};
  399. rb.Push(DeviceNotFound);
  400. return;
  401. }
  402. ModelInfo model_info{};
  403. const auto result = device.value()->GetModelInfo(model_info);
  404. ctx.WriteBuffer(model_info);
  405. IPC::ResponseBuilder rb{ctx, 2};
  406. rb.Push(result);
  407. }
  408. void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) {
  409. IPC::RequestParser rp{ctx};
  410. const auto device_handle{rp.Pop<u64>()};
  411. LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
  412. if (state == State::NonInitialized) {
  413. IPC::ResponseBuilder rb{ctx, 2};
  414. rb.Push(NfcDisabled);
  415. return;
  416. }
  417. auto device = GetNfpDevice(device_handle);
  418. if (!device.has_value()) {
  419. IPC::ResponseBuilder rb{ctx, 2};
  420. rb.Push(DeviceNotFound);
  421. return;
  422. }
  423. IPC::ResponseBuilder rb{ctx, 2, 1};
  424. rb.Push(ResultSuccess);
  425. rb.PushCopyObjects(device.value()->GetActivateEvent());
  426. }
  427. void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) {
  428. IPC::RequestParser rp{ctx};
  429. const auto device_handle{rp.Pop<u64>()};
  430. LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
  431. if (state == State::NonInitialized) {
  432. IPC::ResponseBuilder rb{ctx, 2};
  433. rb.Push(NfcDisabled);
  434. return;
  435. }
  436. auto device = GetNfpDevice(device_handle);
  437. if (!device.has_value()) {
  438. IPC::ResponseBuilder rb{ctx, 2};
  439. rb.Push(DeviceNotFound);
  440. return;
  441. }
  442. IPC::ResponseBuilder rb{ctx, 2, 1};
  443. rb.Push(ResultSuccess);
  444. rb.PushCopyObjects(device.value()->GetDeactivateEvent());
  445. }
  446. void IUser::GetState(Kernel::HLERequestContext& ctx) {
  447. LOG_DEBUG(Service_NFC, "called");
  448. IPC::ResponseBuilder rb{ctx, 3, 0};
  449. rb.Push(ResultSuccess);
  450. rb.PushEnum(state);
  451. }
  452. void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) {
  453. IPC::RequestParser rp{ctx};
  454. const auto device_handle{rp.Pop<u64>()};
  455. LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
  456. auto device = GetNfpDevice(device_handle);
  457. if (!device.has_value()) {
  458. IPC::ResponseBuilder rb{ctx, 2};
  459. rb.Push(DeviceNotFound);
  460. return;
  461. }
  462. IPC::ResponseBuilder rb{ctx, 3};
  463. rb.Push(ResultSuccess);
  464. rb.PushEnum(device.value()->GetCurrentState());
  465. }
  466. void IUser::GetNpadId(Kernel::HLERequestContext& ctx) {
  467. IPC::RequestParser rp{ctx};
  468. const auto device_handle{rp.Pop<u64>()};
  469. LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
  470. if (state == State::NonInitialized) {
  471. IPC::ResponseBuilder rb{ctx, 2};
  472. rb.Push(NfcDisabled);
  473. return;
  474. }
  475. auto device = GetNfpDevice(device_handle);
  476. if (!device.has_value()) {
  477. IPC::ResponseBuilder rb{ctx, 2};
  478. rb.Push(DeviceNotFound);
  479. return;
  480. }
  481. IPC::ResponseBuilder rb{ctx, 3};
  482. rb.Push(ResultSuccess);
  483. rb.PushEnum(device.value()->GetNpadId());
  484. }
  485. void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) {
  486. IPC::RequestParser rp{ctx};
  487. const auto device_handle{rp.Pop<u64>()};
  488. LOG_DEBUG(Service_NFP, "called, device_handle={}", device_handle);
  489. auto device = GetNfpDevice(device_handle);
  490. if (!device.has_value()) {
  491. IPC::ResponseBuilder rb{ctx, 2};
  492. rb.Push(DeviceNotFound);
  493. return;
  494. }
  495. IPC::ResponseBuilder rb{ctx, 3};
  496. rb.Push(ResultSuccess);
  497. rb.Push(device.value()->GetApplicationAreaSize());
  498. }
  499. void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) {
  500. LOG_INFO(Service_NFP, "called");
  501. if (state == State::NonInitialized) {
  502. IPC::ResponseBuilder rb{ctx, 2};
  503. rb.Push(NfcDisabled);
  504. return;
  505. }
  506. IPC::ResponseBuilder rb{ctx, 2, 1};
  507. rb.Push(ResultSuccess);
  508. rb.PushCopyObjects(availability_change_event->GetReadableEvent());
  509. }
  510. void IUser::RecreateApplicationArea(Kernel::HLERequestContext& ctx) {
  511. IPC::RequestParser rp{ctx};
  512. const auto device_handle{rp.Pop<u64>()};
  513. const auto access_id{rp.Pop<u32>()};
  514. const auto data{ctx.ReadBuffer()};
  515. LOG_INFO(Service_NFP, "called, device_handle={}, data_size={}, access_id={}", device_handle,
  516. access_id, data.size());
  517. if (state == State::NonInitialized) {
  518. IPC::ResponseBuilder rb{ctx, 2};
  519. rb.Push(NfcDisabled);
  520. return;
  521. }
  522. auto device = GetNfpDevice(device_handle);
  523. if (!device.has_value()) {
  524. IPC::ResponseBuilder rb{ctx, 2};
  525. rb.Push(DeviceNotFound);
  526. return;
  527. }
  528. const auto result = device.value()->RecreateApplicationArea(access_id, data);
  529. IPC::ResponseBuilder rb{ctx, 2};
  530. rb.Push(result);
  531. }
  532. std::optional<std::shared_ptr<NfpDevice>> IUser::GetNfpDevice(u64 handle) {
  533. for (auto& device : devices) {
  534. if (device->GetHandle() == handle) {
  535. return device;
  536. }
  537. }
  538. return std::nullopt;
  539. }
  540. } // namespace Service::NFP