diff options
| author | 2015-01-30 16:07:04 -0200 | |
|---|---|---|
| committer | 2015-02-02 15:36:59 -0200 | |
| commit | 8779b31fe60c728ace89a9b5128b68feffa9c7d7 (patch) | |
| tree | b83440cbe4187f1fe120a5a247919a1ecbb1c65d /src | |
| parent | Filesys: Move creation of Handles for File/Directory to service handlers (diff) | |
| download | yuzu-8779b31fe60c728ace89a9b5128b68feffa9c7d7.tar.gz yuzu-8779b31fe60c728ace89a9b5128b68feffa9c7d7.tar.xz yuzu-8779b31fe60c728ace89a9b5128b68feffa9c7d7.zip | |
Make Port/Service registration and querying more HW-accurate
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/service.cpp | 130 | ||||
| -rw-r--r-- | src/core/hle/service/service.h | 30 | ||||
| -rw-r--r-- | src/core/hle/service/srv.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 20 |
4 files changed, 80 insertions, 106 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 355196fd3..e0979ea5d 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -54,96 +54,76 @@ | |||
| 54 | 54 | ||
| 55 | namespace Service { | 55 | namespace Service { |
| 56 | 56 | ||
| 57 | Manager* g_manager = nullptr; ///< Service manager | 57 | std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports; |
| 58 | std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; | ||
| 58 | 59 | ||
| 59 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 60 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 60 | // Service Manager class | 61 | // Module interface |
| 61 | |||
| 62 | void Manager::AddService(Interface* service) { | ||
| 63 | // TOOD(yuriks): Fix error reporting | ||
| 64 | m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE); | ||
| 65 | m_services.push_back(service); | ||
| 66 | } | ||
| 67 | |||
| 68 | void Manager::DeleteService(const std::string& port_name) { | ||
| 69 | Interface* service = FetchFromPortName(port_name); | ||
| 70 | m_services.erase(std::remove(m_services.begin(), m_services.end(), service), m_services.end()); | ||
| 71 | m_port_map.erase(port_name); | ||
| 72 | } | ||
| 73 | 62 | ||
| 74 | Interface* Manager::FetchFromHandle(Handle handle) { | 63 | static void AddNamedPort(Interface* interface) { |
| 75 | // TODO(yuriks): This function is very suspicious and should probably be exterminated. | 64 | g_kernel_named_ports.emplace(interface->GetPortName(), interface); |
| 76 | return Kernel::g_handle_table.Get<Interface>(handle).get(); | ||
| 77 | } | 65 | } |
| 78 | 66 | ||
| 79 | Interface* Manager::FetchFromPortName(const std::string& port_name) { | 67 | static void AddService(Interface* interface) { |
| 80 | auto itr = m_port_map.find(port_name); | 68 | g_srv_services.emplace(interface->GetPortName(), interface); |
| 81 | if (itr == m_port_map.end()) { | ||
| 82 | return nullptr; | ||
| 83 | } | ||
| 84 | return FetchFromHandle(itr->second); | ||
| 85 | } | 69 | } |
| 86 | 70 | ||
| 87 | |||
| 88 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 89 | // Module interface | ||
| 90 | |||
| 91 | /// Initialize ServiceManager | 71 | /// Initialize ServiceManager |
| 92 | void Init() { | 72 | void Init() { |
| 93 | g_manager = new Manager; | 73 | AddNamedPort(new SRV::Interface); |
| 94 | 74 | ||
| 95 | g_manager->AddService(new SRV::Interface); | 75 | AddService(new AC_U::Interface); |
| 96 | g_manager->AddService(new AC_U::Interface); | 76 | AddService(new ACT_U::Interface); |
| 97 | g_manager->AddService(new ACT_U::Interface); | 77 | AddService(new AM_APP::Interface); |
| 98 | g_manager->AddService(new AM_APP::Interface); | 78 | AddService(new AM_NET::Interface); |
| 99 | g_manager->AddService(new AM_NET::Interface); | 79 | AddService(new AM_SYS::Interface); |
| 100 | g_manager->AddService(new AM_SYS::Interface); | 80 | AddService(new APT_A::Interface); |
| 101 | g_manager->AddService(new APT_A::Interface); | 81 | AddService(new APT_S::Interface); |
| 102 | g_manager->AddService(new APT_S::Interface); | 82 | AddService(new APT_U::Interface); |
| 103 | g_manager->AddService(new APT_U::Interface); | 83 | AddService(new BOSS_P::Interface); |
| 104 | g_manager->AddService(new BOSS_P::Interface); | 84 | AddService(new BOSS_U::Interface); |
| 105 | g_manager->AddService(new BOSS_U::Interface); | 85 | AddService(new CAM_U::Interface); |
| 106 | g_manager->AddService(new CAM_U::Interface); | 86 | AddService(new CECD_S::Interface); |
| 107 | g_manager->AddService(new CECD_S::Interface); | 87 | AddService(new CECD_U::Interface); |
| 108 | g_manager->AddService(new CECD_U::Interface); | 88 | AddService(new CFG_I::Interface); |
| 109 | g_manager->AddService(new CFG_I::Interface); | 89 | AddService(new CFG_S::Interface); |
| 110 | g_manager->AddService(new CFG_S::Interface); | 90 | AddService(new CFG_U::Interface); |
| 111 | g_manager->AddService(new CFG_U::Interface); | 91 | AddService(new CSND_SND::Interface); |
| 112 | g_manager->AddService(new CSND_SND::Interface); | 92 | AddService(new DSP_DSP::Interface); |
| 113 | g_manager->AddService(new DSP_DSP::Interface); | 93 | AddService(new ERR_F::Interface); |
| 114 | g_manager->AddService(new ERR_F::Interface); | 94 | AddService(new FRD_A::Interface); |
| 115 | g_manager->AddService(new FRD_A::Interface); | 95 | AddService(new FRD_U::Interface); |
| 116 | g_manager->AddService(new FRD_U::Interface); | 96 | AddService(new FS::FSUserInterface); |
| 117 | g_manager->AddService(new FS::FSUserInterface); | 97 | AddService(new GSP_GPU::Interface); |
| 118 | g_manager->AddService(new GSP_GPU::Interface); | 98 | AddService(new GSP_LCD::Interface); |
| 119 | g_manager->AddService(new GSP_LCD::Interface); | 99 | AddService(new HID_User::Interface); |
| 120 | g_manager->AddService(new HID_User::Interface); | 100 | AddService(new HID_SPVR::Interface); |
| 121 | g_manager->AddService(new HID_SPVR::Interface); | 101 | AddService(new HTTP_C::Interface); |
| 122 | g_manager->AddService(new HTTP_C::Interface); | 102 | AddService(new IR_RST::Interface); |
| 123 | g_manager->AddService(new IR_RST::Interface); | 103 | AddService(new IR_U::Interface); |
| 124 | g_manager->AddService(new IR_U::Interface); | 104 | AddService(new LDR_RO::Interface); |
| 125 | g_manager->AddService(new LDR_RO::Interface); | 105 | AddService(new MIC_U::Interface); |
| 126 | g_manager->AddService(new MIC_U::Interface); | 106 | AddService(new NDM_U::Interface); |
| 127 | g_manager->AddService(new NDM_U::Interface); | 107 | AddService(new NEWS_S::Interface); |
| 128 | g_manager->AddService(new NEWS_S::Interface); | 108 | AddService(new NEWS_U::Interface); |
| 129 | g_manager->AddService(new NEWS_U::Interface); | 109 | AddService(new NIM_AOC::Interface); |
| 130 | g_manager->AddService(new NIM_AOC::Interface); | 110 | AddService(new NS_S::Interface); |
| 131 | g_manager->AddService(new NS_S::Interface); | 111 | AddService(new NWM_UDS::Interface); |
| 132 | g_manager->AddService(new NWM_UDS::Interface); | 112 | AddService(new PM_APP::Interface); |
| 133 | g_manager->AddService(new PM_APP::Interface); | 113 | AddService(new PTM_PLAY::Interface); |
| 134 | g_manager->AddService(new PTM_PLAY::Interface); | 114 | AddService(new PTM_U::Interface); |
| 135 | g_manager->AddService(new PTM_U::Interface); | 115 | AddService(new PTM_SYSM::Interface); |
| 136 | g_manager->AddService(new PTM_SYSM::Interface); | 116 | AddService(new SOC_U::Interface); |
| 137 | g_manager->AddService(new SOC_U::Interface); | 117 | AddService(new SSL_C::Interface); |
| 138 | g_manager->AddService(new SSL_C::Interface); | 118 | AddService(new Y2R_U::Interface); |
| 139 | g_manager->AddService(new Y2R_U::Interface); | ||
| 140 | 119 | ||
| 141 | LOG_DEBUG(Service, "initialized OK"); | 120 | LOG_DEBUG(Service, "initialized OK"); |
| 142 | } | 121 | } |
| 143 | 122 | ||
| 144 | /// Shutdown ServiceManager | 123 | /// Shutdown ServiceManager |
| 145 | void Shutdown() { | 124 | void Shutdown() { |
| 146 | delete g_manager; | 125 | g_srv_services.clear(); |
| 126 | g_kernel_named_ports.clear(); | ||
| 147 | LOG_DEBUG(Service, "shutdown OK"); | 127 | LOG_DEBUG(Service, "shutdown OK"); |
| 148 | } | 128 | } |
| 149 | 129 | ||
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index e75d5008b..533d3565b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -5,9 +5,10 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <algorithm> | 7 | #include <algorithm> |
| 8 | #include <vector> | ||
| 9 | #include <map> | 8 | #include <map> |
| 10 | #include <string> | 9 | #include <string> |
| 10 | #include <unordered_map> | ||
| 11 | #include <vector> | ||
| 11 | 12 | ||
| 12 | #include "common/common.h" | 13 | #include "common/common.h" |
| 13 | #include "common/string_util.h" | 14 | #include "common/string_util.h" |
| @@ -121,34 +122,15 @@ private: | |||
| 121 | 122 | ||
| 122 | }; | 123 | }; |
| 123 | 124 | ||
| 124 | /// Simple class to manage accessing services from ports and UID handles | ||
| 125 | class Manager { | ||
| 126 | public: | ||
| 127 | /// Add a service to the manager | ||
| 128 | void AddService(Interface* service); | ||
| 129 | |||
| 130 | /// Removes a service from the manager | ||
| 131 | void DeleteService(const std::string& port_name); | ||
| 132 | |||
| 133 | /// Get a Service Interface from its Handle | ||
| 134 | Interface* FetchFromHandle(Handle handle); | ||
| 135 | |||
| 136 | /// Get a Service Interface from its port | ||
| 137 | Interface* FetchFromPortName(const std::string& port_name); | ||
| 138 | |||
| 139 | private: | ||
| 140 | std::vector<Interface*> m_services; | ||
| 141 | std::map<std::string, u32> m_port_map; | ||
| 142 | }; | ||
| 143 | |||
| 144 | /// Initialize ServiceManager | 125 | /// Initialize ServiceManager |
| 145 | void Init(); | 126 | void Init(); |
| 146 | 127 | ||
| 147 | /// Shutdown ServiceManager | 128 | /// Shutdown ServiceManager |
| 148 | void Shutdown(); | 129 | void Shutdown(); |
| 149 | 130 | ||
| 150 | 131 | /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC. | |
| 151 | extern Manager* g_manager; ///< Service manager | 132 | extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports; |
| 152 | 133 | /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. | |
| 134 | extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; | ||
| 153 | 135 | ||
| 154 | } // namespace | 136 | } // namespace |
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index aa0aac3bb..c50aebf15 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) { | |||
| 35 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 35 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 36 | 36 | ||
| 37 | std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); | 37 | std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); |
| 38 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | 38 | auto it = Service::g_srv_services.find(port_name); |
| 39 | 39 | ||
| 40 | if (nullptr != service) { | 40 | if (it != Service::g_srv_services.end()) { |
| 41 | cmd_buff[3] = service->GetHandle(); | 41 | cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom(); |
| 42 | LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); | 42 | LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); |
| 43 | } else { | 43 | } else { |
| 44 | LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); | 44 | 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 88813c2ce..d253f4fe5 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -30,6 +30,11 @@ using Kernel::ERR_INVALID_HANDLE; | |||
| 30 | 30 | ||
| 31 | namespace SVC { | 31 | namespace SVC { |
| 32 | 32 | ||
| 33 | const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, | ||
| 34 | ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA | ||
| 35 | const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, | ||
| 36 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E | ||
| 37 | |||
| 33 | /// An invalid result code that is meant to be overwritten when a thread resumes from waiting | 38 | /// An invalid result code that is meant to be overwritten when a thread resumes from waiting |
| 34 | const ResultCode RESULT_INVALID(0xDEADC0DE); | 39 | const ResultCode RESULT_INVALID(0xDEADC0DE); |
| 35 | 40 | ||
| @@ -94,14 +99,21 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o | |||
| 94 | } | 99 | } |
| 95 | 100 | ||
| 96 | /// Connect to an OS service given the port name, returns the handle to the port to out | 101 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 97 | static ResultCode ConnectToPort(Handle* out, const char* port_name) { | 102 | static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) { |
| 98 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | 103 | if (port_name == nullptr) |
| 104 | return ERR_NOT_FOUND; | ||
| 105 | if (std::strlen(port_name) > 11) | ||
| 106 | return ERR_PORT_NAME_TOO_LONG; | ||
| 99 | 107 | ||
| 100 | LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); | 108 | LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); |
| 101 | _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); | ||
| 102 | 109 | ||
| 103 | *out = service->GetHandle(); | 110 | auto it = Service::g_kernel_named_ports.find(port_name); |
| 111 | if (it == Service::g_kernel_named_ports.end()) { | ||
| 112 | LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name); | ||
| 113 | return ERR_NOT_FOUND; | ||
| 114 | } | ||
| 104 | 115 | ||
| 116 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second)); | ||
| 105 | return RESULT_SUCCESS; | 117 | return RESULT_SUCCESS; |
| 106 | } | 118 | } |
| 107 | 119 | ||