mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-28 01:30:03 +00:00
c9c1ba0952
The real kernel requires services to set up their static buffer targets ahead of time. This implementation does not require that and will simply create the storage for the buffers as they are processed in the incoming IPC request. Static buffers are kept in an unordered_map keyed by their buffer id, and are written into the already-setup area of the request thread when responding an IPC request. This fixes a regression (crash) introduced in #2992. This PR introduces more warnings due to the [[deprecated]] attribute being added to void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id); and VAddr PopStaticBuffer(size_t* data_size);
183 lines
5.5 KiB
C++
183 lines
5.5 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/common_types.h"
|
|
#include "common/logging/log.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 {
|
|
namespace 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>();
|
|
|
|
if (ac->connect_event) {
|
|
ac->connect_event->name = "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->name = "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);
|
|
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=%u, minor=%u", 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->name = "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=%08X descriptor=%08X param=%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)
|
|
: ac(std::move(ac)), ServiceFramework(name, max_session) {}
|
|
|
|
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
|
auto ac = std::make_shared<Module>();
|
|
std::make_shared<AC_I>(ac)->InstallAsService(service_manager);
|
|
std::make_shared<AC_U>(ac)->InstallAsService(service_manager);
|
|
}
|
|
|
|
} // namespace AC
|
|
} // namespace Service
|