resource_manager.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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 "core/hle/service/set/system_settings_server.h"
  9. #include "core/hle/service/sm/sm.h"
  10. #include "hid_core/hid_core.h"
  11. #include "hid_core/hid_util.h"
  12. #include "hid_core/resource_manager.h"
  13. #include "hid_core/resources/applet_resource.h"
  14. #include "hid_core/resources/debug_pad/debug_pad.h"
  15. #include "hid_core/resources/digitizer/digitizer.h"
  16. #include "hid_core/resources/hid_firmware_settings.h"
  17. #include "hid_core/resources/keyboard/keyboard.h"
  18. #include "hid_core/resources/mouse/debug_mouse.h"
  19. #include "hid_core/resources/mouse/mouse.h"
  20. #include "hid_core/resources/npad/npad.h"
  21. #include "hid_core/resources/palma/palma.h"
  22. #include "hid_core/resources/shared_memory_format.h"
  23. #include "hid_core/resources/six_axis/console_six_axis.h"
  24. #include "hid_core/resources/six_axis/seven_six_axis.h"
  25. #include "hid_core/resources/six_axis/six_axis.h"
  26. #include "hid_core/resources/system_buttons/capture_button.h"
  27. #include "hid_core/resources/system_buttons/home_button.h"
  28. #include "hid_core/resources/system_buttons/sleep_button.h"
  29. #include "hid_core/resources/touch_screen/gesture.h"
  30. #include "hid_core/resources/touch_screen/touch_screen.h"
  31. #include "hid_core/resources/touch_screen/touch_screen_driver.h"
  32. #include "hid_core/resources/touch_screen/touch_screen_resource.h"
  33. #include "hid_core/resources/unique_pad/unique_pad.h"
  34. #include "hid_core/resources/vibration/gc_vibration_device.h"
  35. #include "hid_core/resources/vibration/n64_vibration_device.h"
  36. #include "hid_core/resources/vibration/vibration_base.h"
  37. #include "hid_core/resources/vibration/vibration_device.h"
  38. namespace Service::HID {
  39. // Updating period for each HID device.
  40. // Period time is obtained by measuring the number of samples in a second on HW using a homebrew
  41. // Correct npad_update_ns is 4ms this is overclocked to lower input lag
  42. constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
  43. constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
  44. constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
  45. constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
  46. ResourceManager::ResourceManager(Core::System& system_,
  47. std::shared_ptr<HidFirmwareSettings> settings)
  48. : firmware_settings{settings}, system{system_}, service_context{system_, "hid"} {
  49. applet_resource = std::make_shared<AppletResource>(system);
  50. // Register update callbacks
  51. npad_update_event = Core::Timing::CreateEvent("HID::UpdatePadCallback",
  52. [this](s64 time, std::chrono::nanoseconds ns_late)
  53. -> std::optional<std::chrono::nanoseconds> {
  54. UpdateNpad(ns_late);
  55. return std::nullopt;
  56. });
  57. default_update_event = Core::Timing::CreateEvent(
  58. "HID::UpdateDefaultCallback",
  59. [this](s64 time,
  60. std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  61. UpdateControllers(ns_late);
  62. return std::nullopt;
  63. });
  64. mouse_keyboard_update_event = Core::Timing::CreateEvent(
  65. "HID::UpdateMouseKeyboardCallback",
  66. [this](s64 time,
  67. std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  68. UpdateMouseKeyboard(ns_late);
  69. return std::nullopt;
  70. });
  71. motion_update_event = Core::Timing::CreateEvent(
  72. "HID::UpdateMotionCallback",
  73. [this](s64 time,
  74. std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  75. UpdateMotion(ns_late);
  76. return std::nullopt;
  77. });
  78. }
  79. ResourceManager::~ResourceManager() {
  80. system.CoreTiming().UnscheduleEvent(npad_update_event);
  81. system.CoreTiming().UnscheduleEvent(default_update_event);
  82. system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event);
  83. system.CoreTiming().UnscheduleEvent(motion_update_event);
  84. system.CoreTiming().UnscheduleEvent(touch_update_event);
  85. input_event->Finalize();
  86. };
  87. void ResourceManager::Initialize() {
  88. if (is_initialized) {
  89. return;
  90. }
  91. system.HIDCore().ReloadInputDevices();
  92. input_event = service_context.CreateEvent("ResourceManager:InputEvent");
  93. InitializeHandheldConfig();
  94. InitializeHidCommonSampler();
  95. InitializeTouchScreenSampler();
  96. InitializeConsoleSixAxisSampler();
  97. InitializeAHidSampler();
  98. is_initialized = true;
  99. }
  100. std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const {
  101. return applet_resource;
  102. }
  103. std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const {
  104. return capture_button;
  105. }
  106. std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const {
  107. return console_six_axis;
  108. }
  109. std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const {
  110. return debug_mouse;
  111. }
  112. std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
  113. return debug_pad;
  114. }
  115. std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const {
  116. return digitizer;
  117. }
  118. std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
  119. return gesture;
  120. }
  121. std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const {
  122. return home_button;
  123. }
  124. std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const {
  125. return keyboard;
  126. }
  127. std::shared_ptr<Mouse> ResourceManager::GetMouse() const {
  128. return mouse;
  129. }
  130. std::shared_ptr<NPad> ResourceManager::GetNpad() const {
  131. return npad;
  132. }
  133. std::shared_ptr<Palma> ResourceManager::GetPalma() const {
  134. return palma;
  135. }
  136. std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const {
  137. return seven_six_axis;
  138. }
  139. std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const {
  140. return six_axis;
  141. }
  142. std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const {
  143. return sleep_button;
  144. }
  145. std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const {
  146. return touch_screen;
  147. }
  148. std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const {
  149. return unique_pad;
  150. }
  151. Result ResourceManager::CreateAppletResource(u64 aruid) {
  152. if (aruid == SystemAruid) {
  153. const auto result = RegisterCoreAppletResource();
  154. if (result.IsError()) {
  155. return result;
  156. }
  157. return GetNpad()->ActivateNpadResource();
  158. }
  159. const auto result = CreateAppletResourceImpl(aruid);
  160. if (result.IsError()) {
  161. return result;
  162. }
  163. // Homebrew doesn't try to activate some controllers, so we activate them by default
  164. npad->Activate();
  165. six_axis->Activate();
  166. touch_screen->Activate();
  167. gesture->Activate();
  168. return GetNpad()->ActivateNpadResource(aruid);
  169. }
  170. Result ResourceManager::CreateAppletResourceImpl(u64 aruid) {
  171. std::scoped_lock lock{shared_mutex};
  172. return applet_resource->CreateAppletResource(aruid);
  173. }
  174. void ResourceManager::InitializeHandheldConfig() {
  175. handheld_config = std::make_shared<HandheldConfig>();
  176. handheld_config->is_handheld_hid_enabled = true;
  177. handheld_config->is_joycon_rail_enabled = true;
  178. handheld_config->is_force_handheld_style_vibration = false;
  179. handheld_config->is_force_handheld = false;
  180. if (firmware_settings->IsHandheldForced()) {
  181. handheld_config->is_joycon_rail_enabled = false;
  182. }
  183. }
  184. void ResourceManager::InitializeHidCommonSampler() {
  185. debug_pad = std::make_shared<DebugPad>(system.HIDCore());
  186. mouse = std::make_shared<Mouse>(system.HIDCore());
  187. debug_mouse = std::make_shared<DebugMouse>(system.HIDCore());
  188. keyboard = std::make_shared<Keyboard>(system.HIDCore());
  189. unique_pad = std::make_shared<UniquePad>(system.HIDCore());
  190. npad = std::make_shared<NPad>(system.HIDCore(), service_context);
  191. home_button = std::make_shared<HomeButton>(system.HIDCore());
  192. sleep_button = std::make_shared<SleepButton>(system.HIDCore());
  193. capture_button = std::make_shared<CaptureButton>(system.HIDCore());
  194. digitizer = std::make_shared<Digitizer>(system.HIDCore());
  195. palma = std::make_shared<Palma>(system.HIDCore(), service_context);
  196. six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
  197. debug_pad->SetAppletResource(applet_resource, &shared_mutex);
  198. digitizer->SetAppletResource(applet_resource, &shared_mutex);
  199. unique_pad->SetAppletResource(applet_resource, &shared_mutex);
  200. keyboard->SetAppletResource(applet_resource, &shared_mutex);
  201. const auto settings =
  202. system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
  203. npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config, input_event,
  204. &input_mutex, settings);
  205. six_axis->SetAppletResource(applet_resource, &shared_mutex);
  206. mouse->SetAppletResource(applet_resource, &shared_mutex);
  207. debug_mouse->SetAppletResource(applet_resource, &shared_mutex);
  208. home_button->SetAppletResource(applet_resource, &shared_mutex);
  209. sleep_button->SetAppletResource(applet_resource, &shared_mutex);
  210. capture_button->SetAppletResource(applet_resource, &shared_mutex);
  211. system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
  212. system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
  213. default_update_event);
  214. system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
  215. mouse_keyboard_update_event);
  216. system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
  217. motion_update_event);
  218. }
  219. void ResourceManager::InitializeTouchScreenSampler() {
  220. // This is nn.hid.TouchScreenSampler
  221. touch_resource = std::make_shared<TouchResource>(system);
  222. touch_driver = std::make_shared<TouchDriver>(system.HIDCore());
  223. touch_screen = std::make_shared<TouchScreen>(touch_resource);
  224. gesture = std::make_shared<Gesture>(touch_resource);
  225. touch_update_event = Core::Timing::CreateEvent(
  226. "HID::TouchUpdateCallback",
  227. [this](s64 time,
  228. std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
  229. touch_resource->OnTouchUpdate(time);
  230. return std::nullopt;
  231. });
  232. touch_resource->SetTouchDriver(touch_driver);
  233. touch_resource->SetAppletResource(applet_resource, &shared_mutex);
  234. touch_resource->SetInputEvent(input_event, &input_mutex);
  235. touch_resource->SetHandheldConfig(handheld_config);
  236. touch_resource->SetTimerEvent(touch_update_event);
  237. }
  238. void ResourceManager::InitializeConsoleSixAxisSampler() {
  239. console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore());
  240. seven_six_axis = std::make_shared<SevenSixAxis>(system);
  241. console_six_axis->SetAppletResource(applet_resource, &shared_mutex);
  242. }
  243. void ResourceManager::InitializeAHidSampler() {
  244. // TODO
  245. }
  246. Result ResourceManager::RegisterCoreAppletResource() {
  247. std::scoped_lock lock{shared_mutex};
  248. return applet_resource->RegisterCoreAppletResource();
  249. }
  250. Result ResourceManager::UnregisterCoreAppletResource() {
  251. std::scoped_lock lock{shared_mutex};
  252. return applet_resource->UnregisterCoreAppletResource();
  253. }
  254. Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) {
  255. std::scoped_lock lock{shared_mutex};
  256. auto result = applet_resource->RegisterAppletResourceUserId(aruid, bool_value);
  257. if (result.IsSuccess()) {
  258. result = npad->RegisterAppletResourceUserId(aruid);
  259. }
  260. return result;
  261. }
  262. void ResourceManager::UnregisterAppletResourceUserId(u64 aruid) {
  263. std::scoped_lock lock{shared_mutex};
  264. applet_resource->UnregisterAppletResourceUserId(aruid);
  265. npad->UnregisterAppletResourceUserId(aruid);
  266. // palma->UnregisterAppletResourceUserId(aruid);
  267. }
  268. Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) {
  269. std::scoped_lock lock{shared_mutex};
  270. return applet_resource->GetSharedMemoryHandle(out_handle, aruid);
  271. }
  272. void ResourceManager::FreeAppletResourceId(u64 aruid) {
  273. std::scoped_lock lock{shared_mutex};
  274. applet_resource->FreeAppletResourceId(aruid);
  275. npad->FreeAppletResourceId(aruid);
  276. }
  277. void ResourceManager::EnableInput(u64 aruid, bool is_enabled) {
  278. std::scoped_lock lock{shared_mutex};
  279. applet_resource->EnableInput(aruid, is_enabled);
  280. }
  281. void ResourceManager::EnableSixAxisSensor(u64 aruid, bool is_enabled) {
  282. std::scoped_lock lock{shared_mutex};
  283. applet_resource->EnableSixAxisSensor(aruid, is_enabled);
  284. }
  285. void ResourceManager::EnablePadInput(u64 aruid, bool is_enabled) {
  286. std::scoped_lock lock{shared_mutex};
  287. applet_resource->EnablePadInput(aruid, is_enabled);
  288. }
  289. void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) {
  290. std::scoped_lock lock{shared_mutex};
  291. applet_resource->EnableTouchScreen(aruid, is_enabled);
  292. }
  293. NpadVibrationBase* ResourceManager::GetVibrationDevice(
  294. const Core::HID::VibrationDeviceHandle& handle) {
  295. return npad->GetVibrationDevice(handle);
  296. }
  297. NpadN64VibrationDevice* ResourceManager::GetN64VibrationDevice(
  298. const Core::HID::VibrationDeviceHandle& handle) {
  299. return npad->GetN64VibrationDevice(handle);
  300. }
  301. NpadVibrationDevice* ResourceManager::GetNSVibrationDevice(
  302. const Core::HID::VibrationDeviceHandle& handle) {
  303. return npad->GetNSVibrationDevice(handle);
  304. }
  305. NpadGcVibrationDevice* ResourceManager::GetGcVibrationDevice(
  306. const Core::HID::VibrationDeviceHandle& handle) {
  307. return npad->GetGcVibrationDevice(handle);
  308. }
  309. Result ResourceManager::SetAruidValidForVibration(u64 aruid, bool is_enabled) {
  310. std::scoped_lock lock{shared_mutex};
  311. const bool has_changed = applet_resource->SetAruidValidForVibration(aruid, is_enabled);
  312. if (has_changed) {
  313. auto devices = npad->GetAllVibrationDevices();
  314. for ([[maybe_unused]] auto* device : devices) {
  315. // TODO
  316. }
  317. }
  318. auto* vibration_handler = npad->GetVibrationHandler();
  319. if (aruid != vibration_handler->GetSessionAruid()) {
  320. vibration_handler->EndPermitVibrationSession();
  321. }
  322. return ResultSuccess;
  323. }
  324. void ResourceManager::SetForceHandheldStyleVibration(bool is_forced) {
  325. handheld_config->is_force_handheld_style_vibration = is_forced;
  326. }
  327. Result ResourceManager::IsVibrationAruidActive(u64 aruid, bool& is_active) const {
  328. std::scoped_lock lock{shared_mutex};
  329. is_active = applet_resource->IsVibrationAruidActive(aruid);
  330. return ResultSuccess;
  331. }
  332. Result ResourceManager::GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info,
  333. const Core::HID::VibrationDeviceHandle& handle) {
  334. bool check_device_index = false;
  335. const Result is_valid = IsVibrationHandleValid(handle);
  336. if (is_valid.IsError()) {
  337. return is_valid;
  338. }
  339. switch (handle.npad_type) {
  340. case Core::HID::NpadStyleIndex::Fullkey:
  341. case Core::HID::NpadStyleIndex::Handheld:
  342. case Core::HID::NpadStyleIndex::JoyconDual:
  343. case Core::HID::NpadStyleIndex::JoyconLeft:
  344. case Core::HID::NpadStyleIndex::JoyconRight:
  345. device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
  346. check_device_index = true;
  347. break;
  348. case Core::HID::NpadStyleIndex::GameCube:
  349. device_info.type = Core::HID::VibrationDeviceType::GcErm;
  350. break;
  351. case Core::HID::NpadStyleIndex::N64:
  352. device_info.type = Core::HID::VibrationDeviceType::N64;
  353. break;
  354. default:
  355. device_info.type = Core::HID::VibrationDeviceType::Unknown;
  356. break;
  357. }
  358. device_info.position = Core::HID::VibrationDevicePosition::None;
  359. if (check_device_index) {
  360. switch (handle.device_index) {
  361. case Core::HID::DeviceIndex::Left:
  362. device_info.position = Core::HID::VibrationDevicePosition::Left;
  363. break;
  364. case Core::HID::DeviceIndex::Right:
  365. device_info.position = Core::HID::VibrationDevicePosition::Right;
  366. break;
  367. case Core::HID::DeviceIndex::None:
  368. default:
  369. ASSERT_MSG(false, "DeviceIndex should never be None!");
  370. break;
  371. }
  372. }
  373. return ResultSuccess;
  374. }
  375. Result ResourceManager::SendVibrationValue(u64 aruid,
  376. const Core::HID::VibrationDeviceHandle& handle,
  377. const Core::HID::VibrationValue& value) {
  378. bool has_active_aruid{};
  379. NpadVibrationDevice* device{nullptr};
  380. Result result = IsVibrationAruidActive(aruid, has_active_aruid);
  381. if (result.IsSuccess() && has_active_aruid) {
  382. result = IsVibrationHandleValid(handle);
  383. }
  384. if (result.IsSuccess() && has_active_aruid) {
  385. device = GetNSVibrationDevice(handle);
  386. }
  387. if (device != nullptr) {
  388. // Prevent sending vibrations to an inactive vibration handle
  389. if (!device->IsActive()) {
  390. return ResultSuccess;
  391. }
  392. result = device->SendVibrationValue(value);
  393. }
  394. return result;
  395. }
  396. Result ResourceManager::GetTouchScreenFirmwareVersion(Core::HID::FirmwareVersion& firmware) const {
  397. return ResultSuccess;
  398. }
  399. void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) {
  400. auto& core_timing = system.CoreTiming();
  401. debug_pad->OnUpdate(core_timing);
  402. digitizer->OnUpdate(core_timing);
  403. unique_pad->OnUpdate(core_timing);
  404. palma->OnUpdate(core_timing);
  405. home_button->OnUpdate(core_timing);
  406. sleep_button->OnUpdate(core_timing);
  407. capture_button->OnUpdate(core_timing);
  408. }
  409. void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) {
  410. auto& core_timing = system.CoreTiming();
  411. npad->OnUpdate(core_timing);
  412. }
  413. void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) {
  414. auto& core_timing = system.CoreTiming();
  415. mouse->OnUpdate(core_timing);
  416. debug_mouse->OnUpdate(core_timing);
  417. keyboard->OnUpdate(core_timing);
  418. }
  419. void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) {
  420. auto& core_timing = system.CoreTiming();
  421. six_axis->OnUpdate(core_timing);
  422. seven_six_axis->OnUpdate(core_timing);
  423. console_six_axis->OnUpdate(core_timing);
  424. }
  425. IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource,
  426. u64 applet_resource_user_id)
  427. : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id},
  428. resource_manager{resource} {
  429. static const FunctionInfo functions[] = {
  430. {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
  431. };
  432. RegisterHandlers(functions);
  433. }
  434. IAppletResource::~IAppletResource() {
  435. resource_manager->FreeAppletResourceId(aruid);
  436. }
  437. void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
  438. Kernel::KSharedMemory* handle;
  439. const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid);
  440. LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw);
  441. IPC::ResponseBuilder rb{ctx, 2, 1};
  442. rb.Push(result);
  443. rb.PushCopyObjects(handle);
  444. }
  445. } // namespace Service::HID