ac_u.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include "common/logging/log.h"
  6. #include "core/hle/kernel/event.h"
  7. #include "core/hle/service/ac_u.h"
  8. namespace Service {
  9. namespace AC {
  10. struct ACConfig {
  11. std::array<u8, 0x200> data;
  12. };
  13. static ACConfig default_config{};
  14. static bool ac_connected = false;
  15. static Kernel::SharedPtr<Kernel::Event> close_event;
  16. static Kernel::SharedPtr<Kernel::Event> connect_event;
  17. static Kernel::SharedPtr<Kernel::Event> disconnect_event;
  18. /**
  19. * AC_U::CreateDefaultConfig service function
  20. * Inputs:
  21. * 64 : ACConfig size << 14 | 2
  22. * 65 : pointer to ACConfig struct
  23. * Outputs:
  24. * 1 : Result of function, 0 on success, otherwise error code
  25. */
  26. static void CreateDefaultConfig(Interface* self) {
  27. u32* cmd_buff = Kernel::GetCommandBuffer();
  28. u32 ac_config_addr = cmd_buff[65];
  29. ASSERT_MSG(cmd_buff[64] == (sizeof(ACConfig) << 14 | 2),
  30. "Output buffer size not equal ACConfig size");
  31. Memory::WriteBlock(ac_config_addr, &default_config, sizeof(ACConfig));
  32. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  33. LOG_WARNING(Service_AC, "(STUBBED) called");
  34. }
  35. /**
  36. * AC_U::ConnectAsync service function
  37. * Inputs:
  38. * 1 : ProcessId Header
  39. * 3 : Copy Handle Header
  40. * 4 : Connection Event handle
  41. * 5 : ACConfig size << 14 | 2
  42. * 6 : pointer to ACConfig struct
  43. * Outputs:
  44. * 1 : Result of function, 0 on success, otherwise error code
  45. */
  46. static void ConnectAsync(Interface* self) {
  47. u32* cmd_buff = Kernel::GetCommandBuffer();
  48. connect_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
  49. if (connect_event) {
  50. connect_event->name = "AC_U:connect_event";
  51. connect_event->Signal();
  52. ac_connected = true;
  53. }
  54. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  55. LOG_WARNING(Service_AC, "(STUBBED) called");
  56. }
  57. /**
  58. * AC_U::GetConnectResult service function
  59. * Inputs:
  60. * 1 : ProcessId Header
  61. * Outputs:
  62. * 1 : Result of function, 0 on success, otherwise error code
  63. */
  64. static void GetConnectResult(Interface* self) {
  65. u32* cmd_buff = Kernel::GetCommandBuffer();
  66. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  67. LOG_WARNING(Service_AC, "(STUBBED) called");
  68. }
  69. /**
  70. * AC_U::CloseAsync service function
  71. * Inputs:
  72. * 1 : ProcessId Header
  73. * 3 : Copy Handle Header
  74. * 4 : Event handle, should be signaled when AC connection is closed
  75. * Outputs:
  76. * 1 : Result of function, 0 on success, otherwise error code
  77. */
  78. static void CloseAsync(Interface* self) {
  79. u32* cmd_buff = Kernel::GetCommandBuffer();
  80. if (ac_connected && disconnect_event) {
  81. disconnect_event->Signal();
  82. }
  83. close_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
  84. if (close_event) {
  85. close_event->name = "AC_U:close_event";
  86. close_event->Signal();
  87. }
  88. ac_connected = false;
  89. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  90. LOG_WARNING(Service_AC, "(STUBBED) called");
  91. }
  92. /**
  93. * AC_U::GetCloseResult service function
  94. * Inputs:
  95. * 1 : ProcessId Header
  96. * Outputs:
  97. * 1 : Result of function, 0 on success, otherwise error code
  98. */
  99. static void GetCloseResult(Interface* self) {
  100. u32* cmd_buff = Kernel::GetCommandBuffer();
  101. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  102. LOG_WARNING(Service_AC, "(STUBBED) called");
  103. }
  104. /**
  105. * AC_U::GetWifiStatus service function
  106. * Outputs:
  107. * 1 : Result of function, 0 on success, otherwise error code
  108. * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
  109. */
  110. static void GetWifiStatus(Interface* self) {
  111. u32* cmd_buff = Kernel::GetCommandBuffer();
  112. // TODO(purpasmart96): This function is only a stub,
  113. // it returns a valid result without implementing full functionality.
  114. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  115. cmd_buff[2] = 0; // Connection type set to none
  116. LOG_WARNING(Service_AC, "(STUBBED) called");
  117. }
  118. /**
  119. * AC_U::GetInfraPriority service function
  120. * Inputs:
  121. * 1 : ACConfig size << 14 | 2
  122. * 2 : pointer to ACConfig struct
  123. * Outputs:
  124. * 1 : Result of function, 0 on success, otherwise error code
  125. * 2 : Infra Priority
  126. */
  127. static void GetInfraPriority(Interface* self) {
  128. u32* cmd_buff = Kernel::GetCommandBuffer();
  129. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  130. cmd_buff[2] = 0; // Infra Priority, default 0
  131. LOG_WARNING(Service_AC, "(STUBBED) called");
  132. }
  133. /**
  134. * AC_U::SetRequestEulaVersion service function
  135. * Inputs:
  136. * 1 : Eula Version major
  137. * 2 : Eula Version minor
  138. * 3 : ACConfig size << 14 | 2
  139. * 4 : Input pointer to ACConfig struct
  140. * 64 : ACConfig size << 14 | 2
  141. * 65 : Output pointer to ACConfig struct
  142. * Outputs:
  143. * 1 : Result of function, 0 on success, otherwise error code
  144. * 2 : Infra Priority
  145. */
  146. static void SetRequestEulaVersion(Interface* self) {
  147. u32* cmd_buff = Kernel::GetCommandBuffer();
  148. u32 major = cmd_buff[1] & 0xFF;
  149. u32 minor = cmd_buff[2] & 0xFF;
  150. ASSERT_MSG(cmd_buff[3] == (sizeof(ACConfig) << 14 | 2),
  151. "Input buffer size not equal ACConfig size");
  152. ASSERT_MSG(cmd_buff[64] == (sizeof(ACConfig) << 14 | 2),
  153. "Output buffer size not equal ACConfig size");
  154. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  155. cmd_buff[2] = 0; // Infra Priority
  156. LOG_WARNING(Service_AC, "(STUBBED) called, major=%u, minor=%u", major, minor);
  157. }
  158. /**
  159. * AC_U::RegisterDisconnectEvent service function
  160. * Inputs:
  161. * 1 : ProcessId Header
  162. * 3 : Copy Handle Header
  163. * 4 : Event handle, should be signaled when AC connection is closed
  164. * Outputs:
  165. * 1 : Result of function, 0 on success, otherwise error code
  166. */
  167. static void RegisterDisconnectEvent(Interface* self) {
  168. u32* cmd_buff = Kernel::GetCommandBuffer();
  169. disconnect_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
  170. if (disconnect_event) {
  171. disconnect_event->name = "AC_U:disconnect_event";
  172. }
  173. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  174. LOG_WARNING(Service_AC, "(STUBBED) called");
  175. }
  176. /**
  177. * AC_U::IsConnected service function
  178. * Outputs:
  179. * 1 : Result of function, 0 on success, otherwise error code
  180. * 2 : bool, is connected
  181. */
  182. static void IsConnected(Interface* self) {
  183. u32* cmd_buff = Kernel::GetCommandBuffer();
  184. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  185. cmd_buff[2] = ac_connected;
  186. LOG_WARNING(Service_AC, "(STUBBED) called");
  187. }
  188. /**
  189. * AC_U::SetClientVersion service function
  190. * Inputs:
  191. * 1 : Used SDK Version
  192. * Outputs:
  193. * 1 : Result of function, 0 on success, otherwise error code
  194. */
  195. static void SetClientVersion(Interface* self) {
  196. u32* cmd_buff = Kernel::GetCommandBuffer();
  197. const u32 version = cmd_buff[1];
  198. self->SetVersion(version);
  199. LOG_WARNING(Service_AC, "(STUBBED) called, version: 0x%08X", version);
  200. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  201. }
  202. const Interface::FunctionInfo FunctionTable[] = {
  203. {0x00010000, CreateDefaultConfig, "CreateDefaultConfig"},
  204. {0x00040006, ConnectAsync, "ConnectAsync"},
  205. {0x00050002, GetConnectResult, "GetConnectResult"},
  206. {0x00070002, nullptr, "CancelConnectAsync"},
  207. {0x00080004, CloseAsync, "CloseAsync"},
  208. {0x00090002, GetCloseResult, "GetCloseResult"},
  209. {0x000A0000, nullptr, "GetLastErrorCode"},
  210. {0x000C0000, nullptr, "GetStatus"},
  211. {0x000D0000, GetWifiStatus, "GetWifiStatus"},
  212. {0x000E0042, nullptr, "GetCurrentAPInfo"},
  213. {0x00100042, nullptr, "GetCurrentNZoneInfo"},
  214. {0x00110042, nullptr, "GetNZoneApNumService"},
  215. {0x001D0042, nullptr, "ScanAPs"},
  216. {0x00240042, nullptr, "AddDenyApType"},
  217. {0x00270002, GetInfraPriority, "GetInfraPriority"},
  218. {0x002D0082, SetRequestEulaVersion, "SetRequestEulaVersion"},
  219. {0x00300004, RegisterDisconnectEvent, "RegisterDisconnectEvent"},
  220. {0x003C0042, nullptr, "GetAPSSIDList"},
  221. {0x003E0042, IsConnected, "IsConnected"},
  222. {0x00400042, SetClientVersion, "SetClientVersion"},
  223. };
  224. AC_U::AC_U() {
  225. Register(FunctionTable);
  226. ac_connected = false;
  227. close_event = nullptr;
  228. connect_event = nullptr;
  229. disconnect_event = nullptr;
  230. }
  231. AC_U::~AC_U() {
  232. close_event = nullptr;
  233. connect_event = nullptr;
  234. disconnect_event = nullptr;
  235. }
  236. } // namespace AC
  237. } // namespace Service