nfc_interface.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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);
  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. const auto tag_protocol{rp.PopEnum<NfcProtocol>()};
  114. LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol);
  115. auto result = GetManager()->StartDetection(device_handle, tag_protocol);
  116. result = TranslateResultToServiceError(result);
  117. IPC::ResponseBuilder rb{ctx, 2};
  118. rb.Push(result);
  119. }
  120. void NfcInterface::StopDetection(HLERequestContext& ctx) {
  121. IPC::RequestParser rp{ctx};
  122. const auto device_handle{rp.Pop<u64>()};
  123. LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
  124. auto result = GetManager()->StopDetection(device_handle);
  125. result = TranslateResultToServiceError(result);
  126. IPC::ResponseBuilder rb{ctx, 2};
  127. rb.Push(result);
  128. }
  129. void NfcInterface::GetTagInfo(HLERequestContext& ctx) {
  130. IPC::RequestParser rp{ctx};
  131. const auto device_handle{rp.Pop<u64>()};
  132. LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
  133. TagInfo tag_info{};
  134. auto result =
  135. GetManager()->GetTagInfo(device_handle, tag_info, backend_type == BackendType::Mifare);
  136. result = TranslateResultToServiceError(result);
  137. if (result.IsSuccess()) {
  138. ctx.WriteBuffer(tag_info);
  139. }
  140. IPC::ResponseBuilder rb{ctx, 2};
  141. rb.Push(result);
  142. }
  143. void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) {
  144. IPC::RequestParser rp{ctx};
  145. const auto device_handle{rp.Pop<u64>()};
  146. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  147. IPC::ResponseBuilder rb{ctx, 2, 1};
  148. rb.Push(ResultSuccess);
  149. rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle));
  150. }
  151. void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
  152. IPC::RequestParser rp{ctx};
  153. const auto device_handle{rp.Pop<u64>()};
  154. LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
  155. IPC::ResponseBuilder rb{ctx, 2, 1};
  156. rb.Push(ResultSuccess);
  157. rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle));
  158. }
  159. void NfcInterface::ReadMifare(HLERequestContext& ctx) {
  160. IPC::RequestParser rp{ctx};
  161. const auto device_handle{rp.Pop<u64>()};
  162. const auto buffer{ctx.ReadBuffer()};
  163. const auto number_of_commands{ctx.GetReadBufferNumElements<MifareReadBlockParameter>()};
  164. std::vector<MifareReadBlockParameter> read_commands(number_of_commands);
  165. memcpy(read_commands.data(), buffer.data(),
  166. number_of_commands * sizeof(MifareReadBlockParameter));
  167. LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
  168. device_handle, number_of_commands);
  169. std::vector<MifareReadBlockData> out_data(number_of_commands);
  170. auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data);
  171. result = TranslateResultToServiceError(result);
  172. if (result.IsSuccess()) {
  173. ctx.WriteBuffer(out_data);
  174. }
  175. IPC::ResponseBuilder rb{ctx, 2};
  176. rb.Push(result);
  177. }
  178. void NfcInterface::WriteMifare(HLERequestContext& ctx) {
  179. IPC::RequestParser rp{ctx};
  180. const auto device_handle{rp.Pop<u64>()};
  181. const auto buffer{ctx.ReadBuffer()};
  182. const auto number_of_commands{ctx.GetReadBufferNumElements<MifareWriteBlockParameter>()};
  183. std::vector<MifareWriteBlockParameter> write_commands(number_of_commands);
  184. memcpy(write_commands.data(), buffer.data(),
  185. number_of_commands * sizeof(MifareWriteBlockParameter));
  186. LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
  187. device_handle, number_of_commands);
  188. auto result = GetManager()->WriteMifare(device_handle, write_commands);
  189. result = TranslateResultToServiceError(result);
  190. IPC::ResponseBuilder rb{ctx, 2};
  191. rb.Push(result);
  192. }
  193. void NfcInterface::SendCommandByPassThrough(HLERequestContext& ctx) {
  194. IPC::RequestParser rp{ctx};
  195. const auto device_handle{rp.Pop<u64>()};
  196. const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()};
  197. const auto command_data{ctx.ReadBuffer()};
  198. LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}",
  199. device_handle, timeout.ToSeconds(), command_data.size());
  200. std::vector<u8> out_data(1);
  201. auto result =
  202. GetManager()->SendCommandByPassThrough(device_handle, timeout, command_data, out_data);
  203. result = TranslateResultToServiceError(result);
  204. if (result.IsError()) {
  205. IPC::ResponseBuilder rb{ctx, 2};
  206. rb.Push(result);
  207. return;
  208. }
  209. ctx.WriteBuffer(out_data);
  210. IPC::ResponseBuilder rb{ctx, 3};
  211. rb.Push(ResultSuccess);
  212. rb.Push(static_cast<u32>(out_data.size()));
  213. }
  214. std::shared_ptr<DeviceManager> NfcInterface::GetManager() {
  215. if (device_manager == nullptr) {
  216. device_manager = std::make_shared<DeviceManager>(system, service_context);
  217. }
  218. return device_manager;
  219. }
  220. BackendType NfcInterface::GetBackendType() const {
  221. return backend_type;
  222. }
  223. Result NfcInterface::TranslateResultToServiceError(Result result) const {
  224. const auto backend = GetBackendType();
  225. if (result.IsSuccess()) {
  226. return result;
  227. }
  228. if (result.module != ErrorModule::NFC) {
  229. return result;
  230. }
  231. switch (backend) {
  232. case BackendType::Mifare:
  233. return TranslateResultToNfp(result);
  234. case BackendType::Nfp: {
  235. return TranslateResultToNfp(result);
  236. }
  237. default:
  238. if (result != ResultBackupPathAlreadyExist) {
  239. return result;
  240. }
  241. return ResultUnknown74;
  242. }
  243. }
  244. Result NfcInterface::TranslateResultToNfp(Result result) const {
  245. if (result == ResultDeviceNotFound) {
  246. return NFP::ResultDeviceNotFound;
  247. }
  248. if (result == ResultInvalidArgument) {
  249. return NFP::ResultInvalidArgument;
  250. }
  251. if (result == ResultWrongApplicationAreaSize) {
  252. return NFP::ResultWrongApplicationAreaSize;
  253. }
  254. if (result == ResultWrongDeviceState) {
  255. return NFP::ResultWrongDeviceState;
  256. }
  257. if (result == ResultUnknown74) {
  258. return NFP::ResultUnknown74;
  259. }
  260. if (result == ResultNfcDisabled) {
  261. return NFP::ResultNfcDisabled;
  262. }
  263. if (result == ResultNfcNotInitialized) {
  264. return NFP::ResultNfcDisabled;
  265. }
  266. if (result == ResultWriteAmiiboFailed) {
  267. return NFP::ResultWriteAmiiboFailed;
  268. }
  269. if (result == ResultTagRemoved) {
  270. return NFP::ResultTagRemoved;
  271. }
  272. if (result == ResultRegistrationIsNotInitialized) {
  273. return NFP::ResultRegistrationIsNotInitialized;
  274. }
  275. if (result == ResultApplicationAreaIsNotInitialized) {
  276. return NFP::ResultApplicationAreaIsNotInitialized;
  277. }
  278. if (result == ResultCorruptedDataWithBackup) {
  279. return NFP::ResultCorruptedDataWithBackup;
  280. }
  281. if (result == ResultCorruptedData) {
  282. return NFP::ResultCorruptedData;
  283. }
  284. if (result == ResultWrongApplicationAreaId) {
  285. return NFP::ResultWrongApplicationAreaId;
  286. }
  287. if (result == ResultApplicationAreaExist) {
  288. return NFP::ResultApplicationAreaExist;
  289. }
  290. if (result == ResultNotAnAmiibo) {
  291. return NFP::ResultNotAnAmiibo;
  292. }
  293. if (result == ResultUnableToAccessBackupFile) {
  294. return NFP::ResultUnableToAccessBackupFile;
  295. }
  296. LOG_WARNING(Service_NFC, "Result conversion not handled");
  297. return result;
  298. }
  299. Result NfcInterface::TranslateResultToMifare(Result result) const {
  300. if (result == ResultDeviceNotFound) {
  301. return Mifare::ResultDeviceNotFound;
  302. }
  303. if (result == ResultInvalidArgument) {
  304. return Mifare::ResultInvalidArgument;
  305. }
  306. if (result == ResultWrongDeviceState) {
  307. return Mifare::ResultWrongDeviceState;
  308. }
  309. if (result == ResultNfcDisabled) {
  310. return Mifare::ResultNfcDisabled;
  311. }
  312. if (result == ResultTagRemoved) {
  313. return Mifare::ResultTagRemoved;
  314. }
  315. LOG_WARNING(Service_NFC, "Result conversion not handled");
  316. return result;
  317. }
  318. } // namespace Service::NFC