nfp_user.cpp 18 KB

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