diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 29abb703f0..1e023303d3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -29,6 +29,7 @@ set(SRCS hle/kernel/address_arbiter.cpp hle/kernel/client_port.cpp hle/kernel/client_session.cpp + hle/kernel/domain.cpp hle/kernel/event.cpp hle/kernel/handle_table.cpp hle/kernel/hle_ipc.cpp @@ -118,6 +119,7 @@ set(HEADERS hle/kernel/address_arbiter.h hle/kernel/client_port.h hle/kernel/client_session.h + hle/kernel/domain.h hle/kernel/errors.h hle/kernel/event.h hle/kernel/handle_table.h diff --git a/src/core/hle/kernel/domain.cpp b/src/core/hle/kernel/domain.cpp new file mode 100644 index 0000000000..19ba861f5a --- /dev/null +++ b/src/core/hle/kernel/domain.cpp @@ -0,0 +1,44 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/domain.h" +#include "core/hle/kernel/handle_table.h" +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/process.h" +#include "core/hle/kernel/session.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +ResultVal> Domain::Create(std::string name) { + SharedPtr domain(new Domain); + domain->name = std::move(name); + return MakeResult(std::move(domain)); +} + +ResultVal> Domain::CreateFromSession(const Session& session) { + auto res = Create(session.port->GetName() + "_Domain"); + auto& domain = res.Unwrap(); + domain->request_handlers.push_back(std::move(session.server->hle_handler)); + Kernel::g_handle_table.ConvertSessionToDomain(session, domain); + return res; +} + +ResultCode Domain::SendSyncRequest(SharedPtr thread) { + Kernel::HLERequestContext context(this); + u32* cmd_buf = (u32*)Memory::GetPointer(Kernel::GetCurrentThread()->GetTLSAddress()); + context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process, + Kernel::g_handle_table); + + auto& domain_message_header = context.GetDomainMessageHeader(); + if (domain_message_header) { + // If there is a DomainMessageHeader, then this is CommandType "Request" + const u32 object_id{context.GetDomainMessageHeader()->object_id}; + return request_handlers[object_id - 1]->HandleSyncRequest(context); + } + return request_handlers.front()->HandleSyncRequest(context); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/domain.h b/src/core/hle/kernel/domain.h new file mode 100644 index 0000000000..74f7ad0dd4 --- /dev/null +++ b/src/core/hle/kernel/domain.h @@ -0,0 +1,45 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include "core/hle/kernel/sync_object.h" +#include "core/hle/result.h" + +namespace Kernel { + +class Session; +class SessionRequestHandler; + +class Domain final : public SyncObject { +public: + std::string GetTypeName() const override { + return "Domain"; + } + + static const HandleType HANDLE_TYPE = HandleType::Domain; + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + + static ResultVal> CreateFromSession(const Session& server); + + ResultCode SendSyncRequest(SharedPtr thread) override; + + /// The name of this domain (optional) + std::string name; + + std::vector> request_handlers; + +private: + Domain() = default; + ~Domain() override = default; + + static ResultVal> Create(std::string name = "Unknown"); +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 73fab3981e..e43055bfdd 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -31,6 +31,7 @@ enum class HandleType : u32 { ServerPort, ClientSession, ServerSession, + Domain, }; enum { @@ -83,12 +84,28 @@ public: case HandleType::CodeSet: case HandleType::ClientPort: case HandleType::ClientSession: + case HandleType::Domain: return false; } UNREACHABLE(); } + /** + * Check if svcSendSyncRequest can be called on the object + * @return True svcSendSyncRequest can be called on the object, otherwise false + */ + bool IsSyncable() const { + switch (GetHandleType()) { + case HandleType::ClientSession: + case HandleType::Domain: + return true; + } + + UNREACHABLE(); + } + + public: static unsigned int next_object_id; diff --git a/src/core/hle/kernel/sync_object.h b/src/core/hle/kernel/sync_object.h index ce2835ca4b..5d715226e0 100644 --- a/src/core/hle/kernel/sync_object.h +++ b/src/core/hle/kernel/sync_object.h @@ -16,10 +16,10 @@ class Thread; class SyncObject : public Object { public: /** - * Handle a sync request from the emulated application. - * @param thread Thread that initiated the request. - * @returns ResultCode from the operation. - */ + * Handle a sync request from the emulated application. + * @param thread Thread that initiated the request. + * @returns ResultCode from the operation. + */ virtual ResultCode SendSyncRequest(SharedPtr thread) = 0; };