| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- // Copyright 2014 Citra Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #include <array>
- #include "common/logging/log.h"
- #include "core/hle/kernel/event.h"
- #include "core/hle/service/ac_u.h"
- namespace Service {
- namespace AC {
- struct ACConfig {
- std::array<u8, 0x200> data;
- };
- static ACConfig default_config{};
- static bool ac_connected = false;
- static Kernel::SharedPtr<Kernel::Event> close_event;
- static Kernel::SharedPtr<Kernel::Event> connect_event;
- static Kernel::SharedPtr<Kernel::Event> disconnect_event;
- /**
- * AC_U::CreateDefaultConfig service function
- * Inputs:
- * 64 : ACConfig size << 14 | 2
- * 65 : pointer to ACConfig struct
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
- static void CreateDefaultConfig(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 ac_config_addr = cmd_buff[65];
- ASSERT_MSG(cmd_buff[64] == (sizeof(ACConfig) << 14 | 2),
- "Output buffer size not equal ACConfig size");
- Memory::WriteBlock(ac_config_addr, &default_config, sizeof(ACConfig));
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::ConnectAsync service function
- * Inputs:
- * 1 : ProcessId Header
- * 3 : Copy Handle Header
- * 4 : Connection Event handle
- * 5 : ACConfig size << 14 | 2
- * 6 : pointer to ACConfig struct
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
- static void ConnectAsync(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- connect_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
- if (connect_event) {
- connect_event->name = "AC_U:connect_event";
- connect_event->Signal();
- ac_connected = true;
- }
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::GetConnectResult service function
- * Inputs:
- * 1 : ProcessId Header
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
- static void GetConnectResult(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::CloseAsync service function
- * Inputs:
- * 1 : ProcessId Header
- * 3 : Copy Handle Header
- * 4 : Event handle, should be signaled when AC connection is closed
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
- static void CloseAsync(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- if (ac_connected && disconnect_event) {
- disconnect_event->Signal();
- }
- close_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
- if (close_event) {
- close_event->name = "AC_U:close_event";
- close_event->Signal();
- }
- ac_connected = false;
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::GetCloseResult service function
- * Inputs:
- * 1 : ProcessId Header
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
- static void GetCloseResult(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::GetWifiStatus service function
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
- */
- static void GetWifiStatus(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- // TODO(purpasmart96): This function is only a stub,
- // it returns a valid result without implementing full functionality.
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- cmd_buff[2] = 0; // Connection type set to none
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::GetInfraPriority service function
- * Inputs:
- * 1 : ACConfig size << 14 | 2
- * 2 : pointer to ACConfig struct
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Infra Priority
- */
- static void GetInfraPriority(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- cmd_buff[2] = 0; // Infra Priority, default 0
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::SetRequestEulaVersion service function
- * Inputs:
- * 1 : Eula Version major
- * 2 : Eula Version minor
- * 3 : ACConfig size << 14 | 2
- * 4 : Input pointer to ACConfig struct
- * 64 : ACConfig size << 14 | 2
- * 65 : Output pointer to ACConfig struct
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : Infra Priority
- */
- static void SetRequestEulaVersion(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 major = cmd_buff[1] & 0xFF;
- u32 minor = cmd_buff[2] & 0xFF;
- ASSERT_MSG(cmd_buff[3] == (sizeof(ACConfig) << 14 | 2),
- "Input buffer size not equal ACConfig size");
- ASSERT_MSG(cmd_buff[64] == (sizeof(ACConfig) << 14 | 2),
- "Output buffer size not equal ACConfig size");
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- cmd_buff[2] = 0; // Infra Priority
- LOG_WARNING(Service_AC, "(STUBBED) called, major=%u, minor=%u", major, minor);
- }
- /**
- * AC_U::RegisterDisconnectEvent service function
- * Inputs:
- * 1 : ProcessId Header
- * 3 : Copy Handle Header
- * 4 : Event handle, should be signaled when AC connection is closed
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
- static void RegisterDisconnectEvent(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- disconnect_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
- if (disconnect_event) {
- disconnect_event->name = "AC_U:disconnect_event";
- }
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::IsConnected service function
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- * 2 : bool, is connected
- */
- static void IsConnected(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- cmd_buff[2] = ac_connected;
- LOG_WARNING(Service_AC, "(STUBBED) called");
- }
- /**
- * AC_U::SetClientVersion service function
- * Inputs:
- * 1 : Used SDK Version
- * Outputs:
- * 1 : Result of function, 0 on success, otherwise error code
- */
- static void SetClientVersion(Interface* self) {
- u32* cmd_buff = Kernel::GetCommandBuffer();
- const u32 version = cmd_buff[1];
- self->SetVersion(version);
- LOG_WARNING(Service_AC, "(STUBBED) called, version: 0x%08X", version);
- cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- }
- const Interface::FunctionInfo FunctionTable[] = {
- {0x00010000, CreateDefaultConfig, "CreateDefaultConfig"},
- {0x00040006, ConnectAsync, "ConnectAsync"},
- {0x00050002, GetConnectResult, "GetConnectResult"},
- {0x00070002, nullptr, "CancelConnectAsync"},
- {0x00080004, CloseAsync, "CloseAsync"},
- {0x00090002, GetCloseResult, "GetCloseResult"},
- {0x000A0000, nullptr, "GetLastErrorCode"},
- {0x000C0000, nullptr, "GetStatus"},
- {0x000D0000, GetWifiStatus, "GetWifiStatus"},
- {0x000E0042, nullptr, "GetCurrentAPInfo"},
- {0x00100042, nullptr, "GetCurrentNZoneInfo"},
- {0x00110042, nullptr, "GetNZoneApNumService"},
- {0x001D0042, nullptr, "ScanAPs"},
- {0x00240042, nullptr, "AddDenyApType"},
- {0x00270002, GetInfraPriority, "GetInfraPriority"},
- {0x002D0082, SetRequestEulaVersion, "SetRequestEulaVersion"},
- {0x00300004, RegisterDisconnectEvent, "RegisterDisconnectEvent"},
- {0x003C0042, nullptr, "GetAPSSIDList"},
- {0x003E0042, IsConnected, "IsConnected"},
- {0x00400042, SetClientVersion, "SetClientVersion"},
- };
- AC_U::AC_U() {
- Register(FunctionTable);
- ac_connected = false;
- close_event = nullptr;
- connect_event = nullptr;
- disconnect_event = nullptr;
- }
- AC_U::~AC_U() {
- close_event = nullptr;
- connect_event = nullptr;
- disconnect_event = nullptr;
- }
- } // namespace AC
- } // namespace Service
|