// Copyright 2016 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include #include "common/common_types.h" #include "common/logging/log.h" #include "core/hle/ipc.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/result.h" #include "core/hle/service/ac/ac.h" #include "core/hle/service/ac/ac_i.h" #include "core/hle/service/ac/ac_u.h" #include "core/memory.h" namespace Service { namespace AC { struct ACConfig { std::array data; }; static ACConfig default_config{}; static bool ac_connected = false; static Kernel::SharedPtr close_event; static Kernel::SharedPtr connect_event; static Kernel::SharedPtr disconnect_event; 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"); } void ConnectAsync(Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); connect_event = Kernel::g_handle_table.Get(cmd_buff[4]); if (connect_event) { connect_event->name = "AC:connect_event"; connect_event->Signal(); ac_connected = true; } cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_AC, "(STUBBED) called"); } void GetConnectResult(Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_AC, "(STUBBED) called"); } void CloseAsync(Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); if (ac_connected && disconnect_event) { disconnect_event->Signal(); } close_event = Kernel::g_handle_table.Get(cmd_buff[4]); if (close_event) { close_event->name = "AC:close_event"; close_event->Signal(); } ac_connected = false; cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_AC, "(STUBBED) called"); } void GetCloseResult(Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_AC, "(STUBBED) called"); } 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"); } 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"); } 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); } void RegisterDisconnectEvent(Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); disconnect_event = Kernel::g_handle_table.Get(cmd_buff[4]); if (disconnect_event) { disconnect_event->name = "AC:disconnect_event"; } cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_AC, "(STUBBED) called"); } 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"); } 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 } void Init() { AddService(new AC_I); AddService(new AC_U); ac_connected = false; close_event = nullptr; connect_event = nullptr; disconnect_event = nullptr; } void Shutdown() { ac_connected = false; close_event = nullptr; connect_event = nullptr; disconnect_event = nullptr; } } // namespace AC } // namespace Service