summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-05-11 01:08:06 +0200
committerbunnei <bunneidev@gmail.com>2021-05-11 05:34:38 +0200
commit21671d05a362f98cd24dcc520a3da163e349fe07 (patch)
tree904d17169565cb12c4dd7ac8c640d136803ae686
parenthle: service: Implement IPC::CommandType::Close. (diff)
downloadyuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar
yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar.gz
yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar.bz2
yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar.lz
yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar.xz
yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar.zst
yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.zip
-rw-r--r--src/core/hle/service/service.cpp29
-rw-r--r--src/core/hle/service/service.h24
2 files changed, 52 insertions, 1 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index e36c35a86..2c9b2ce6d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -133,6 +133,16 @@ void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* function
}
}
+void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions,
+ std::size_t n) {
+ handlers_tipc.reserve(handlers_tipc.size() + n);
+ for (std::size_t i = 0; i < n; ++i) {
+ // Usually this array is sorted by id already, so hint to insert at the end
+ handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header,
+ functions[i]);
+ }
+}
+
void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx,
const FunctionInfoBase* info) {
auto cmd_buf = ctx.CommandBuffer();
@@ -167,6 +177,20 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
handler_invoker(this, info->handler_callback, ctx);
}
+void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) {
+ boost::container::flat_map<u32, FunctionInfoBase>::iterator itr;
+
+ itr = handlers_tipc.find(ctx.GetCommand());
+
+ const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second;
+ if (info == nullptr || info->handler_callback == nullptr) {
+ return ReportUnimplementedFunction(ctx, info);
+ }
+
+ LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
+ handler_invoker(this, info->handler_callback, ctx);
+}
+
ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
Kernel::HLERequestContext& ctx) {
const auto guard = LockService();
@@ -190,6 +214,11 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& sessi
break;
}
default:
+ if (ctx.IsTipc()) {
+ InvokeRequestTipc(ctx);
+ break;
+ }
+
UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType());
}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 51e22a791..3dfb0740a 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -21,7 +21,9 @@ class System;
namespace Kernel {
class HLERequestContext;
-}
+class KClientPort;
+class KServerSession;
+} // namespace Kernel
namespace Service {
@@ -67,6 +69,10 @@ public:
/// Invokes a service request routine using the HIPC protocol.
void InvokeRequest(Kernel::HLERequestContext& ctx);
+
+ /// Invokes a service request routine using the HIPC protocol.
+ void InvokeRequestTipc(Kernel::HLERequestContext& ctx);
+
/// Creates a port pair and registers it on the kernel's global port registry.
Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel);
@@ -105,6 +111,7 @@ private:
~ServiceFrameworkBase() override;
void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
+ void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n);
void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info);
/// Identifier string used to connect to the service.
@@ -119,6 +126,7 @@ private:
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
InvokerFn* handler_invoker;
boost::container::flat_map<u32, FunctionInfoBase> handlers;
+ boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
Common::SpinLock lock_service;
@@ -186,6 +194,20 @@ protected:
RegisterHandlersBase(functions, n);
}
+ /// Registers handlers in the service.
+ template <std::size_t N>
+ void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) {
+ RegisterHandlersTipc(functions, N);
+ }
+
+ /**
+ * Registers handlers in the service. Usually prefer using the other RegisterHandlers
+ * overload in order to avoid needing to specify the array size.
+ */
+ void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) {
+ RegisterHandlersBaseTipc(functions, n);
+ }
+
private:
/**
* This function is used to allow invocation of pointers to handlers stored in the base class