aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner <yuriks@yuriks.net>2015-01-30 16:07:04 -0200
committerGravatar Yuri Kunde Schlesner <yuriks@yuriks.net>2015-02-02 15:36:59 -0200
commit8779b31fe60c728ace89a9b5128b68feffa9c7d7 (patch)
treeb83440cbe4187f1fe120a5a247919a1ecbb1c65d
parent5e91fc0d1aa806a9635e06e047d5367988f21093 (diff)
Make Port/Service registration and querying more HW-accurate
-rw-r--r--src/core/hle/service/service.cpp130
-rw-r--r--src/core/hle/service/service.h30
-rw-r--r--src/core/hle/service/srv.cpp6
-rw-r--r--src/core/hle/svc.cpp20
4 files changed, 80 insertions, 106 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 355196fd..e0979ea5 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -54,96 +54,76 @@
namespace Service {
-Manager* g_manager = nullptr; ///< Service manager
+std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
+std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
////////////////////////////////////////////////////////////////////////////////////////////////////
-// Service Manager class
-
-void Manager::AddService(Interface* service) {
- // TOOD(yuriks): Fix error reporting
- m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE);
- m_services.push_back(service);
-}
-
-void Manager::DeleteService(const std::string& port_name) {
- Interface* service = FetchFromPortName(port_name);
- m_services.erase(std::remove(m_services.begin(), m_services.end(), service), m_services.end());
- m_port_map.erase(port_name);
-}
+// Module interface
-Interface* Manager::FetchFromHandle(Handle handle) {
- // TODO(yuriks): This function is very suspicious and should probably be exterminated.
- return Kernel::g_handle_table.Get<Interface>(handle).get();
+static void AddNamedPort(Interface* interface) {
+ g_kernel_named_ports.emplace(interface->GetPortName(), interface);
}
-Interface* Manager::FetchFromPortName(const std::string& port_name) {
- auto itr = m_port_map.find(port_name);
- if (itr == m_port_map.end()) {
- return nullptr;
- }
- return FetchFromHandle(itr->second);
+static void AddService(Interface* interface) {
+ g_srv_services.emplace(interface->GetPortName(), interface);
}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Module interface
-
/// Initialize ServiceManager
void Init() {
- g_manager = new Manager;
-
- g_manager->AddService(new SRV::Interface);
- g_manager->AddService(new AC_U::Interface);
- g_manager->AddService(new ACT_U::Interface);
- g_manager->AddService(new AM_APP::Interface);
- g_manager->AddService(new AM_NET::Interface);
- g_manager->AddService(new AM_SYS::Interface);
- g_manager->AddService(new APT_A::Interface);
- g_manager->AddService(new APT_S::Interface);
- g_manager->AddService(new APT_U::Interface);
- g_manager->AddService(new BOSS_P::Interface);
- g_manager->AddService(new BOSS_U::Interface);
- g_manager->AddService(new CAM_U::Interface);
- g_manager->AddService(new CECD_S::Interface);
- g_manager->AddService(new CECD_U::Interface);
- g_manager->AddService(new CFG_I::Interface);
- g_manager->AddService(new CFG_S::Interface);
- g_manager->AddService(new CFG_U::Interface);
- g_manager->AddService(new CSND_SND::Interface);
- g_manager->AddService(new DSP_DSP::Interface);
- g_manager->AddService(new ERR_F::Interface);
- g_manager->AddService(new FRD_A::Interface);
- g_manager->AddService(new FRD_U::Interface);
- g_manager->AddService(new FS::FSUserInterface);
- g_manager->AddService(new GSP_GPU::Interface);
- g_manager->AddService(new GSP_LCD::Interface);
- g_manager->AddService(new HID_User::Interface);
- g_manager->AddService(new HID_SPVR::Interface);
- g_manager->AddService(new HTTP_C::Interface);
- g_manager->AddService(new IR_RST::Interface);
- g_manager->AddService(new IR_U::Interface);
- g_manager->AddService(new LDR_RO::Interface);
- g_manager->AddService(new MIC_U::Interface);
- g_manager->AddService(new NDM_U::Interface);
- g_manager->AddService(new NEWS_S::Interface);
- g_manager->AddService(new NEWS_U::Interface);
- g_manager->AddService(new NIM_AOC::Interface);
- g_manager->AddService(new NS_S::Interface);
- g_manager->AddService(new NWM_UDS::Interface);
- g_manager->AddService(new PM_APP::Interface);
- g_manager->AddService(new PTM_PLAY::Interface);
- g_manager->AddService(new PTM_U::Interface);
- g_manager->AddService(new PTM_SYSM::Interface);
- g_manager->AddService(new SOC_U::Interface);
- g_manager->AddService(new SSL_C::Interface);
- g_manager->AddService(new Y2R_U::Interface);
+ AddNamedPort(new SRV::Interface);
+
+ AddService(new AC_U::Interface);
+ AddService(new ACT_U::Interface);
+ AddService(new AM_APP::Interface);
+ AddService(new AM_NET::Interface);
+ AddService(new AM_SYS::Interface);
+ AddService(new APT_A::Interface);
+ AddService(new APT_S::Interface);
+ AddService(new APT_U::Interface);
+ AddService(new BOSS_P::Interface);
+ AddService(new BOSS_U::Interface);
+ AddService(new CAM_U::Interface);
+ AddService(new CECD_S::Interface);
+ AddService(new CECD_U::Interface);
+ AddService(new CFG_I::Interface);
+ AddService(new CFG_S::Interface);
+ AddService(new CFG_U::Interface);
+ AddService(new CSND_SND::Interface);
+ AddService(new DSP_DSP::Interface);
+ AddService(new ERR_F::Interface);
+ AddService(new FRD_A::Interface);
+ AddService(new FRD_U::Interface);
+ AddService(new FS::FSUserInterface);
+ AddService(new GSP_GPU::Interface);
+ AddService(new GSP_LCD::Interface);
+ AddService(new HID_User::Interface);
+ AddService(new HID_SPVR::Interface);
+ AddService(new HTTP_C::Interface);
+ AddService(new IR_RST::Interface);
+ AddService(new IR_U::Interface);
+ AddService(new LDR_RO::Interface);
+ AddService(new MIC_U::Interface);
+ AddService(new NDM_U::Interface);
+ AddService(new NEWS_S::Interface);
+ AddService(new NEWS_U::Interface);
+ AddService(new NIM_AOC::Interface);
+ AddService(new NS_S::Interface);
+ AddService(new NWM_UDS::Interface);
+ AddService(new PM_APP::Interface);
+ AddService(new PTM_PLAY::Interface);
+ AddService(new PTM_U::Interface);
+ AddService(new PTM_SYSM::Interface);
+ AddService(new SOC_U::Interface);
+ AddService(new SSL_C::Interface);
+ AddService(new Y2R_U::Interface);
LOG_DEBUG(Service, "initialized OK");
}
/// Shutdown ServiceManager
void Shutdown() {
- delete g_manager;
+ g_srv_services.clear();
+ g_kernel_named_ports.clear();
LOG_DEBUG(Service, "shutdown OK");
}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index e75d5008..533d3565 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -5,9 +5,10 @@
#pragma once
#include <algorithm>
-#include <vector>
#include <map>
#include <string>
+#include <unordered_map>
+#include <vector>
#include "common/common.h"
#include "common/string_util.h"
@@ -121,34 +122,15 @@ private:
};
-/// Simple class to manage accessing services from ports and UID handles
-class Manager {
-public:
- /// Add a service to the manager
- void AddService(Interface* service);
-
- /// Removes a service from the manager
- void DeleteService(const std::string& port_name);
-
- /// Get a Service Interface from its Handle
- Interface* FetchFromHandle(Handle handle);
-
- /// Get a Service Interface from its port
- Interface* FetchFromPortName(const std::string& port_name);
-
-private:
- std::vector<Interface*> m_services;
- std::map<std::string, u32> m_port_map;
-};
-
/// Initialize ServiceManager
void Init();
/// Shutdown ServiceManager
void Shutdown();
-
-extern Manager* g_manager; ///< Service manager
-
+/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
+extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports;
+/// Map of services registered with the "srv:" service, retrieved using GetServiceHandle.
+extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
} // namespace
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index aa0aac3b..c50aebf1 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -35,10 +35,10 @@ static void GetServiceHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
- Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
+ auto it = Service::g_srv_services.find(port_name);
- if (nullptr != service) {
- cmd_buff[3] = service->GetHandle();
+ if (it != Service::g_srv_services.end()) {
+ cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom();
LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]);
} else {
LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str());
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 88813c2c..d253f4fe 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -30,6 +30,11 @@ using Kernel::ERR_INVALID_HANDLE;
namespace SVC {
+const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
+ ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
+const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
+ ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E
+
/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
const ResultCode RESULT_INVALID(0xDEADC0DE);
@@ -94,14 +99,21 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
}
/// Connect to an OS service given the port name, returns the handle to the port to out
-static ResultCode ConnectToPort(Handle* out, const char* port_name) {
- Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
+static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) {
+ if (port_name == nullptr)
+ return ERR_NOT_FOUND;
+ if (std::strlen(port_name) > 11)
+ return ERR_PORT_NAME_TOO_LONG;
LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
- _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!");
- *out = service->GetHandle();
+ auto it = Service::g_kernel_named_ports.find(port_name);
+ if (it == Service::g_kernel_named_ports.end()) {
+ LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name);
+ return ERR_NOT_FOUND;
+ }
+ CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second));
return RESULT_SUCCESS;
}