resource_manager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-3.0-or-later
  3. #include "common/logging/log.h"
  4. #include "core/core.h"
  5. #include "core/core_timing.h"
  6. #include "core/hle/kernel/k_shared_memory.h"
  7. #include "core/hle/service/ipc_helpers.h"
  8. #include "hid_core/hid_core.h"
  9. #include "hid_core/resource_manager.h"
  10. #include "hid_core/resources/applet_resource.h"
  11. #include "hid_core/resources/debug_pad/debug_pad.h"
  12. #include "hid_core/resources/digitizer/digitizer.h"
  13. #include "hid_core/resources/keyboard/keyboard.h"
  14. #include "hid_core/resources/mouse/debug_mouse.h"
  15. #include "hid_core/resources/mouse/mouse.h"
  16. #include "hid_core/resources/npad/npad.h"
  17. #include "hid_core/resources/palma/palma.h"
  18. #include "hid_core/resources/shared_memory_format.h"
  19. #include "hid_core/resources/six_axis/console_six_axis.h"
  20. #include "hid_core/resources/six_axis/seven_six_axis.h"
  21. #include "hid_core/resources/six_axis/six_axis.h"
  22. #include "hid_core/resources/system_buttons/capture_button.h"
  23. #include "hid_core/resources/system_buttons/home_button.h"
  24. #include "hid_core/resources/system_buttons/sleep_button.h"
  25. #include "hid_core/resources/touch_screen/gesture.h"
  26. #include "hid_core/resources/touch_screen/touch_screen.h"
  27. #include "hid_core/resources/unique_pad/unique_pad.h"
  28. namespace Service::HID {
  29. // Updating period for each HID device.
  30. // Period time is obtained by measuring the number of samples in a second on HW using a homebrew
  31. // Correct npad_update_ns is 4ms this is overclocked to lower input lag
  32. constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
  33. constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
  34. constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
  35. constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
  36. ResourceManager::ResourceManager(Core::System& system_)
  37. : system{system_}, service_context{system_, "hid"} {
  38. applet_resource = std::make_shared<AppletResource>(system);
  39. }
  40. ResourceManager::~ResourceManager() = default;
  41. void ResourceManager::Initialize() {
  42. if (is_initialized) {
  43. return;
  44. }
  45. system.HIDCore().ReloadInputDevices();
  46. InitializeHidCommonSampler();
  47. InitializeTouchScreenSampler();
  48. InitializeConsoleSixAxisSampler();
  49. InitializeAHidSampler();
  50. is_initialized = true;
  51. }
  52. std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const {
  53. return applet_resource;
  54. }
  55. std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const {
  56. return capture_button;
  57. }
  58. std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const {
  59. return console_six_axis;
  60. }
  61. std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const {
  62. return debug_mouse;
  63. }
  64. std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
  65. return debug_pad;
  66. }
  67. std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const {
  68. return digitizer;
  69. }
  70. std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
  71. return gesture;
  72. }
  73. std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const {
  74. return home_button;
  75. }
  76. std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const {
  77. return keyboard;
  78. }
  79. std::shared_ptr<Mouse> ResourceManager::GetMouse() const {
  80. return mouse;
  81. }
  82. std::shared_ptr<NPad> ResourceManager::GetNpad() const {
  83. return npad;
  84. }
  85. std::shared_ptr<Palma> ResourceManager::GetPalma() const {
  86. return palma;
  87. }
  88. std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const {
  89. return seven_six_axis;
  90. }
  91. std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const {
  92. return six_axis;
  93. }
  94. std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const {
  95. return sleep_button;
  96. }
  97. std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const {
  98. return touch_screen;
  99. }
  100. std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const {
  101. return unique_pad;
  102. }
  103. Result ResourceManager::CreateAppletResource(u64 aruid) {
  104. if (aruid == SystemAruid) {
  105. const auto result = RegisterCoreAppletResource();
  106. if (result.IsError()) {
  107. return result;
  108. }
  109. return GetNpad()->ActivateNpadResource();
  110. }
  111. const auto result = CreateAppletResourceImpl(aruid);
  112. if (result.IsError()) {
  113. return result;
  114. }
  115. // Homebrew doesn't try to activate some controllers, so we activate them by default
  116. npad->Activate();
  117. six_axis->Activate();
  118. touch_screen->Activate();
  119. return GetNpad()->ActivateNpadResource(aruid);
  120. }
  121. Result ResourceManager::CreateAppletResourceImpl(u64 aruid) {
  122. std::scoped_lock lock{shared_mutex};
  123. return applet_resource->CreateAppletResource(aruid);
  124. }
  125. void ResourceManager::InitializeHidCommonSampler() {
  126. debug_pad = std::make_shared<DebugPad>(system.HIDCore());
  127. mouse = std::make_shared<Mouse>(system.HIDCore());
  128. debug_mouse = std::make_shared<DebugMouse>(system.HIDCore());
  129. keyboard = std::make_shared<Keyboard>(system.HIDCore());
  130. unique_pad = std::make_shared<UniquePad>(system.HIDCore());
  131. npad = std::make_shared<NPad>(system.HIDCore(), service_context);
  132. gesture = std::make_shared<Gesture>(system.HIDCore());
  133. home_button = std::make_shared<HomeButton>(system.HIDCore());
  134. sleep_button = std::make_shared<SleepButton>(system.HIDCore());
  135. capture_button = std::make_shared<CaptureButton>(system.HIDCore());
  136. digitizer = std::make_shared<Digitizer>(system.HIDCore());
  137. palma = std::make_shared<Palma>(system.HIDCore(), service_context);
  138. six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
  139. debug_pad->SetAppletResource(applet_resource, &shared_mutex);
  140. digitizer->SetAppletResource(applet_resource, &shared_mutex);
  141. keyboard->SetAppletResource(applet_resource, &shared_mutex);
  142. npad->SetNpadExternals(applet_resource, &shared_mutex);
  143. six_axis->SetAppletResource(applet_resource, &shared_mutex);
  144. mouse->SetAppletResource(applet_resource, &shared_mutex);
  145. debug_mouse->SetAppletResource(applet_resource, &shared_mutex);
  146. home_button->SetAppletResource(applet_resource, &shared_mutex);
  147. sleep_button->SetAppletResource(applet_resource, &shared_mutex);
  148. capture_button->SetAppletResource(applet_resource, &shared_mutex);
  149. }
  150. void ResourceManager::InitializeTouchScreenSampler() {
  151. gesture = std::make_shared<Gesture>(system.HIDCore());
  152. touch_screen = std::make_shared<TouchScreen>(system.HIDCore());
  153. touch_screen->SetAppletResource(applet_resource, &shared_mutex);
  154. gesture->SetAppletResource(applet_resource, &shared_mutex);
  155. }
  156. void ResourceManager::InitializeConsoleSixAxisSampler() {
  157. console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore());
  158. seven_six_axis = std::make_shared<SevenSixAxis>(system);
  159. console_six_axis->SetAppletResource(applet_resource, &shared_mutex);
  160. }
  161. void ResourceManager::InitializeAHidSampler() {
  162. // TODO
  163. }
  164. Result ResourceManager::RegisterCoreAppletResource() {
  165. std::scoped_lock lock{shared_mutex};
  166. return applet_resource->RegisterCoreAppletResource();
  167. }
  168. Result ResourceManager::UnregisterCoreAppletResource() {
  169. std::scoped_lock lock{shared_mutex};
  170. return applet_resource->UnregisterCoreAppletResource();
  171. }
  172. Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) {
  173. std::scoped_lock lock{shared_mutex};
  174. auto result = applet_resource->RegisterAppletResourceUserId(aruid, bool_value);
  175. if (result.IsSuccess()) {
  176. result = npad->RegisterAppletResourceUserId(aruid);
  177. }
  178. return result;
  179. }
  180. void ResourceManager::UnregisterAppletResourceUserId(u64 aruid) {
  181. std::scoped_lock lock{shared_mutex};
  182. applet_resource->UnregisterAppletResourceUserId(aruid);
  183. npad->UnregisterAppletResourceUserId(aruid);
  184. }
  185. Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) {
  186. std::scoped_lock lock{shared_mutex};
  187. return applet_resource->GetSharedMemoryHandle(out_handle, aruid);
  188. }
  189. void ResourceManager::FreeAppletResourceId(u64 aruid) {
  190. std::scoped_lock lock{shared_mutex};
  191. applet_resource->FreeAppletResourceId(aruid);
  192. }
  193. void ResourceManager::EnableInput(u64 aruid, bool is_enabled) {
  194. std::scoped_lock lock{shared_mutex};
  195. applet_resource->EnableInput(aruid, is_enabled);
  196. }
  197. void ResourceManager::EnableSixAxisSensor(u64 aruid, bool is_enabled) {
  198. std::scoped_lock lock{shared_mutex};
  199. applet_resource->EnableSixAxisSensor(aruid, is_enabled);
  200. }
  201. void ResourceManager::EnablePadInput(u64 aruid, bool is_enabled) {
  202. std::scoped_lock lock{shared_mutex};
  203. applet_resource->EnablePadInput(aruid, is_enabled);
  204. }
  205. void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) {
  206. std::scoped_lock lock{shared_mutex};
  207. applet_resource->EnableTouchScreen(aruid, is_enabled);
  208. }
  209. void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) {
  210. auto& core_timing = system.CoreTiming();
  211. debug_pad->OnUpdate(core_timing);
  212. digitizer->OnUpdate(core_timing);
  213. unique_pad->OnUpdate(core_timing);
  214. gesture->OnUpdate(core_timing);
  215. touch_screen->OnUpdate(core_timing);
  216. palma->OnUpdate(core_timing);
  217. home_button->OnUpdate(core_timing);
  218. sleep_button->OnUpdate(core_timing);
  219. capture_button->OnUpdate(core_timing);
  220. }
  221. void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) {
  222. auto& core_timing = system.CoreTiming();
  223. npad->OnUpdate(core_timing);
  224. }
  225. void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) {
  226. auto& core_timing = system.CoreTiming();
  227. mouse->OnUpdate(core_timing);
  228. debug_mouse->OnUpdate(core_timing);
  229. keyboard->OnUpdate(core_timing);
  230. }
  231. void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) {
  232. auto& core_timing = system.CoreTiming();
  233. six_axis->OnUpdate(core_timing);
  234. seven_six_axis->OnUpdate(core_timing);
  235. console_six_axis->OnUpdate(core_timing);
  236. }
  237. IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource,
  238. u64 applet_resource_user_id)
  239. : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id},
  240. resource_manager{resource} {
  241. static const FunctionInfo functions[] = {
  242. {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
  243. };
  244. RegisterHandlers(functions);
  245. // Register update callbacks
  246. npad_update_event = Core::Timing::CreateEvent(
  247. "HID::UpdatePadCallback",
  248. [this, resource](
  249. s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  250. const auto guard = LockService();
  251. resource->UpdateNpad(ns_late);
  252. return std::nullopt;
  253. });
  254. default_update_event = Core::Timing::CreateEvent(
  255. "HID::UpdateDefaultCallback",
  256. [this, resource](
  257. s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  258. const auto guard = LockService();
  259. resource->UpdateControllers(ns_late);
  260. return std::nullopt;
  261. });
  262. mouse_keyboard_update_event = Core::Timing::CreateEvent(
  263. "HID::UpdateMouseKeyboardCallback",
  264. [this, resource](
  265. s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  266. const auto guard = LockService();
  267. resource->UpdateMouseKeyboard(ns_late);
  268. return std::nullopt;
  269. });
  270. motion_update_event = Core::Timing::CreateEvent(
  271. "HID::UpdateMotionCallback",
  272. [this, resource](
  273. s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  274. const auto guard = LockService();
  275. resource->UpdateMotion(ns_late);
  276. return std::nullopt;
  277. });
  278. system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
  279. system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
  280. default_update_event);
  281. system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
  282. mouse_keyboard_update_event);
  283. system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
  284. motion_update_event);
  285. }
  286. IAppletResource::~IAppletResource() {
  287. system.CoreTiming().UnscheduleEvent(npad_update_event);
  288. system.CoreTiming().UnscheduleEvent(default_update_event);
  289. system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event);
  290. system.CoreTiming().UnscheduleEvent(motion_update_event);
  291. resource_manager->FreeAppletResourceId(aruid);
  292. }
  293. void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
  294. Kernel::KSharedMemory* handle;
  295. const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid);
  296. LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw);
  297. IPC::ResponseBuilder rb{ctx, 2, 1};
  298. rb.Push(result);
  299. rb.PushCopyObjects(handle);
  300. }
  301. } // namespace Service::HID