diff options
| author | 2021-05-10 16:08:06 -0700 | |
|---|---|---|
| committer | 2021-05-10 20:34:38 -0700 | |
| commit | 21671d05a362f98cd24dcc520a3da163e349fe07 (patch) | |
| tree | 904d17169565cb12c4dd7ac8c640d136803ae686 | |
| parent | hle: service: Implement IPC::CommandType::Close. (diff) | |
| download | yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar.gz yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.tar.xz yuzu-21671d05a362f98cd24dcc520a3da163e349fe07.zip | |
hle: service: Add support for dispatching TIPC requests.
| -rw-r--r-- | src/core/hle/service/service.cpp | 29 | ||||
| -rw-r--r-- | src/core/hle/service/service.h | 24 |
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 | |||
| 133 | } | 133 | } |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, | ||
| 137 | std::size_t n) { | ||
| 138 | handlers_tipc.reserve(handlers_tipc.size() + n); | ||
| 139 | for (std::size_t i = 0; i < n; ++i) { | ||
| 140 | // Usually this array is sorted by id already, so hint to insert at the end | ||
| 141 | handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, | ||
| 142 | functions[i]); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 136 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, | 146 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, |
| 137 | const FunctionInfoBase* info) { | 147 | const FunctionInfoBase* info) { |
| 138 | auto cmd_buf = ctx.CommandBuffer(); | 148 | auto cmd_buf = ctx.CommandBuffer(); |
| @@ -167,6 +177,20 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { | |||
| 167 | handler_invoker(this, info->handler_callback, ctx); | 177 | handler_invoker(this, info->handler_callback, ctx); |
| 168 | } | 178 | } |
| 169 | 179 | ||
| 180 | void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) { | ||
| 181 | boost::container::flat_map<u32, FunctionInfoBase>::iterator itr; | ||
| 182 | |||
| 183 | itr = handlers_tipc.find(ctx.GetCommand()); | ||
| 184 | |||
| 185 | const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second; | ||
| 186 | if (info == nullptr || info->handler_callback == nullptr) { | ||
| 187 | return ReportUnimplementedFunction(ctx, info); | ||
| 188 | } | ||
| 189 | |||
| 190 | LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); | ||
| 191 | handler_invoker(this, info->handler_callback, ctx); | ||
| 192 | } | ||
| 193 | |||
| 170 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, | 194 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, |
| 171 | Kernel::HLERequestContext& ctx) { | 195 | Kernel::HLERequestContext& ctx) { |
| 172 | const auto guard = LockService(); | 196 | const auto guard = LockService(); |
| @@ -190,6 +214,11 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& sessi | |||
| 190 | break; | 214 | break; |
| 191 | } | 215 | } |
| 192 | default: | 216 | default: |
| 217 | if (ctx.IsTipc()) { | ||
| 218 | InvokeRequestTipc(ctx); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | |||
| 193 | UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); | 222 | UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); |
| 194 | } | 223 | } |
| 195 | 224 | ||
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; | |||
| 21 | 21 | ||
| 22 | namespace Kernel { | 22 | namespace Kernel { |
| 23 | class HLERequestContext; | 23 | class HLERequestContext; |
| 24 | } | 24 | class KClientPort; |
| 25 | class KServerSession; | ||
| 26 | } // namespace Kernel | ||
| 25 | 27 | ||
| 26 | namespace Service { | 28 | namespace Service { |
| 27 | 29 | ||
| @@ -67,6 +69,10 @@ public: | |||
| 67 | 69 | ||
| 68 | /// Invokes a service request routine using the HIPC protocol. | 70 | /// Invokes a service request routine using the HIPC protocol. |
| 69 | void InvokeRequest(Kernel::HLERequestContext& ctx); | 71 | void InvokeRequest(Kernel::HLERequestContext& ctx); |
| 72 | |||
| 73 | /// Invokes a service request routine using the HIPC protocol. | ||
| 74 | void InvokeRequestTipc(Kernel::HLERequestContext& ctx); | ||
| 75 | |||
| 70 | /// Creates a port pair and registers it on the kernel's global port registry. | 76 | /// Creates a port pair and registers it on the kernel's global port registry. |
| 71 | Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel); | 77 | Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel); |
| 72 | 78 | ||
| @@ -105,6 +111,7 @@ private: | |||
| 105 | ~ServiceFrameworkBase() override; | 111 | ~ServiceFrameworkBase() override; |
| 106 | 112 | ||
| 107 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); | 113 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); |
| 114 | void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n); | ||
| 108 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); | 115 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); |
| 109 | 116 | ||
| 110 | /// Identifier string used to connect to the service. | 117 | /// Identifier string used to connect to the service. |
| @@ -119,6 +126,7 @@ private: | |||
| 119 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. | 126 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. |
| 120 | InvokerFn* handler_invoker; | 127 | InvokerFn* handler_invoker; |
| 121 | boost::container::flat_map<u32, FunctionInfoBase> handlers; | 128 | boost::container::flat_map<u32, FunctionInfoBase> handlers; |
| 129 | boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc; | ||
| 122 | 130 | ||
| 123 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. | 131 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. |
| 124 | Common::SpinLock lock_service; | 132 | Common::SpinLock lock_service; |
| @@ -186,6 +194,20 @@ protected: | |||
| 186 | RegisterHandlersBase(functions, n); | 194 | RegisterHandlersBase(functions, n); |
| 187 | } | 195 | } |
| 188 | 196 | ||
| 197 | /// Registers handlers in the service. | ||
| 198 | template <std::size_t N> | ||
| 199 | void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) { | ||
| 200 | RegisterHandlersTipc(functions, N); | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * Registers handlers in the service. Usually prefer using the other RegisterHandlers | ||
| 205 | * overload in order to avoid needing to specify the array size. | ||
| 206 | */ | ||
| 207 | void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) { | ||
| 208 | RegisterHandlersBaseTipc(functions, n); | ||
| 209 | } | ||
| 210 | |||
| 189 | private: | 211 | private: |
| 190 | /** | 212 | /** |
| 191 | * This function is used to allow invocation of pointers to handlers stored in the base class | 213 | * This function is used to allow invocation of pointers to handlers stored in the base class |