summaryrefslogtreecommitdiff
path: root/src/core/hle/service/service.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/service.cpp')
-rw-r--r--src/core/hle/service/service.cpp98
1 files changed, 90 insertions, 8 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 0d443aa44..d34968428 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <fmt/format.h>
5#include "common/logging/log.h" 6#include "common/logging/log.h"
6#include "common/string_util.h" 7#include "common/string_util.h"
7#include "core/hle/kernel/client_port.h" 8#include "core/hle/kernel/client_port.h"
@@ -45,9 +46,14 @@
45#include "core/hle/service/ssl_c.h" 46#include "core/hle/service/ssl_c.h"
46#include "core/hle/service/y2r_u.h" 47#include "core/hle/service/y2r_u.h"
47 48
49using Kernel::ClientPort;
50using Kernel::ServerPort;
51using Kernel::ServerSession;
52using Kernel::SharedPtr;
53
48namespace Service { 54namespace Service {
49 55
50std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_kernel_named_ports; 56std::unordered_map<std::string, SharedPtr<ClientPort>> g_kernel_named_ports;
51 57
52/** 58/**
53 * Creates a function string for logging, complete with the name (or header code, depending 59 * Creates a function string for logging, complete with the name (or header code, depending
@@ -69,7 +75,7 @@ static std::string MakeFunctionString(const char* name, const char* port_name,
69Interface::Interface(u32 max_sessions) : max_sessions(max_sessions) {} 75Interface::Interface(u32 max_sessions) : max_sessions(max_sessions) {}
70Interface::~Interface() = default; 76Interface::~Interface() = default;
71 77
72void Interface::HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) { 78void Interface::HandleSyncRequest(SharedPtr<ServerSession> server_session) {
73 // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which 79 // TODO(Subv): Make use of the server_session in the HLE service handlers to distinguish which
74 // session triggered each command. 80 // session triggered each command.
75 81
@@ -103,16 +109,91 @@ void Interface::Register(const FunctionInfo* functions, size_t n) {
103} 109}
104 110
105//////////////////////////////////////////////////////////////////////////////////////////////////// 111////////////////////////////////////////////////////////////////////////////////////////////////////
112
113ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_sessions,
114 InvokerFn* handler_invoker)
115 : service_name(service_name), max_sessions(max_sessions), handler_invoker(handler_invoker) {}
116
117ServiceFrameworkBase::~ServiceFrameworkBase() = default;
118
119void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
120 ASSERT(port == nullptr);
121 port = service_manager.RegisterService(service_name, max_sessions).Unwrap();
122 port->SetHleHandler(shared_from_this());
123}
124
125void ServiceFrameworkBase::InstallAsNamedPort() {
126 ASSERT(port == nullptr);
127 SharedPtr<ServerPort> server_port;
128 SharedPtr<ClientPort> client_port;
129 std::tie(server_port, client_port) = ServerPort::CreatePortPair(max_sessions, service_name);
130 server_port->SetHleHandler(shared_from_this());
131 AddNamedPort(service_name, std::move(client_port));
132}
133
134void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, size_t n) {
135 handlers.reserve(handlers.size() + n);
136 for (size_t i = 0; i < n; ++i) {
137 // Usually this array is sorted by id already, so hint to insert at the end
138 handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]);
139 }
140}
141
142void ServiceFrameworkBase::ReportUnimplementedFunction(u32* cmd_buf, const FunctionInfoBase* info) {
143 IPC::Header header{cmd_buf[0]};
144 int num_params = header.normal_params_size + header.translate_params_size;
145 std::string function_name = info == nullptr ? fmt::format("{:#08x}", cmd_buf[0]) : info->name;
146
147 fmt::MemoryWriter w;
148 w.write("function '{}': port='{}' cmd_buf={{[0]={:#x}", function_name, service_name,
149 cmd_buf[0]);
150 for (int i = 1; i <= num_params; ++i) {
151 w.write(", [{}]={:#x}", i, cmd_buf[i]);
152 }
153 w << '}';
154
155 LOG_ERROR(Service, "unknown / unimplemented %s", w.c_str());
156 // TODO(bunnei): Hack - ignore error
157 cmd_buf[1] = 0;
158}
159
160void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_session) {
161 u32* cmd_buf = Kernel::GetCommandBuffer();
162
163 // TODO(yuriks): The kernel should be the one handling this as part of translation after
164 // everything else is migrated
165 Kernel::HLERequestContext context;
166 context.cmd_buf = cmd_buf;
167 context.session = std::move(server_session);
168
169 u32 header_code = cmd_buf[0];
170 auto itr = handlers.find(header_code);
171 const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second;
172 if (info == nullptr || info->handler_callback == nullptr) {
173 return ReportUnimplementedFunction(cmd_buf, info);
174 }
175
176 LOG_TRACE(Service, "%s",
177 MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf).c_str());
178 handler_invoker(this, info->handler_callback, context);
179}
180
181////////////////////////////////////////////////////////////////////////////////////////////////////
106// Module interface 182// Module interface
107 183
184// TODO(yuriks): Move to kernel
185void AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
186 g_kernel_named_ports.emplace(std::move(name), std::move(port));
187}
188
108static void AddNamedPort(Interface* interface_) { 189static void AddNamedPort(Interface* interface_) {
109 Kernel::SharedPtr<Kernel::ServerPort> server_port; 190 SharedPtr<ServerPort> server_port;
110 Kernel::SharedPtr<Kernel::ClientPort> client_port; 191 SharedPtr<ClientPort> client_port;
111 std::tie(server_port, client_port) = 192 std::tie(server_port, client_port) =
112 Kernel::ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName()); 193 ServerPort::CreatePortPair(interface_->GetMaxSessions(), interface_->GetPortName());
113 194
114 server_port->SetHleHandler(std::shared_ptr<Interface>(interface_)); 195 server_port->SetHleHandler(std::shared_ptr<Interface>(interface_));
115 g_kernel_named_ports.emplace(interface_->GetPortName(), std::move(client_port)); 196 AddNamedPort(interface_->GetPortName(), std::move(client_port));
116} 197}
117 198
118void AddService(Interface* interface_) { 199void AddService(Interface* interface_) {
@@ -125,8 +206,9 @@ void AddService(Interface* interface_) {
125 206
126/// Initialize ServiceManager 207/// Initialize ServiceManager
127void Init() { 208void Init() {
128 SM::g_service_manager = std::make_unique<SM::ServiceManager>(); 209 SM::g_service_manager = std::make_shared<SM::ServiceManager>();
129 AddNamedPort(new SM::SRV); 210 SM::ServiceManager::InstallInterfaces(SM::g_service_manager);
211
130 AddNamedPort(new ERR::ERR_F); 212 AddNamedPort(new ERR::ERR_F);
131 213
132 FS::ArchiveInit(); 214 FS::ArchiveInit();