forked from moonpower/azahar-UWP
* apt: Implement additional library applet state management. * kernel: Clear process handle table on exit. * apt: Implement system applet commands. * apt: Pop MediaType from command buffers with correct size. * apt: Improve accuracy of parameters and HLE applet lifecycle. * apt: General cleanup. * file_sys: Make system save data open error code more correct. Not sure if this is the exact right error code, but it's at least more correct than before as Game Notes will now create its system save data instead of throwing a fatal error. * apt: Fix launching New 3DS Internet Browser. * frd: Correct fix to GetMyScreenName response.
196 lines
5.9 KiB
C++
196 lines
5.9 KiB
C++
// Copyright 2016 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <vector>
|
|
#include "common/archives.h"
|
|
#include "common/common_types.h"
|
|
#include "common/logging/log.h"
|
|
#include "core/core.h"
|
|
#include "core/hle/ipc.h"
|
|
#include "core/hle/ipc_helpers.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::AC {
|
|
void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x1, 0, 0);
|
|
|
|
std::vector<u8> buffer(sizeof(ACConfig));
|
|
std::memcpy(buffer.data(), &ac->default_config, buffer.size());
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushStaticBuffer(std::move(buffer), 0);
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::ConnectAsync(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x4, 0, 6);
|
|
|
|
rp.Skip(2, false); // ProcessId descriptor
|
|
ac->connect_event = rp.PopObject<Kernel::Event>();
|
|
rp.Skip(2, false); // Buffer descriptor
|
|
|
|
if (ac->connect_event) {
|
|
ac->connect_event->SetName("AC:connect_event");
|
|
ac->connect_event->Signal();
|
|
ac->ac_connected = true;
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::GetConnectResult(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x5, 0, 2);
|
|
rp.Skip(2, false); // ProcessId descriptor
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
}
|
|
|
|
void Module::Interface::CloseAsync(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x8, 0, 4);
|
|
rp.Skip(2, false); // ProcessId descriptor
|
|
|
|
ac->close_event = rp.PopObject<Kernel::Event>();
|
|
|
|
if (ac->ac_connected && ac->disconnect_event) {
|
|
ac->disconnect_event->Signal();
|
|
}
|
|
|
|
if (ac->close_event) {
|
|
ac->close_event->SetName("AC:close_event");
|
|
ac->close_event->Signal();
|
|
}
|
|
|
|
ac->ac_connected = false;
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
}
|
|
|
|
void Module::Interface::GetCloseResult(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x9, 0, 2);
|
|
rp.Skip(2, false); // ProcessId descriptor
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0xD, 0, 0);
|
|
|
|
// TODO(purpasmart96): This function is only a stub,
|
|
// it returns a valid result without implementing full functionality.
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.Push<u32>(0); // Connection type set to none
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x27, 0, 2);
|
|
[[maybe_unused]] const std::vector<u8>& ac_config = rp.PopStaticBuffer();
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.Push<u32>(0); // Infra Priority, default 0
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::SetRequestEulaVersion(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x2D, 2, 2);
|
|
|
|
u32 major = rp.Pop<u8>();
|
|
u32 minor = rp.Pop<u8>();
|
|
|
|
const std::vector<u8>& ac_config = rp.PopStaticBuffer();
|
|
|
|
// TODO(Subv): Copy over the input ACConfig to the stored ACConfig.
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.PushStaticBuffer(std::move(ac_config), 0);
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called, major={}, minor={}", major, minor);
|
|
}
|
|
|
|
void Module::Interface::RegisterDisconnectEvent(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x30, 0, 4);
|
|
rp.Skip(2, false); // ProcessId descriptor
|
|
|
|
ac->disconnect_event = rp.PopObject<Kernel::Event>();
|
|
if (ac->disconnect_event) {
|
|
ac->disconnect_event->SetName("AC:disconnect_event");
|
|
}
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called");
|
|
}
|
|
|
|
void Module::Interface::IsConnected(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x3E, 1, 2);
|
|
u32 unk = rp.Pop<u32>();
|
|
u32 unk_descriptor = rp.Pop<u32>();
|
|
u32 unk_param = rp.Pop<u32>();
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
rb.Push(ac->ac_connected);
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called unk=0x{:08X} descriptor=0x{:08X} param=0x{:08X}", unk,
|
|
unk_descriptor, unk_param);
|
|
}
|
|
|
|
void Module::Interface::SetClientVersion(Kernel::HLERequestContext& ctx) {
|
|
IPC::RequestParser rp(ctx, 0x40, 1, 2);
|
|
|
|
u32 version = rp.Pop<u32>();
|
|
rp.Skip(2, false); // ProcessId descriptor
|
|
|
|
LOG_WARNING(Service_AC, "(STUBBED) called, version: 0x{:08X}", version);
|
|
|
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
rb.Push(RESULT_SUCCESS);
|
|
}
|
|
|
|
Module::Interface::Interface(std::shared_ptr<Module> ac, const char* name, u32 max_session)
|
|
: ServiceFramework(name, max_session), ac(std::move(ac)) {}
|
|
|
|
void InstallInterfaces(Core::System& system) {
|
|
auto& service_manager = system.ServiceManager();
|
|
auto ac = std::make_shared<Module>();
|
|
std::make_shared<AC_I>(ac)->InstallAsService(service_manager);
|
|
std::make_shared<AC_U>(ac)->InstallAsService(service_manager);
|
|
}
|
|
|
|
template <class Archive>
|
|
void Module::serialize(Archive& ar, const unsigned int) {
|
|
ar& ac_connected;
|
|
ar& close_event;
|
|
ar& connect_event;
|
|
ar& disconnect_event;
|
|
// default_config is never written to
|
|
}
|
|
|
|
} // namespace Service::AC
|
|
|
|
SERIALIZE_IMPL(Service::AC::Module)
|