service.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <algorithm>
  6. #include <vector>
  7. #include <map>
  8. #include <string>
  9. #include "common/common.h"
  10. #include "common/string_util.h"
  11. #include "core/mem_map.h"
  12. #include "core/hle/kernel/kernel.h"
  13. #include "core/hle/kernel/session.h"
  14. #include "core/hle/svc.h"
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////
  16. // Namespace Service
  17. namespace Service {
  18. static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
  19. class Manager;
  20. /// Interface to a CTROS service
  21. class Interface : public Kernel::Session {
  22. // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
  23. // just something that encapsulates a session and acts as a helper to implement service
  24. // processes.
  25. friend class Manager;
  26. /**
  27. * Creates a function string for logging, complete with the name (or header code, depending
  28. * on what's passed in) the port name, and all the cmd_buff arguments.
  29. */
  30. std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) {
  31. // Number of params == bits 0-5 + bits 6-11
  32. int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
  33. std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str());
  34. for (int i = 1; i <= num_params; ++i) {
  35. function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
  36. }
  37. return function_string;
  38. }
  39. public:
  40. std::string GetName() const override { return GetPortName(); }
  41. typedef void (*Function)(Interface*);
  42. struct FunctionInfo {
  43. u32 id;
  44. Function func;
  45. std::string name;
  46. };
  47. /**
  48. * Gets the string name used by CTROS for a service
  49. * @return Port name of service
  50. */
  51. virtual std::string GetPortName() const {
  52. return "[UNKNOWN SERVICE PORT]";
  53. }
  54. /// Allocates a new handle for the service
  55. Handle CreateHandle(Kernel::Object *obj) {
  56. // TODO(yuriks): Fix error reporting
  57. Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE);
  58. m_handles.push_back(handle);
  59. return handle;
  60. }
  61. /// Frees a handle from the service
  62. template <class T>
  63. void DeleteHandle(const Handle handle) {
  64. Kernel::g_handle_table.Close(handle);
  65. m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
  66. }
  67. ResultVal<bool> SyncRequest() override {
  68. u32* cmd_buff = Kernel::GetCommandBuffer();
  69. auto itr = m_functions.find(cmd_buff[0]);
  70. if (itr == m_functions.end() || itr->second.func == nullptr) {
  71. std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
  72. LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str());
  73. // TODO(bunnei): Hack - ignore error
  74. cmd_buff[1] = 0;
  75. return MakeResult<bool>(false);
  76. } else {
  77. LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str());
  78. }
  79. itr->second.func(this);
  80. return MakeResult<bool>(false); // TODO: Implement return from actual function
  81. }
  82. protected:
  83. /**
  84. * Registers the functions in the service
  85. */
  86. void Register(const FunctionInfo* functions, int len) {
  87. for (int i = 0; i < len; i++) {
  88. m_functions[functions[i].id] = functions[i];
  89. }
  90. }
  91. private:
  92. std::vector<Handle> m_handles;
  93. std::map<u32, FunctionInfo> m_functions;
  94. };
  95. /// Simple class to manage accessing services from ports and UID handles
  96. class Manager {
  97. public:
  98. /// Add a service to the manager
  99. void AddService(Interface* service);
  100. /// Removes a service from the manager
  101. void DeleteService(const std::string& port_name);
  102. /// Get a Service Interface from its Handle
  103. Interface* FetchFromHandle(Handle handle);
  104. /// Get a Service Interface from its port
  105. Interface* FetchFromPortName(const std::string& port_name);
  106. private:
  107. std::vector<Interface*> m_services;
  108. std::map<std::string, u32> m_port_map;
  109. };
  110. /// Initialize ServiceManager
  111. void Init();
  112. /// Shutdown ServiceManager
  113. void Shutdown();
  114. extern Manager* g_manager; ///< Service manager
  115. } // namespace