hle: service: Add support for dispatching TIPC requests.
This commit is contained in:
		| @@ -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()); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user