mifare_interface.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/logging/log.h"
  4. #include "core/core.h"
  5. #include "core/hid/hid_types.h"
  6. #include "core/hle/kernel/k_event.h"
  7. #include "core/hle/service/ipc_helpers.h"
  8. #include "core/hle/service/nfc/mifare_interface.h"
  9. #include "core/hle/service/nfc/nfc_device.h"
  10. #include "core/hle/service/nfc/nfc_result.h"
  11. namespace Service::NFC {
  12. MFInterface::MFInterface(Core::System& system_, const char* name)
  13. : ServiceFramework{system_, name}, service_context{system_, service_name} {
  14. availability_change_event = service_context.CreateEvent("MFInterface:AvailabilityChangeEvent");
  15. for (u32 device_index = 0; device_index < 10; device_index++) {
  16. devices[device_index] =
  17. std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
  18. service_context, availability_change_event);
  19. }
  20. }
  21. MFInterface ::~MFInterface() {
  22. availability_change_event->Close();
  23. }
  24. void MFInterface::Initialize(HLERequestContext& ctx) {
  25. LOG_INFO(Service_NFC, "called");
  26. state = State::Initialized;
  27. for (auto& device : devices) {
  28. device->Initialize();
  29. }
  30. IPC::ResponseBuilder rb{ctx, 2, 0};
  31. rb.Push(ResultSuccess);
  32. }
  33. void MFInterface::Finalize(HLERequestContext& ctx) {
  34. LOG_INFO(Service_NFC, "called");
  35. state = State::NonInitialized;
  36. for (auto& device : devices) {
  37. device->Finalize();
  38. }
  39. IPC::ResponseBuilder rb{ctx, 2};
  40. rb.Push(ResultSuccess);
  41. }
  42. void MFInterface::ListDevices(HLERequestContext& ctx) {
  43. LOG_DEBUG(Service_NFC, "called");
  44. if (state == State::NonInitialized) {
  45. IPC::ResponseBuilder rb{ctx, 2};
  46. rb.Push(MifareNfcDisabled);
  47. return;
  48. }
  49. if (!ctx.CanWriteBuffer()) {
  50. IPC::ResponseBuilder rb{ctx, 2};
  51. rb.Push(MifareInvalidArgument);
  52. return;
  53. }
  54. if (ctx.GetWriteBufferSize() == 0) {
  55. IPC::ResponseBuilder rb{ctx, 2};
  56. rb.Push(MifareInvalidArgument);
  57. return;
  58. }
  59. std::vector<u64> nfp_devices;
  60. const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
  61. for (const auto& device : devices) {
  62. if (nfp_devices.size() >= max_allowed_devices) {
  63. continue;
  64. }
  65. if (device->GetCurrentState() != NFP::DeviceState::Unavailable) {
  66. nfp_devices.push_back(device->GetHandle());
  67. }
  68. }
  69. if (nfp_devices.empty()) {
  70. IPC::ResponseBuilder rb{ctx, 2};
  71. rb.Push(MifareDeviceNotFound);
  72. return;
  73. }
  74. ctx.WriteBuffer(nfp_devices);
  75. IPC::ResponseBuilder rb{ctx, 3};
  76. rb.Push(ResultSuccess);
  77. rb.Push(static_cast<s32>(nfp_devices.size()));
  78. }
  79. void MFInterface::StartDetection(HLERequestContext& ctx) {
  80. IPC::RequestParser rp{ctx};
  81. const auto device_handle{rp.Pop<u64>()};
  82. LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
  83. if (state == State::NonInitialized) {
  84. IPC::ResponseBuilder rb{ctx, 2};
  85. rb.Push(MifareNfcDisabled);
  86. return;
  87. }
  88. auto device = GetNfcDevice(device_handle);
  89. if (!device.has_value()) {
  90. IPC::ResponseBuilder rb{ctx, 2};
  91. rb.Push(MifareDeviceNotFound);
  92. return;
  93. }
  94. const auto result = device.value()->StartDetection(NFP::TagProtocol::All);
  95. IPC::ResponseBuilder rb{ctx, 2};
  96. rb.Push(result);
  97. }
  98. void MFInterface::StopDetection(HLERequestContext& ctx) {
  99. IPC::RequestParser rp{ctx};
  100. const auto device_handle{rp.Pop<u64>()};
  101. LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
  102. if (state == State::NonInitialized) {
  103. IPC::ResponseBuilder rb{ctx, 2};
  104. rb.Push(MifareNfcDisabled);
  105. return;
  106. }
  107. auto device = GetNfcDevice(device_handle);
  108. if (!device.has_value()) {
  109. IPC::ResponseBuilder rb{ctx, 2};
  110. rb.Push(MifareDeviceNotFound);
  111. return;
  112. }
  113. const auto result = device.value()->StopDetection();
  114. IPC::ResponseBuilder rb{ctx, 2};
  115. rb.Push(result);
  116. }
  117. void MFInterface::Read(HLERequestContext& ctx) {
  118. IPC::RequestParser rp{ctx};
  119. const auto device_handle{rp.Pop<u64>()};
  120. const auto buffer{ctx.ReadBuffer()};
  121. const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareReadBlockParameter>()};
  122. std::vector<NFP::MifareReadBlockParameter> read_commands(number_of_commands);
  123. memcpy(read_commands.data(), buffer.data(),
  124. number_of_commands * sizeof(NFP::MifareReadBlockParameter));
  125. LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
  126. device_handle, number_of_commands);
  127. if (state == State::NonInitialized) {
  128. IPC::ResponseBuilder rb{ctx, 2};
  129. rb.Push(MifareNfcDisabled);
  130. return;
  131. }
  132. auto device = GetNfcDevice(device_handle);
  133. if (!device.has_value()) {
  134. IPC::ResponseBuilder rb{ctx, 2};
  135. rb.Push(MifareDeviceNotFound);
  136. return;
  137. }
  138. Result result = ResultSuccess;
  139. std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
  140. for (std::size_t i = 0; i < number_of_commands; i++) {
  141. result = device.value()->MifareRead(read_commands[i], out_data[i]);
  142. if (result.IsError()) {
  143. break;
  144. }
  145. }
  146. ctx.WriteBuffer(out_data);
  147. IPC::ResponseBuilder rb{ctx, 2};
  148. rb.Push(result);
  149. }
  150. void MFInterface::Write(HLERequestContext& ctx) {
  151. IPC::RequestParser rp{ctx};
  152. const auto device_handle{rp.Pop<u64>()};
  153. const auto buffer{ctx.ReadBuffer()};
  154. const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareWriteBlockParameter>()};
  155. std::vector<NFP::MifareWriteBlockParameter> write_commands(number_of_commands);
  156. memcpy(write_commands.data(), buffer.data(),
  157. number_of_commands * sizeof(NFP::MifareWriteBlockParameter));
  158. LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
  159. device_handle, number_of_commands);
  160. if (state == State::NonInitialized) {
  161. IPC::ResponseBuilder rb{ctx, 2};
  162. rb.Push(MifareNfcDisabled);
  163. return;
  164. }
  165. auto device = GetNfcDevice(device_handle);
  166. if (!device.has_value()) {
  167. IPC::ResponseBuilder rb{ctx, 2};
  168. rb.Push(MifareDeviceNotFound);
  169. return;
  170. }
  171. Result result = ResultSuccess;
  172. std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
  173. for (std::size_t i = 0; i < number_of_commands; i++) {
  174. result = device.value()->MifareWrite(write_commands[i]);
  175. if (result.IsError()) {
  176. break;
  177. }
  178. }
  179. if (result.IsSuccess()) {
  180. result = device.value()->Flush();
  181. }
  182. IPC::ResponseBuilder rb{ctx, 2};
  183. rb.Push(result);
  184. }
  185. void MFInterface::GetTagInfo(HLERequestContext& ctx) {
  186. IPC::RequestParser rp{ctx};
  187. const auto device_handle{rp.Pop<u64>()};
  188. LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
  189. if (state == State::NonInitialized) {
  190. IPC::ResponseBuilder rb{ctx, 2};
  191. rb.Push(MifareNfcDisabled);
  192. return;
  193. }
  194. auto device = GetNfcDevice(device_handle);
  195. if (!device.has_value()) {
  196. IPC::ResponseBuilder rb{ctx, 2};
  197. rb.Push(MifareDeviceNotFound);
  198. return;
  199. }
  200. NFP::TagInfo tag_info{};
  201. const auto result = device.value()->GetTagInfo(tag_info, true);
  202. ctx.WriteBuffer(tag_info);
  203. IPC::ResponseBuilder rb{ctx, 2};
  204. rb.Push(result);
  205. }
  206. void MFInterface::GetActivateEventHandle(HLERequestContext& ctx) {
  207. IPC::RequestParser rp{ctx};
  208. const auto device_handle{rp.Pop<u64>()};
  209. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  210. if (state == State::NonInitialized) {
  211. IPC::ResponseBuilder rb{ctx, 2};
  212. rb.Push(MifareNfcDisabled);
  213. return;
  214. }
  215. auto device = GetNfcDevice(device_handle);
  216. if (!device.has_value()) {
  217. IPC::ResponseBuilder rb{ctx, 2};
  218. rb.Push(MifareDeviceNotFound);
  219. return;
  220. }
  221. IPC::ResponseBuilder rb{ctx, 2, 1};
  222. rb.Push(ResultSuccess);
  223. rb.PushCopyObjects(device.value()->GetActivateEvent());
  224. }
  225. void MFInterface::GetDeactivateEventHandle(HLERequestContext& ctx) {
  226. IPC::RequestParser rp{ctx};
  227. const auto device_handle{rp.Pop<u64>()};
  228. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  229. if (state == State::NonInitialized) {
  230. IPC::ResponseBuilder rb{ctx, 2};
  231. rb.Push(MifareNfcDisabled);
  232. return;
  233. }
  234. auto device = GetNfcDevice(device_handle);
  235. if (!device.has_value()) {
  236. IPC::ResponseBuilder rb{ctx, 2};
  237. rb.Push(MifareDeviceNotFound);
  238. return;
  239. }
  240. IPC::ResponseBuilder rb{ctx, 2, 1};
  241. rb.Push(ResultSuccess);
  242. rb.PushCopyObjects(device.value()->GetDeactivateEvent());
  243. }
  244. void MFInterface::GetState(HLERequestContext& ctx) {
  245. LOG_DEBUG(Service_NFC, "called");
  246. IPC::ResponseBuilder rb{ctx, 3};
  247. rb.Push(ResultSuccess);
  248. rb.PushEnum(state);
  249. }
  250. void MFInterface::GetDeviceState(HLERequestContext& ctx) {
  251. IPC::RequestParser rp{ctx};
  252. const auto device_handle{rp.Pop<u64>()};
  253. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  254. auto device = GetNfcDevice(device_handle);
  255. if (!device.has_value()) {
  256. IPC::ResponseBuilder rb{ctx, 2};
  257. rb.Push(MifareDeviceNotFound);
  258. return;
  259. }
  260. IPC::ResponseBuilder rb{ctx, 3};
  261. rb.Push(ResultSuccess);
  262. rb.PushEnum(device.value()->GetCurrentState());
  263. }
  264. void MFInterface::GetNpadId(HLERequestContext& ctx) {
  265. IPC::RequestParser rp{ctx};
  266. const auto device_handle{rp.Pop<u64>()};
  267. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  268. if (state == State::NonInitialized) {
  269. IPC::ResponseBuilder rb{ctx, 2};
  270. rb.Push(MifareNfcDisabled);
  271. return;
  272. }
  273. auto device = GetNfcDevice(device_handle);
  274. if (!device.has_value()) {
  275. IPC::ResponseBuilder rb{ctx, 2};
  276. rb.Push(MifareDeviceNotFound);
  277. return;
  278. }
  279. IPC::ResponseBuilder rb{ctx, 3};
  280. rb.Push(ResultSuccess);
  281. rb.PushEnum(device.value()->GetNpadId());
  282. }
  283. void MFInterface::GetAvailabilityChangeEventHandle(HLERequestContext& ctx) {
  284. LOG_INFO(Service_NFC, "called");
  285. if (state == State::NonInitialized) {
  286. IPC::ResponseBuilder rb{ctx, 2};
  287. rb.Push(MifareNfcDisabled);
  288. return;
  289. }
  290. IPC::ResponseBuilder rb{ctx, 2, 1};
  291. rb.Push(ResultSuccess);
  292. rb.PushCopyObjects(availability_change_event->GetReadableEvent());
  293. }
  294. std::optional<std::shared_ptr<NfcDevice>> MFInterface::GetNfcDevice(u64 handle) {
  295. for (auto& device : devices) {
  296. if (device->GetHandle() == handle) {
  297. return device;
  298. }
  299. }
  300. return std::nullopt;
  301. }
  302. } // namespace Service::NFC