nfc_interface.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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/common/device.h"
  9. #include "core/hle/service/nfc/common/device_manager.h"
  10. #include "core/hle/service/nfc/mifare_result.h"
  11. #include "core/hle/service/nfc/mifare_types.h"
  12. #include "core/hle/service/nfc/nfc_interface.h"
  13. #include "core/hle/service/nfc/nfc_result.h"
  14. #include "core/hle/service/nfc/nfc_types.h"
  15. #include "core/hle/service/nfp/nfp_result.h"
  16. #include "core/hle/service/time/clock_types.h"
  17. namespace Service::NFC {
  18. NfcInterface::NfcInterface(Core::System& system_, const char* name, BackendType service_backend)
  19. : ServiceFramework{system_, name}, service_context{system_, service_name},
  20. backend_type{service_backend} {}
  21. NfcInterface ::~NfcInterface() = default;
  22. void NfcInterface::Initialize(HLERequestContext& ctx) {
  23. LOG_INFO(Service_NFC, "called");
  24. auto manager = GetManager();
  25. auto result = manager->Initialize();
  26. if (result.IsSuccess()) {
  27. state = State::Initialized;
  28. } else {
  29. manager->Finalize();
  30. }
  31. IPC::ResponseBuilder rb{ctx, 2, 0};
  32. rb.Push(result);
  33. }
  34. void NfcInterface::Finalize(HLERequestContext& ctx) {
  35. LOG_INFO(Service_NFC, "called");
  36. if (state != State::NonInitialized) {
  37. if (GetBackendType() != BackendType::None) {
  38. GetManager()->Finalize();
  39. }
  40. device_manager = nullptr;
  41. state = State::NonInitialized;
  42. }
  43. IPC::ResponseBuilder rb{ctx, 2};
  44. rb.Push(ResultSuccess);
  45. }
  46. void NfcInterface::GetState(HLERequestContext& ctx) {
  47. LOG_DEBUG(Service_NFC, "called");
  48. IPC::ResponseBuilder rb{ctx, 3};
  49. rb.Push(ResultSuccess);
  50. rb.PushEnum(state);
  51. }
  52. void NfcInterface::IsNfcEnabled(HLERequestContext& ctx) {
  53. LOG_DEBUG(Service_NFC, "called");
  54. // TODO: This calls nn::settings::detail::GetNfcEnableFlag
  55. const bool is_enabled = true;
  56. IPC::ResponseBuilder rb{ctx, 3};
  57. rb.Push(ResultSuccess);
  58. rb.Push(is_enabled);
  59. }
  60. void NfcInterface::ListDevices(HLERequestContext& ctx) {
  61. std::vector<u64> nfp_devices;
  62. const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
  63. LOG_DEBUG(Service_NFC, "called");
  64. auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices, true);
  65. result = TranslateResultToServiceError(result);
  66. if (result.IsError()) {
  67. IPC::ResponseBuilder rb{ctx, 2};
  68. rb.Push(result);
  69. return;
  70. }
  71. ctx.WriteBuffer(nfp_devices);
  72. IPC::ResponseBuilder rb{ctx, 3};
  73. rb.Push(ResultSuccess);
  74. rb.Push(static_cast<s32>(nfp_devices.size()));
  75. }
  76. void NfcInterface::GetDeviceState(HLERequestContext& ctx) {
  77. IPC::RequestParser rp{ctx};
  78. const auto device_handle{rp.Pop<u64>()};
  79. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  80. const auto device_state = GetManager()->GetDeviceState(device_handle);
  81. if (device_state > DeviceState::Finalized) {
  82. ASSERT_MSG(false, "Invalid device state");
  83. }
  84. IPC::ResponseBuilder rb{ctx, 3};
  85. rb.Push(ResultSuccess);
  86. rb.PushEnum(device_state);
  87. }
  88. void NfcInterface::GetNpadId(HLERequestContext& ctx) {
  89. IPC::RequestParser rp{ctx};
  90. const auto device_handle{rp.Pop<u64>()};
  91. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  92. Core::HID::NpadIdType npad_id{};
  93. auto result = GetManager()->GetNpadId(device_handle, npad_id);
  94. result = TranslateResultToServiceError(result);
  95. if (result.IsError()) {
  96. IPC::ResponseBuilder rb{ctx, 2};
  97. rb.Push(result);
  98. return;
  99. }
  100. IPC::ResponseBuilder rb{ctx, 3};
  101. rb.Push(ResultSuccess);
  102. rb.PushEnum(npad_id);
  103. }
  104. void NfcInterface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {
  105. LOG_INFO(Service_NFC, "called");
  106. IPC::ResponseBuilder rb{ctx, 2, 1};
  107. rb.Push(ResultSuccess);
  108. rb.PushCopyObjects(GetManager()->AttachAvailabilityChangeEvent());
  109. }
  110. void NfcInterface::StartDetection(HLERequestContext& ctx) {
  111. IPC::RequestParser rp{ctx};
  112. const auto device_handle{rp.Pop<u64>()};
  113. auto tag_protocol{NfcProtocol::All};
  114. if (backend_type == BackendType::Nfc) {
  115. tag_protocol = rp.PopEnum<NfcProtocol>();
  116. }
  117. LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol);
  118. auto result = GetManager()->StartDetection(device_handle, tag_protocol);
  119. result = TranslateResultToServiceError(result);
  120. IPC::ResponseBuilder rb{ctx, 2};
  121. rb.Push(result);
  122. }
  123. void NfcInterface::StopDetection(HLERequestContext& ctx) {
  124. IPC::RequestParser rp{ctx};
  125. const auto device_handle{rp.Pop<u64>()};
  126. LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
  127. auto result = GetManager()->StopDetection(device_handle);
  128. result = TranslateResultToServiceError(result);
  129. IPC::ResponseBuilder rb{ctx, 2};
  130. rb.Push(result);
  131. }
  132. void NfcInterface::GetTagInfo(HLERequestContext& ctx) {
  133. IPC::RequestParser rp{ctx};
  134. const auto device_handle{rp.Pop<u64>()};
  135. LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
  136. TagInfo tag_info{};
  137. auto result = GetManager()->GetTagInfo(device_handle, tag_info);
  138. result = TranslateResultToServiceError(result);
  139. if (result.IsSuccess()) {
  140. ctx.WriteBuffer(tag_info);
  141. }
  142. IPC::ResponseBuilder rb{ctx, 2};
  143. rb.Push(result);
  144. }
  145. void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) {
  146. IPC::RequestParser rp{ctx};
  147. const auto device_handle{rp.Pop<u64>()};
  148. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  149. Kernel::KReadableEvent* out_event = nullptr;
  150. auto result = GetManager()->AttachActivateEvent(&out_event, device_handle);
  151. result = TranslateResultToServiceError(result);
  152. IPC::ResponseBuilder rb{ctx, 2, 1};
  153. rb.Push(result);
  154. rb.PushCopyObjects(out_event);
  155. }
  156. void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
  157. IPC::RequestParser rp{ctx};
  158. const auto device_handle{rp.Pop<u64>()};
  159. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  160. Kernel::KReadableEvent* out_event = nullptr;
  161. auto result = GetManager()->AttachDeactivateEvent(&out_event, device_handle);
  162. result = TranslateResultToServiceError(result);
  163. IPC::ResponseBuilder rb{ctx, 2, 1};
  164. rb.Push(result);
  165. rb.PushCopyObjects(out_event);
  166. }
  167. void NfcInterface::ReadMifare(HLERequestContext& ctx) {
  168. IPC::RequestParser rp{ctx};
  169. const auto device_handle{rp.Pop<u64>()};
  170. const auto buffer{ctx.ReadBuffer()};
  171. const auto number_of_commands{ctx.GetReadBufferNumElements<MifareReadBlockParameter>()};
  172. std::vector<MifareReadBlockParameter> read_commands(number_of_commands);
  173. memcpy(read_commands.data(), buffer.data(),
  174. number_of_commands * sizeof(MifareReadBlockParameter));
  175. LOG_INFO(Service_NFC, "called, device_handle={}, read_commands_size={}", device_handle,
  176. number_of_commands);
  177. std::vector<MifareReadBlockData> out_data(number_of_commands);
  178. auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data);
  179. result = TranslateResultToServiceError(result);
  180. if (result.IsSuccess()) {
  181. ctx.WriteBuffer(out_data);
  182. }
  183. IPC::ResponseBuilder rb{ctx, 2};
  184. rb.Push(result);
  185. }
  186. void NfcInterface::WriteMifare(HLERequestContext& ctx) {
  187. IPC::RequestParser rp{ctx};
  188. const auto device_handle{rp.Pop<u64>()};
  189. const auto buffer{ctx.ReadBuffer()};
  190. const auto number_of_commands{ctx.GetReadBufferNumElements<MifareWriteBlockParameter>()};
  191. std::vector<MifareWriteBlockParameter> write_commands(number_of_commands);
  192. memcpy(write_commands.data(), buffer.data(),
  193. number_of_commands * sizeof(MifareWriteBlockParameter));
  194. LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
  195. device_handle, number_of_commands);
  196. auto result = GetManager()->WriteMifare(device_handle, write_commands);
  197. result = TranslateResultToServiceError(result);
  198. IPC::ResponseBuilder rb{ctx, 2};
  199. rb.Push(result);
  200. }
  201. void NfcInterface::SendCommandByPassThrough(HLERequestContext& ctx) {
  202. IPC::RequestParser rp{ctx};
  203. const auto device_handle{rp.Pop<u64>()};
  204. const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()};
  205. const auto command_data{ctx.ReadBuffer()};
  206. LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}",
  207. device_handle, timeout.ToSeconds(), command_data.size());
  208. std::vector<u8> out_data(1);
  209. auto result =
  210. GetManager()->SendCommandByPassThrough(device_handle, timeout, command_data, out_data);
  211. result = TranslateResultToServiceError(result);
  212. if (result.IsError()) {
  213. IPC::ResponseBuilder rb{ctx, 2};
  214. rb.Push(result);
  215. return;
  216. }
  217. ctx.WriteBuffer(out_data);
  218. IPC::ResponseBuilder rb{ctx, 3};
  219. rb.Push(ResultSuccess);
  220. rb.Push(static_cast<u32>(out_data.size()));
  221. }
  222. std::shared_ptr<DeviceManager> NfcInterface::GetManager() {
  223. if (device_manager == nullptr) {
  224. device_manager = std::make_shared<DeviceManager>(system, service_context);
  225. }
  226. return device_manager;
  227. }
  228. BackendType NfcInterface::GetBackendType() const {
  229. return backend_type;
  230. }
  231. Result NfcInterface::TranslateResultToServiceError(Result result) const {
  232. const auto backend = GetBackendType();
  233. if (result.IsSuccess()) {
  234. return result;
  235. }
  236. if (result.module != ErrorModule::NFC) {
  237. return result;
  238. }
  239. switch (backend) {
  240. case BackendType::Mifare:
  241. return TranslateResultToNfp(result);
  242. case BackendType::Nfp: {
  243. return TranslateResultToNfp(result);
  244. }
  245. default:
  246. if (result != ResultBackupPathAlreadyExist) {
  247. return result;
  248. }
  249. return ResultUnknown74;
  250. }
  251. }
  252. Result NfcInterface::TranslateResultToNfp(Result result) const {
  253. if (result == ResultDeviceNotFound) {
  254. return NFP::ResultDeviceNotFound;
  255. }
  256. if (result == ResultInvalidArgument) {
  257. return NFP::ResultInvalidArgument;
  258. }
  259. if (result == ResultWrongApplicationAreaSize) {
  260. return NFP::ResultWrongApplicationAreaSize;
  261. }
  262. if (result == ResultWrongDeviceState) {
  263. return NFP::ResultWrongDeviceState;
  264. }
  265. if (result == ResultUnknown74) {
  266. return NFP::ResultUnknown74;
  267. }
  268. if (result == ResultNfcDisabled) {
  269. return NFP::ResultNfcDisabled;
  270. }
  271. if (result == ResultNfcNotInitialized) {
  272. return NFP::ResultNfcDisabled;
  273. }
  274. if (result == ResultWriteAmiiboFailed) {
  275. return NFP::ResultWriteAmiiboFailed;
  276. }
  277. if (result == ResultTagRemoved) {
  278. return NFP::ResultTagRemoved;
  279. }
  280. if (result == ResultRegistrationIsNotInitialized) {
  281. return NFP::ResultRegistrationIsNotInitialized;
  282. }
  283. if (result == ResultApplicationAreaIsNotInitialized) {
  284. return NFP::ResultApplicationAreaIsNotInitialized;
  285. }
  286. if (result == ResultCorruptedDataWithBackup) {
  287. return NFP::ResultCorruptedDataWithBackup;
  288. }
  289. if (result == ResultCorruptedData) {
  290. return NFP::ResultCorruptedData;
  291. }
  292. if (result == ResultWrongApplicationAreaId) {
  293. return NFP::ResultWrongApplicationAreaId;
  294. }
  295. if (result == ResultApplicationAreaExist) {
  296. return NFP::ResultApplicationAreaExist;
  297. }
  298. if (result == ResultInvalidTagType) {
  299. return NFP::ResultNotAnAmiibo;
  300. }
  301. if (result == ResultUnableToAccessBackupFile) {
  302. return NFP::ResultUnableToAccessBackupFile;
  303. }
  304. LOG_WARNING(Service_NFC, "Result conversion not handled");
  305. return result;
  306. }
  307. Result NfcInterface::TranslateResultToMifare(Result result) const {
  308. if (result == ResultDeviceNotFound) {
  309. return Mifare::ResultDeviceNotFound;
  310. }
  311. if (result == ResultInvalidArgument) {
  312. return Mifare::ResultInvalidArgument;
  313. }
  314. if (result == ResultWrongDeviceState) {
  315. return Mifare::ResultWrongDeviceState;
  316. }
  317. if (result == ResultNfcDisabled) {
  318. return Mifare::ResultNfcDisabled;
  319. }
  320. if (result == ResultTagRemoved) {
  321. return Mifare::ResultTagRemoved;
  322. }
  323. if (result == ResultInvalidTagType) {
  324. return Mifare::ResultNotAMifare;
  325. }
  326. LOG_WARNING(Service_NFC, "Result conversion not handled");
  327. return result;
  328. }
  329. } // namespace Service::NFC