nifm.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "core/core.h"
  5. #include "core/hle/ipc_helpers.h"
  6. #include "core/hle/kernel/kernel.h"
  7. #include "core/hle/kernel/readable_event.h"
  8. #include "core/hle/kernel/writable_event.h"
  9. #include "core/hle/service/nifm/nifm.h"
  10. #include "core/hle/service/service.h"
  11. #include "core/network/network.h"
  12. #include "core/settings.h"
  13. namespace Service::NIFM {
  14. enum class RequestState : u32 {
  15. NotSubmitted = 1,
  16. Error = 1, ///< The duplicate 1 is intentional; it means both not submitted and error on HW.
  17. Pending = 2,
  18. Connected = 3,
  19. };
  20. class IScanRequest final : public ServiceFramework<IScanRequest> {
  21. public:
  22. explicit IScanRequest() : ServiceFramework("IScanRequest") {
  23. // clang-format off
  24. static const FunctionInfo functions[] = {
  25. {0, nullptr, "Submit"},
  26. {1, nullptr, "IsProcessing"},
  27. {2, nullptr, "GetResult"},
  28. {3, nullptr, "GetSystemEventReadableHandle"},
  29. {4, nullptr, "SetChannels"},
  30. };
  31. // clang-format on
  32. RegisterHandlers(functions);
  33. }
  34. };
  35. class IRequest final : public ServiceFramework<IRequest> {
  36. public:
  37. explicit IRequest(Core::System& system) : ServiceFramework("IRequest") {
  38. static const FunctionInfo functions[] = {
  39. {0, &IRequest::GetRequestState, "GetRequestState"},
  40. {1, &IRequest::GetResult, "GetResult"},
  41. {2, &IRequest::GetSystemEventReadableHandles, "GetSystemEventReadableHandles"},
  42. {3, &IRequest::Cancel, "Cancel"},
  43. {4, &IRequest::Submit, "Submit"},
  44. {5, nullptr, "SetRequirement"},
  45. {6, nullptr, "SetRequirementPreset"},
  46. {8, nullptr, "SetPriority"},
  47. {9, nullptr, "SetNetworkProfileId"},
  48. {10, nullptr, "SetRejectable"},
  49. {11, &IRequest::SetConnectionConfirmationOption, "SetConnectionConfirmationOption"},
  50. {12, nullptr, "SetPersistent"},
  51. {13, nullptr, "SetInstant"},
  52. {14, nullptr, "SetSustainable"},
  53. {15, nullptr, "SetRawPriority"},
  54. {16, nullptr, "SetGreedy"},
  55. {17, nullptr, "SetSharable"},
  56. {18, nullptr, "SetRequirementByRevision"},
  57. {19, nullptr, "GetRequirement"},
  58. {20, nullptr, "GetRevision"},
  59. {21, nullptr, "GetAppletInfo"},
  60. {22, nullptr, "GetAdditionalInfo"},
  61. {23, nullptr, "SetKeptInSleep"},
  62. {24, nullptr, "RegisterSocketDescriptor"},
  63. {25, nullptr, "UnregisterSocketDescriptor"},
  64. };
  65. RegisterHandlers(functions);
  66. auto& kernel = system.Kernel();
  67. event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1");
  68. event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2");
  69. }
  70. private:
  71. void Submit(Kernel::HLERequestContext& ctx) {
  72. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  73. IPC::ResponseBuilder rb{ctx, 2};
  74. rb.Push(RESULT_SUCCESS);
  75. }
  76. void GetRequestState(Kernel::HLERequestContext& ctx) {
  77. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  78. IPC::ResponseBuilder rb{ctx, 3};
  79. rb.Push(RESULT_SUCCESS);
  80. if (Settings::values.bcat_backend == "none") {
  81. rb.PushEnum(RequestState::NotSubmitted);
  82. } else {
  83. rb.PushEnum(RequestState::Connected);
  84. }
  85. }
  86. void GetResult(Kernel::HLERequestContext& ctx) {
  87. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  88. IPC::ResponseBuilder rb{ctx, 2};
  89. rb.Push(RESULT_SUCCESS);
  90. }
  91. void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) {
  92. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  93. IPC::ResponseBuilder rb{ctx, 2, 2};
  94. rb.Push(RESULT_SUCCESS);
  95. rb.PushCopyObjects(event1.readable, event2.readable);
  96. }
  97. void Cancel(Kernel::HLERequestContext& ctx) {
  98. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  99. IPC::ResponseBuilder rb{ctx, 2};
  100. rb.Push(RESULT_SUCCESS);
  101. }
  102. void SetConnectionConfirmationOption(Kernel::HLERequestContext& ctx) {
  103. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  104. IPC::ResponseBuilder rb{ctx, 2};
  105. rb.Push(RESULT_SUCCESS);
  106. }
  107. Kernel::EventPair event1, event2;
  108. };
  109. class INetworkProfile final : public ServiceFramework<INetworkProfile> {
  110. public:
  111. explicit INetworkProfile() : ServiceFramework("INetworkProfile") {
  112. static const FunctionInfo functions[] = {
  113. {0, nullptr, "Update"},
  114. {1, nullptr, "PersistOld"},
  115. {2, nullptr, "Persist"},
  116. };
  117. RegisterHandlers(functions);
  118. }
  119. };
  120. class IGeneralService final : public ServiceFramework<IGeneralService> {
  121. public:
  122. IGeneralService(Core::System& system);
  123. private:
  124. void GetClientId(Kernel::HLERequestContext& ctx) {
  125. static constexpr u32 client_id = 1;
  126. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  127. IPC::ResponseBuilder rb{ctx, 4};
  128. rb.Push(RESULT_SUCCESS);
  129. rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid
  130. }
  131. void CreateScanRequest(Kernel::HLERequestContext& ctx) {
  132. LOG_DEBUG(Service_NIFM, "called");
  133. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  134. rb.Push(RESULT_SUCCESS);
  135. rb.PushIpcInterface<IScanRequest>();
  136. }
  137. void CreateRequest(Kernel::HLERequestContext& ctx) {
  138. LOG_DEBUG(Service_NIFM, "called");
  139. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  140. rb.Push(RESULT_SUCCESS);
  141. rb.PushIpcInterface<IRequest>(system);
  142. }
  143. void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
  144. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  145. IPC::ResponseBuilder rb{ctx, 2};
  146. rb.Push(RESULT_SUCCESS);
  147. }
  148. void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) {
  149. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  150. const auto [ipv4, error] = Network::GetHostIPv4Address();
  151. UNIMPLEMENTED_IF(error != Network::Errno::SUCCESS);
  152. IPC::ResponseBuilder rb{ctx, 3};
  153. rb.Push(RESULT_SUCCESS);
  154. rb.PushRaw(ipv4);
  155. }
  156. void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
  157. LOG_DEBUG(Service_NIFM, "called");
  158. ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c,
  159. "SfNetworkProfileData is not the correct size");
  160. u128 uuid{};
  161. auto buffer = ctx.ReadBuffer();
  162. std::memcpy(&uuid, buffer.data() + 8, sizeof(u128));
  163. IPC::ResponseBuilder rb{ctx, 6, 0, 1};
  164. rb.Push(RESULT_SUCCESS);
  165. rb.PushIpcInterface<INetworkProfile>();
  166. rb.PushRaw<u128>(uuid);
  167. }
  168. void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
  169. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  170. IPC::ResponseBuilder rb{ctx, 3};
  171. rb.Push(RESULT_SUCCESS);
  172. rb.Push<u8>(0);
  173. }
  174. void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) {
  175. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  176. IPC::ResponseBuilder rb{ctx, 3};
  177. rb.Push(RESULT_SUCCESS);
  178. if (Settings::values.bcat_backend == "none") {
  179. rb.Push<u8>(0);
  180. } else {
  181. rb.Push<u8>(1);
  182. }
  183. }
  184. void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
  185. LOG_WARNING(Service_NIFM, "(STUBBED) called");
  186. IPC::ResponseBuilder rb{ctx, 3};
  187. rb.Push(RESULT_SUCCESS);
  188. if (Settings::values.bcat_backend == "none") {
  189. rb.Push<u8>(0);
  190. } else {
  191. rb.Push<u8>(1);
  192. }
  193. }
  194. Core::System& system;
  195. };
  196. IGeneralService::IGeneralService(Core::System& system)
  197. : ServiceFramework("IGeneralService"), system(system) {
  198. // clang-format off
  199. static const FunctionInfo functions[] = {
  200. {1, &IGeneralService::GetClientId, "GetClientId"},
  201. {2, &IGeneralService::CreateScanRequest, "CreateScanRequest"},
  202. {4, &IGeneralService::CreateRequest, "CreateRequest"},
  203. {5, nullptr, "GetCurrentNetworkProfile"},
  204. {6, nullptr, "EnumerateNetworkInterfaces"},
  205. {7, nullptr, "EnumerateNetworkProfiles"},
  206. {8, nullptr, "GetNetworkProfile"},
  207. {9, nullptr, "SetNetworkProfile"},
  208. {10, &IGeneralService::RemoveNetworkProfile, "RemoveNetworkProfile"},
  209. {11, nullptr, "GetScanDataOld"},
  210. {12, &IGeneralService::GetCurrentIpAddress, "GetCurrentIpAddress"},
  211. {13, nullptr, "GetCurrentAccessPointOld"},
  212. {14, &IGeneralService::CreateTemporaryNetworkProfile, "CreateTemporaryNetworkProfile"},
  213. {15, nullptr, "GetCurrentIpConfigInfo"},
  214. {16, nullptr, "SetWirelessCommunicationEnabled"},
  215. {17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
  216. {18, nullptr, "GetInternetConnectionStatus"},
  217. {19, nullptr, "SetEthernetCommunicationEnabled"},
  218. {20, &IGeneralService::IsEthernetCommunicationEnabled, "IsEthernetCommunicationEnabled"},
  219. {21, &IGeneralService::IsAnyInternetRequestAccepted, "IsAnyInternetRequestAccepted"},
  220. {22, nullptr, "IsAnyForegroundRequestAccepted"},
  221. {23, nullptr, "PutToSleep"},
  222. {24, nullptr, "WakeUp"},
  223. {25, nullptr, "GetSsidListVersion"},
  224. {26, nullptr, "SetExclusiveClient"},
  225. {27, nullptr, "GetDefaultIpSetting"},
  226. {28, nullptr, "SetDefaultIpSetting"},
  227. {29, nullptr, "SetWirelessCommunicationEnabledForTest"},
  228. {30, nullptr, "SetEthernetCommunicationEnabledForTest"},
  229. {31, nullptr, "GetTelemetorySystemEventReadableHandle"},
  230. {32, nullptr, "GetTelemetryInfo"},
  231. {33, nullptr, "ConfirmSystemAvailability"},
  232. {34, nullptr, "SetBackgroundRequestEnabled"},
  233. {35, nullptr, "GetScanData"},
  234. {36, nullptr, "GetCurrentAccessPoint"},
  235. {37, nullptr, "Shutdown"},
  236. {38, nullptr, "GetAllowedChannels"},
  237. {39, nullptr, "NotifyApplicationSuspended"},
  238. {40, nullptr, "SetAcceptableNetworkTypeFlag"},
  239. {41, nullptr, "GetAcceptableNetworkTypeFlag"},
  240. {42, nullptr, "NotifyConnectionStateChanged"},
  241. {43, nullptr, "SetWowlDelayedWakeTime"},
  242. };
  243. // clang-format on
  244. RegisterHandlers(functions);
  245. }
  246. class NetworkInterface final : public ServiceFramework<NetworkInterface> {
  247. public:
  248. explicit NetworkInterface(const char* name, Core::System& system)
  249. : ServiceFramework{name}, system(system) {
  250. static const FunctionInfo functions[] = {
  251. {4, &NetworkInterface::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
  252. {5, &NetworkInterface::CreateGeneralService, "CreateGeneralService"},
  253. };
  254. RegisterHandlers(functions);
  255. }
  256. void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
  257. LOG_DEBUG(Service_NIFM, "called");
  258. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  259. rb.Push(RESULT_SUCCESS);
  260. rb.PushIpcInterface<IGeneralService>(system);
  261. }
  262. void CreateGeneralService(Kernel::HLERequestContext& ctx) {
  263. LOG_DEBUG(Service_NIFM, "called");
  264. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  265. rb.Push(RESULT_SUCCESS);
  266. rb.PushIpcInterface<IGeneralService>(system);
  267. }
  268. private:
  269. Core::System& system;
  270. };
  271. void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
  272. std::make_shared<NetworkInterface>("nifm:a", system)->InstallAsService(service_manager);
  273. std::make_shared<NetworkInterface>("nifm:s", system)->InstallAsService(service_manager);
  274. std::make_shared<NetworkInterface>("nifm:u", system)->InstallAsService(service_manager);
  275. }
  276. } // namespace Service::NIFM