diff options
| author | 2024-01-04 20:37:43 -0600 | |
|---|---|---|
| committer | 2024-01-05 11:41:15 -0600 | |
| commit | ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613 (patch) | |
| tree | 3b95cbb74be05f0ce7a007353f1f9f95e1ed3901 /src/core | |
| parent | Merge pull request #12437 from ameerj/gl-amd-fixes (diff) | |
| download | yuzu-ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613.tar.gz yuzu-ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613.tar.xz yuzu-ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613.zip | |
hid_core: Move hid to it's own subproject
Diffstat (limited to 'src/core')
115 files changed, 67 insertions, 16174 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e2ec2164c..adcc23c18 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -183,22 +183,6 @@ add_library(core STATIC | |||
| 183 | frontend/framebuffer_layout.cpp | 183 | frontend/framebuffer_layout.cpp |
| 184 | frontend/framebuffer_layout.h | 184 | frontend/framebuffer_layout.h |
| 185 | frontend/graphics_context.h | 185 | frontend/graphics_context.h |
| 186 | hid/emulated_console.cpp | ||
| 187 | hid/emulated_console.h | ||
| 188 | hid/emulated_controller.cpp | ||
| 189 | hid/emulated_controller.h | ||
| 190 | hid/emulated_devices.cpp | ||
| 191 | hid/emulated_devices.h | ||
| 192 | hid/hid_core.cpp | ||
| 193 | hid/hid_core.h | ||
| 194 | hid/hid_types.h | ||
| 195 | hid/input_converter.cpp | ||
| 196 | hid/input_converter.h | ||
| 197 | hid/input_interpreter.cpp | ||
| 198 | hid/input_interpreter.h | ||
| 199 | hid/irs_types.h | ||
| 200 | hid/motion_input.cpp | ||
| 201 | hid/motion_input.h | ||
| 202 | hle/api_version.h | 186 | hle/api_version.h |
| 203 | hle/ipc.h | 187 | hle/ipc.h |
| 204 | hle/kernel/board/nintendo/nx/k_memory_layout.cpp | 188 | hle/kernel/board/nintendo/nx/k_memory_layout.cpp |
| @@ -531,94 +515,16 @@ add_library(core STATIC | |||
| 531 | hle/service/hid/hid.h | 515 | hle/service/hid/hid.h |
| 532 | hle/service/hid/hid_debug_server.cpp | 516 | hle/service/hid/hid_debug_server.cpp |
| 533 | hle/service/hid/hid_debug_server.h | 517 | hle/service/hid/hid_debug_server.h |
| 534 | hle/service/hid/hid_firmware_settings.cpp | ||
| 535 | hle/service/hid/hid_firmware_settings.h | ||
| 536 | hle/service/hid/hid_server.cpp | 518 | hle/service/hid/hid_server.cpp |
| 537 | hle/service/hid/hid_server.h | 519 | hle/service/hid/hid_server.h |
| 538 | hle/service/hid/hid_system_server.cpp | 520 | hle/service/hid/hid_system_server.cpp |
| 539 | hle/service/hid/hid_system_server.h | 521 | hle/service/hid/hid_system_server.h |
| 540 | hle/service/hid/hid_util.h | ||
| 541 | hle/service/hid/hidbus.cpp | 522 | hle/service/hid/hidbus.cpp |
| 542 | hle/service/hid/hidbus.h | 523 | hle/service/hid/hidbus.h |
| 543 | hle/service/hid/irs.cpp | 524 | hle/service/hid/irs.cpp |
| 544 | hle/service/hid/irs.h | 525 | hle/service/hid/irs.h |
| 545 | hle/service/hid/irs_ring_lifo.h | ||
| 546 | hle/service/hid/resource_manager.cpp | ||
| 547 | hle/service/hid/resource_manager.h | ||
| 548 | hle/service/hid/ring_lifo.h | ||
| 549 | hle/service/hid/xcd.cpp | 526 | hle/service/hid/xcd.cpp |
| 550 | hle/service/hid/xcd.h | 527 | hle/service/hid/xcd.h |
| 551 | hle/service/hid/errors.h | ||
| 552 | hle/service/hid/controllers/npad/npad_data.cpp | ||
| 553 | hle/service/hid/controllers/npad/npad_data.h | ||
| 554 | hle/service/hid/controllers/npad/npad_resource.cpp | ||
| 555 | hle/service/hid/controllers/npad/npad_resource.h | ||
| 556 | hle/service/hid/controllers/types/debug_pad_types.h | ||
| 557 | hle/service/hid/controllers/types/keyboard_types.h | ||
| 558 | hle/service/hid/controllers/types/mouse_types.h | ||
| 559 | hle/service/hid/controllers/types/npad_types.h | ||
| 560 | hle/service/hid/controllers/types/shared_memory_format.h | ||
| 561 | hle/service/hid/controllers/types/touch_types.h | ||
| 562 | hle/service/hid/controllers/applet_resource.cpp | ||
| 563 | hle/service/hid/controllers/applet_resource.h | ||
| 564 | hle/service/hid/controllers/capture_button.cpp | ||
| 565 | hle/service/hid/controllers/capture_button.h | ||
| 566 | hle/service/hid/controllers/console_six_axis.cpp | ||
| 567 | hle/service/hid/controllers/console_six_axis.h | ||
| 568 | hle/service/hid/controllers/controller_base.cpp | ||
| 569 | hle/service/hid/controllers/controller_base.h | ||
| 570 | hle/service/hid/controllers/debug_mouse.cpp | ||
| 571 | hle/service/hid/controllers/debug_mouse.h | ||
| 572 | hle/service/hid/controllers/debug_pad.cpp | ||
| 573 | hle/service/hid/controllers/debug_pad.h | ||
| 574 | hle/service/hid/controllers/digitizer.cpp | ||
| 575 | hle/service/hid/controllers/digitizer.h | ||
| 576 | hle/service/hid/controllers/gesture.cpp | ||
| 577 | hle/service/hid/controllers/gesture.h | ||
| 578 | hle/service/hid/controllers/home_button.cpp | ||
| 579 | hle/service/hid/controllers/home_button.h | ||
| 580 | hle/service/hid/controllers/keyboard.cpp | ||
| 581 | hle/service/hid/controllers/keyboard.h | ||
| 582 | hle/service/hid/controllers/mouse.cpp | ||
| 583 | hle/service/hid/controllers/mouse.h | ||
| 584 | hle/service/hid/controllers/npad.cpp | ||
| 585 | hle/service/hid/controllers/npad.h | ||
| 586 | hle/service/hid/controllers/palma.cpp | ||
| 587 | hle/service/hid/controllers/palma.h | ||
| 588 | hle/service/hid/controllers/seven_six_axis.cpp | ||
| 589 | hle/service/hid/controllers/seven_six_axis.h | ||
| 590 | hle/service/hid/controllers/shared_memory_holder.cpp | ||
| 591 | hle/service/hid/controllers/shared_memory_holder.h | ||
| 592 | hle/service/hid/controllers/six_axis.cpp | ||
| 593 | hle/service/hid/controllers/six_axis.h | ||
| 594 | hle/service/hid/controllers/sleep_button.cpp | ||
| 595 | hle/service/hid/controllers/sleep_button.h | ||
| 596 | hle/service/hid/controllers/touchscreen.cpp | ||
| 597 | hle/service/hid/controllers/touchscreen.h | ||
| 598 | hle/service/hid/controllers/unique_pad.cpp | ||
| 599 | hle/service/hid/controllers/unique_pad.h | ||
| 600 | hle/service/hid/hidbus/hidbus_base.cpp | ||
| 601 | hle/service/hid/hidbus/hidbus_base.h | ||
| 602 | hle/service/hid/hidbus/ringcon.cpp | ||
| 603 | hle/service/hid/hidbus/ringcon.h | ||
| 604 | hle/service/hid/hidbus/starlink.cpp | ||
| 605 | hle/service/hid/hidbus/starlink.h | ||
| 606 | hle/service/hid/hidbus/stubbed.cpp | ||
| 607 | hle/service/hid/hidbus/stubbed.h | ||
| 608 | hle/service/hid/irsensor/clustering_processor.cpp | ||
| 609 | hle/service/hid/irsensor/clustering_processor.h | ||
| 610 | hle/service/hid/irsensor/image_transfer_processor.cpp | ||
| 611 | hle/service/hid/irsensor/image_transfer_processor.h | ||
| 612 | hle/service/hid/irsensor/ir_led_processor.cpp | ||
| 613 | hle/service/hid/irsensor/ir_led_processor.h | ||
| 614 | hle/service/hid/irsensor/moment_processor.cpp | ||
| 615 | hle/service/hid/irsensor/moment_processor.h | ||
| 616 | hle/service/hid/irsensor/pointing_processor.cpp | ||
| 617 | hle/service/hid/irsensor/pointing_processor.h | ||
| 618 | hle/service/hid/irsensor/processor_base.cpp | ||
| 619 | hle/service/hid/irsensor/processor_base.h | ||
| 620 | hle/service/hid/irsensor/tera_plugin_processor.cpp | ||
| 621 | hle/service/hid/irsensor/tera_plugin_processor.h | ||
| 622 | hle/service/lbl/lbl.cpp | 528 | hle/service/lbl/lbl.cpp |
| 623 | hle/service/lbl/lbl.h | 529 | hle/service/lbl/lbl.h |
| 624 | hle/service/ldn/lan_discovery.cpp | 530 | hle/service/ldn/lan_discovery.cpp |
| @@ -959,7 +865,7 @@ endif() | |||
| 959 | 865 | ||
| 960 | create_target_directory_groups(core) | 866 | create_target_directory_groups(core) |
| 961 | 867 | ||
| 962 | target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core nx_tzdb) | 868 | target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb) |
| 963 | target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) | 869 | target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) |
| 964 | if (MINGW) | 870 | if (MINGW) |
| 965 | target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) | 871 | target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 66f444d39..c063f7719 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include "core/file_sys/savedata_factory.h" | 28 | #include "core/file_sys/savedata_factory.h" |
| 29 | #include "core/file_sys/vfs_concat.h" | 29 | #include "core/file_sys/vfs_concat.h" |
| 30 | #include "core/file_sys/vfs_real.h" | 30 | #include "core/file_sys/vfs_real.h" |
| 31 | #include "core/hid/hid_core.h" | ||
| 32 | #include "core/hle/kernel/k_memory_manager.h" | 31 | #include "core/hle/kernel/k_memory_manager.h" |
| 33 | #include "core/hle/kernel/k_process.h" | 32 | #include "core/hle/kernel/k_process.h" |
| 34 | #include "core/hle/kernel/k_resource_limit.h" | 33 | #include "core/hle/kernel/k_resource_limit.h" |
| @@ -52,6 +51,7 @@ | |||
| 52 | #include "core/telemetry_session.h" | 51 | #include "core/telemetry_session.h" |
| 53 | #include "core/tools/freezer.h" | 52 | #include "core/tools/freezer.h" |
| 54 | #include "core/tools/renderdoc.h" | 53 | #include "core/tools/renderdoc.h" |
| 54 | #include "hid_core/hid_core.h" | ||
| 55 | #include "network/network.h" | 55 | #include "network/network.h" |
| 56 | #include "video_core/host1x/host1x.h" | 56 | #include "video_core/host1x/host1x.h" |
| 57 | #include "video_core/renderer_base.h" | 57 | #include "video_core/renderer_base.h" |
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 27755cb58..34fe23b6a 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | #include "common/settings.h" | 6 | #include "common/settings.h" |
| 7 | #include "common/settings_enums.h" | 7 | #include "common/settings_enums.h" |
| 8 | #include "core/frontend/applets/controller.h" | 8 | #include "core/frontend/applets/controller.h" |
| 9 | #include "core/hid/emulated_controller.h" | 9 | #include "hid_core/frontend/emulated_controller.h" |
| 10 | #include "core/hid/hid_core.h" | 10 | #include "hid_core/hid_core.h" |
| 11 | #include "core/hid/hid_types.h" | 11 | #include "hid_core/hid_types.h" |
| 12 | 12 | ||
| 13 | namespace Core::Frontend { | 13 | namespace Core::Frontend { |
| 14 | 14 | ||
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp deleted file mode 100644 index b4afd930e..000000000 --- a/src/core/hid/emulated_console.cpp +++ /dev/null | |||
| @@ -1,324 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/hid/emulated_console.h" | ||
| 6 | #include "core/hid/input_converter.h" | ||
| 7 | |||
| 8 | namespace Core::HID { | ||
| 9 | EmulatedConsole::EmulatedConsole() = default; | ||
| 10 | |||
| 11 | EmulatedConsole::~EmulatedConsole() = default; | ||
| 12 | |||
| 13 | void EmulatedConsole::ReloadFromSettings() { | ||
| 14 | // Using first motion device from player 1. No need to assign any unique config at the moment | ||
| 15 | const auto& player = Settings::values.players.GetValue()[0]; | ||
| 16 | motion_params[0] = Common::ParamPackage(player.motions[0]); | ||
| 17 | |||
| 18 | ReloadInput(); | ||
| 19 | } | ||
| 20 | |||
| 21 | void EmulatedConsole::SetTouchParams() { | ||
| 22 | std::size_t index = 0; | ||
| 23 | |||
| 24 | // We can't use mouse as touch if native mouse is enabled | ||
| 25 | if (!Settings::values.mouse_enabled) { | ||
| 26 | touch_params[index++] = | ||
| 27 | Common::ParamPackage{"engine:mouse,axis_x:0,axis_y:1,button:0,port:2"}; | ||
| 28 | } | ||
| 29 | |||
| 30 | touch_params[index++] = | ||
| 31 | Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"}; | ||
| 32 | touch_params[index++] = | ||
| 33 | Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"}; | ||
| 34 | |||
| 35 | for (int i = 0; i < static_cast<int>(MaxActiveTouchInputs); i++) { | ||
| 36 | Common::ParamPackage touchscreen_param{}; | ||
| 37 | touchscreen_param.Set("engine", "touch"); | ||
| 38 | touchscreen_param.Set("axis_x", i * 2); | ||
| 39 | touchscreen_param.Set("axis_y", (i * 2) + 1); | ||
| 40 | touchscreen_param.Set("button", i); | ||
| 41 | touch_params[index++] = std::move(touchscreen_param); | ||
| 42 | } | ||
| 43 | |||
| 44 | if (Settings::values.touch_from_button_maps.empty()) { | ||
| 45 | LOG_WARNING(Input, "touch_from_button_maps is unset by frontend config"); | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | const auto button_index = | ||
| 50 | static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); | ||
| 51 | const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons; | ||
| 52 | |||
| 53 | // Map the rest of the fingers from touch from button configuration | ||
| 54 | for (const auto& config_entry : touch_buttons) { | ||
| 55 | if (index >= MaxTouchDevices) { | ||
| 56 | continue; | ||
| 57 | } | ||
| 58 | Common::ParamPackage params{config_entry}; | ||
| 59 | Common::ParamPackage touch_button_params; | ||
| 60 | const int x = params.Get("x", 0); | ||
| 61 | const int y = params.Get("y", 0); | ||
| 62 | params.Erase("x"); | ||
| 63 | params.Erase("y"); | ||
| 64 | touch_button_params.Set("engine", "touch_from_button"); | ||
| 65 | touch_button_params.Set("button", params.Serialize()); | ||
| 66 | touch_button_params.Set("x", x); | ||
| 67 | touch_button_params.Set("y", y); | ||
| 68 | touch_params[index] = std::move(touch_button_params); | ||
| 69 | index++; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | void EmulatedConsole::ReloadInput() { | ||
| 74 | // If you load any device here add the equivalent to the UnloadInput() function | ||
| 75 | SetTouchParams(); | ||
| 76 | |||
| 77 | motion_params[1] = Common::ParamPackage{"engine:virtual_gamepad,port:8,motion:0"}; | ||
| 78 | |||
| 79 | for (std::size_t index = 0; index < motion_devices.size(); ++index) { | ||
| 80 | motion_devices[index] = Common::Input::CreateInputDevice(motion_params[index]); | ||
| 81 | if (!motion_devices[index]) { | ||
| 82 | continue; | ||
| 83 | } | ||
| 84 | motion_devices[index]->SetCallback({ | ||
| 85 | .on_change = | ||
| 86 | [this](const Common::Input::CallbackStatus& callback) { SetMotion(callback); }, | ||
| 87 | }); | ||
| 88 | } | ||
| 89 | |||
| 90 | // Restore motion state | ||
| 91 | auto& emulated_motion = console.motion_values.emulated; | ||
| 92 | auto& motion = console.motion_state; | ||
| 93 | emulated_motion.ResetRotations(); | ||
| 94 | emulated_motion.ResetQuaternion(); | ||
| 95 | motion.accel = emulated_motion.GetAcceleration(); | ||
| 96 | motion.gyro = emulated_motion.GetGyroscope(); | ||
| 97 | motion.rotation = emulated_motion.GetRotations(); | ||
| 98 | motion.orientation = emulated_motion.GetOrientation(); | ||
| 99 | motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); | ||
| 100 | |||
| 101 | // Unique index for identifying touch device source | ||
| 102 | std::size_t index = 0; | ||
| 103 | for (auto& touch_device : touch_devices) { | ||
| 104 | touch_device = Common::Input::CreateInputDevice(touch_params[index]); | ||
| 105 | if (!touch_device) { | ||
| 106 | continue; | ||
| 107 | } | ||
| 108 | touch_device->SetCallback({ | ||
| 109 | .on_change = | ||
| 110 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 111 | SetTouch(callback, index); | ||
| 112 | }, | ||
| 113 | }); | ||
| 114 | index++; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | void EmulatedConsole::UnloadInput() { | ||
| 119 | for (auto& motion : motion_devices) { | ||
| 120 | motion.reset(); | ||
| 121 | } | ||
| 122 | for (auto& touch : touch_devices) { | ||
| 123 | touch.reset(); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | void EmulatedConsole::EnableConfiguration() { | ||
| 128 | is_configuring = true; | ||
| 129 | SaveCurrentConfig(); | ||
| 130 | } | ||
| 131 | |||
| 132 | void EmulatedConsole::DisableConfiguration() { | ||
| 133 | is_configuring = false; | ||
| 134 | } | ||
| 135 | |||
| 136 | bool EmulatedConsole::IsConfiguring() const { | ||
| 137 | return is_configuring; | ||
| 138 | } | ||
| 139 | |||
| 140 | void EmulatedConsole::SaveCurrentConfig() { | ||
| 141 | if (!is_configuring) { | ||
| 142 | return; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void EmulatedConsole::RestoreConfig() { | ||
| 147 | if (!is_configuring) { | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | ReloadFromSettings(); | ||
| 151 | } | ||
| 152 | |||
| 153 | Common::ParamPackage EmulatedConsole::GetMotionParam() const { | ||
| 154 | return motion_params[0]; | ||
| 155 | } | ||
| 156 | |||
| 157 | void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { | ||
| 158 | motion_params[0] = std::move(param); | ||
| 159 | ReloadInput(); | ||
| 160 | } | ||
| 161 | |||
| 162 | void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { | ||
| 163 | std::unique_lock lock{mutex}; | ||
| 164 | auto& raw_status = console.motion_values.raw_status; | ||
| 165 | auto& emulated = console.motion_values.emulated; | ||
| 166 | |||
| 167 | raw_status = TransformToMotion(callback); | ||
| 168 | emulated.SetAcceleration(Common::Vec3f{ | ||
| 169 | raw_status.accel.x.value, | ||
| 170 | raw_status.accel.y.value, | ||
| 171 | raw_status.accel.z.value, | ||
| 172 | }); | ||
| 173 | emulated.SetGyroscope(Common::Vec3f{ | ||
| 174 | raw_status.gyro.x.value, | ||
| 175 | raw_status.gyro.y.value, | ||
| 176 | raw_status.gyro.z.value, | ||
| 177 | }); | ||
| 178 | emulated.UpdateRotation(raw_status.delta_timestamp); | ||
| 179 | emulated.UpdateOrientation(raw_status.delta_timestamp); | ||
| 180 | |||
| 181 | if (is_configuring) { | ||
| 182 | lock.unlock(); | ||
| 183 | TriggerOnChange(ConsoleTriggerType::Motion); | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | auto& motion = console.motion_state; | ||
| 188 | motion.accel = emulated.GetAcceleration(); | ||
| 189 | motion.gyro = emulated.GetGyroscope(); | ||
| 190 | motion.rotation = emulated.GetRotations(); | ||
| 191 | motion.orientation = emulated.GetOrientation(); | ||
| 192 | motion.quaternion = emulated.GetQuaternion(); | ||
| 193 | motion.gyro_bias = emulated.GetGyroBias(); | ||
| 194 | motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); | ||
| 195 | // Find what is this value | ||
| 196 | motion.verticalization_error = 0.0f; | ||
| 197 | |||
| 198 | lock.unlock(); | ||
| 199 | TriggerOnChange(ConsoleTriggerType::Motion); | ||
| 200 | } | ||
| 201 | |||
| 202 | void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) { | ||
| 203 | if (index >= MaxTouchDevices) { | ||
| 204 | return; | ||
| 205 | } | ||
| 206 | std::unique_lock lock{mutex}; | ||
| 207 | |||
| 208 | const auto touch_input = TransformToTouch(callback); | ||
| 209 | auto touch_index = GetIndexFromFingerId(index); | ||
| 210 | bool is_new_input = false; | ||
| 211 | |||
| 212 | if (!touch_index.has_value() && touch_input.pressed.value) { | ||
| 213 | touch_index = GetNextFreeIndex(); | ||
| 214 | is_new_input = true; | ||
| 215 | } | ||
| 216 | |||
| 217 | // No free entries or invalid state. Ignore input | ||
| 218 | if (!touch_index.has_value()) { | ||
| 219 | return; | ||
| 220 | } | ||
| 221 | |||
| 222 | auto& touch_value = console.touch_values[touch_index.value()]; | ||
| 223 | |||
| 224 | if (is_new_input) { | ||
| 225 | touch_value.pressed.value = true; | ||
| 226 | touch_value.id = static_cast<int>(index); | ||
| 227 | } | ||
| 228 | |||
| 229 | touch_value.x = touch_input.x; | ||
| 230 | touch_value.y = touch_input.y; | ||
| 231 | |||
| 232 | if (!touch_input.pressed.value) { | ||
| 233 | touch_value.pressed.value = false; | ||
| 234 | } | ||
| 235 | |||
| 236 | if (is_configuring) { | ||
| 237 | lock.unlock(); | ||
| 238 | TriggerOnChange(ConsoleTriggerType::Touch); | ||
| 239 | return; | ||
| 240 | } | ||
| 241 | |||
| 242 | // Touch outside allowed range. Ignore input | ||
| 243 | if (touch_index.value() >= MaxActiveTouchInputs) { | ||
| 244 | return; | ||
| 245 | } | ||
| 246 | |||
| 247 | console.touch_state[touch_index.value()] = { | ||
| 248 | .position = {touch_value.x.value, touch_value.y.value}, | ||
| 249 | .id = static_cast<u32>(touch_index.value()), | ||
| 250 | .pressed = touch_input.pressed.value, | ||
| 251 | }; | ||
| 252 | |||
| 253 | lock.unlock(); | ||
| 254 | TriggerOnChange(ConsoleTriggerType::Touch); | ||
| 255 | } | ||
| 256 | |||
| 257 | ConsoleMotionValues EmulatedConsole::GetMotionValues() const { | ||
| 258 | std::scoped_lock lock{mutex}; | ||
| 259 | return console.motion_values; | ||
| 260 | } | ||
| 261 | |||
| 262 | TouchValues EmulatedConsole::GetTouchValues() const { | ||
| 263 | std::scoped_lock lock{mutex}; | ||
| 264 | return console.touch_values; | ||
| 265 | } | ||
| 266 | |||
| 267 | ConsoleMotion EmulatedConsole::GetMotion() const { | ||
| 268 | std::scoped_lock lock{mutex}; | ||
| 269 | return console.motion_state; | ||
| 270 | } | ||
| 271 | |||
| 272 | TouchFingerState EmulatedConsole::GetTouch() const { | ||
| 273 | std::scoped_lock lock{mutex}; | ||
| 274 | return console.touch_state; | ||
| 275 | } | ||
| 276 | |||
| 277 | std::optional<std::size_t> EmulatedConsole::GetIndexFromFingerId(std::size_t finger_id) const { | ||
| 278 | for (std::size_t index = 0; index < MaxTouchDevices; ++index) { | ||
| 279 | const auto& finger = console.touch_values[index]; | ||
| 280 | if (!finger.pressed.value) { | ||
| 281 | continue; | ||
| 282 | } | ||
| 283 | if (finger.id == static_cast<int>(finger_id)) { | ||
| 284 | return index; | ||
| 285 | } | ||
| 286 | } | ||
| 287 | return std::nullopt; | ||
| 288 | } | ||
| 289 | |||
| 290 | std::optional<std::size_t> EmulatedConsole::GetNextFreeIndex() const { | ||
| 291 | for (std::size_t index = 0; index < MaxTouchDevices; ++index) { | ||
| 292 | if (!console.touch_values[index].pressed.value) { | ||
| 293 | return index; | ||
| 294 | } | ||
| 295 | } | ||
| 296 | return std::nullopt; | ||
| 297 | } | ||
| 298 | |||
| 299 | void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { | ||
| 300 | std::scoped_lock lock{callback_mutex}; | ||
| 301 | for (const auto& poller_pair : callback_list) { | ||
| 302 | const ConsoleUpdateCallback& poller = poller_pair.second; | ||
| 303 | if (poller.on_change) { | ||
| 304 | poller.on_change(type); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { | ||
| 310 | std::scoped_lock lock{callback_mutex}; | ||
| 311 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); | ||
| 312 | return last_callback_key++; | ||
| 313 | } | ||
| 314 | |||
| 315 | void EmulatedConsole::DeleteCallback(int key) { | ||
| 316 | std::scoped_lock lock{callback_mutex}; | ||
| 317 | const auto& iterator = callback_list.find(key); | ||
| 318 | if (iterator == callback_list.end()) { | ||
| 319 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | ||
| 320 | return; | ||
| 321 | } | ||
| 322 | callback_list.erase(iterator); | ||
| 323 | } | ||
| 324 | } // namespace Core::HID | ||
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h deleted file mode 100644 index fae15a556..000000000 --- a/src/core/hid/emulated_console.h +++ /dev/null | |||
| @@ -1,192 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <functional> | ||
| 8 | #include <memory> | ||
| 9 | #include <mutex> | ||
| 10 | #include <optional> | ||
| 11 | #include <unordered_map> | ||
| 12 | |||
| 13 | #include "common/common_funcs.h" | ||
| 14 | #include "common/common_types.h" | ||
| 15 | #include "common/input.h" | ||
| 16 | #include "common/param_package.h" | ||
| 17 | #include "common/point.h" | ||
| 18 | #include "common/quaternion.h" | ||
| 19 | #include "common/vector_math.h" | ||
| 20 | #include "core/hid/hid_types.h" | ||
| 21 | #include "core/hid/motion_input.h" | ||
| 22 | |||
| 23 | namespace Core::HID { | ||
| 24 | static constexpr std::size_t MaxTouchDevices = 32; | ||
| 25 | static constexpr std::size_t MaxActiveTouchInputs = 16; | ||
| 26 | |||
| 27 | struct ConsoleMotionInfo { | ||
| 28 | Common::Input::MotionStatus raw_status{}; | ||
| 29 | MotionInput emulated{}; | ||
| 30 | }; | ||
| 31 | |||
| 32 | using ConsoleMotionDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, 2>; | ||
| 33 | using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, MaxTouchDevices>; | ||
| 34 | |||
| 35 | using ConsoleMotionParams = std::array<Common::ParamPackage, 2>; | ||
| 36 | using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>; | ||
| 37 | |||
| 38 | using ConsoleMotionValues = ConsoleMotionInfo; | ||
| 39 | using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>; | ||
| 40 | |||
| 41 | // Contains all motion related data that is used on the services | ||
| 42 | struct ConsoleMotion { | ||
| 43 | Common::Vec3f accel{}; | ||
| 44 | Common::Vec3f gyro{}; | ||
| 45 | Common::Vec3f rotation{}; | ||
| 46 | std::array<Common::Vec3f, 3> orientation{}; | ||
| 47 | Common::Quaternion<f32> quaternion{}; | ||
| 48 | Common::Vec3f gyro_bias{}; | ||
| 49 | f32 verticalization_error{}; | ||
| 50 | bool is_at_rest{}; | ||
| 51 | }; | ||
| 52 | |||
| 53 | using TouchFingerState = std::array<TouchFinger, MaxActiveTouchInputs>; | ||
| 54 | |||
| 55 | struct ConsoleStatus { | ||
| 56 | // Data from input_common | ||
| 57 | ConsoleMotionValues motion_values{}; | ||
| 58 | TouchValues touch_values{}; | ||
| 59 | |||
| 60 | // Data for HID services | ||
| 61 | ConsoleMotion motion_state{}; | ||
| 62 | TouchFingerState touch_state{}; | ||
| 63 | }; | ||
| 64 | |||
| 65 | enum class ConsoleTriggerType { | ||
| 66 | Motion, | ||
| 67 | Touch, | ||
| 68 | All, | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct ConsoleUpdateCallback { | ||
| 72 | std::function<void(ConsoleTriggerType)> on_change; | ||
| 73 | }; | ||
| 74 | |||
| 75 | class EmulatedConsole { | ||
| 76 | public: | ||
| 77 | /** | ||
| 78 | * Contains all input data within the emulated switch console tablet such as touch and motion | ||
| 79 | */ | ||
| 80 | explicit EmulatedConsole(); | ||
| 81 | ~EmulatedConsole(); | ||
| 82 | |||
| 83 | YUZU_NON_COPYABLE(EmulatedConsole); | ||
| 84 | YUZU_NON_MOVEABLE(EmulatedConsole); | ||
| 85 | |||
| 86 | /// Removes all callbacks created from input devices | ||
| 87 | void UnloadInput(); | ||
| 88 | |||
| 89 | /** | ||
| 90 | * Sets the emulated console into configuring mode | ||
| 91 | * This prevents the modification of the HID state of the emulated console by input commands | ||
| 92 | */ | ||
| 93 | void EnableConfiguration(); | ||
| 94 | |||
| 95 | /// Returns the emulated console into normal mode, allowing the modification of the HID state | ||
| 96 | void DisableConfiguration(); | ||
| 97 | |||
| 98 | /// Returns true if the emulated console is in configuring mode | ||
| 99 | bool IsConfiguring() const; | ||
| 100 | |||
| 101 | /// Reload all input devices | ||
| 102 | void ReloadInput(); | ||
| 103 | |||
| 104 | /// Overrides current mapped devices with the stored configuration and reloads all input devices | ||
| 105 | void ReloadFromSettings(); | ||
| 106 | |||
| 107 | /// Saves the current mapped configuration | ||
| 108 | void SaveCurrentConfig(); | ||
| 109 | |||
| 110 | /// Reverts any mapped changes made that weren't saved | ||
| 111 | void RestoreConfig(); | ||
| 112 | |||
| 113 | // Returns the current mapped motion device | ||
| 114 | Common::ParamPackage GetMotionParam() const; | ||
| 115 | |||
| 116 | /** | ||
| 117 | * Updates the current mapped motion device | ||
| 118 | * @param param ParamPackage with controller data to be mapped | ||
| 119 | */ | ||
| 120 | void SetMotionParam(Common::ParamPackage param); | ||
| 121 | |||
| 122 | /// Returns the latest status of motion input from the console with parameters | ||
| 123 | ConsoleMotionValues GetMotionValues() const; | ||
| 124 | |||
| 125 | /// Returns the latest status of touch input from the console with parameters | ||
| 126 | TouchValues GetTouchValues() const; | ||
| 127 | |||
| 128 | /// Returns the latest status of motion input from the console | ||
| 129 | ConsoleMotion GetMotion() const; | ||
| 130 | |||
| 131 | /// Returns the latest status of touch input from the console | ||
| 132 | TouchFingerState GetTouch() const; | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Adds a callback to the list of events | ||
| 136 | * @param update_callback A ConsoleUpdateCallback that will be triggered | ||
| 137 | * @return an unique key corresponding to the callback index in the list | ||
| 138 | */ | ||
| 139 | int SetCallback(ConsoleUpdateCallback update_callback); | ||
| 140 | |||
| 141 | /** | ||
| 142 | * Removes a callback from the list stopping any future events to this object | ||
| 143 | * @param key Key corresponding to the callback index in the list | ||
| 144 | */ | ||
| 145 | void DeleteCallback(int key); | ||
| 146 | |||
| 147 | private: | ||
| 148 | /// Creates and stores the touch params | ||
| 149 | void SetTouchParams(); | ||
| 150 | |||
| 151 | /** | ||
| 152 | * Updates the motion status of the console | ||
| 153 | * @param callback A CallbackStatus containing gyro and accelerometer data | ||
| 154 | */ | ||
| 155 | void SetMotion(const Common::Input::CallbackStatus& callback); | ||
| 156 | |||
| 157 | /** | ||
| 158 | * Updates the touch status of the console | ||
| 159 | * @param callback A CallbackStatus containing the touch position | ||
| 160 | * @param index Finger ID to be updated | ||
| 161 | */ | ||
| 162 | void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 163 | |||
| 164 | std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const; | ||
| 165 | |||
| 166 | std::optional<std::size_t> GetNextFreeIndex() const; | ||
| 167 | |||
| 168 | /** | ||
| 169 | * Triggers a callback that something has changed on the console status | ||
| 170 | * @param type Input type of the event to trigger | ||
| 171 | */ | ||
| 172 | void TriggerOnChange(ConsoleTriggerType type); | ||
| 173 | |||
| 174 | bool is_configuring{false}; | ||
| 175 | f32 motion_sensitivity{0.01f}; | ||
| 176 | |||
| 177 | ConsoleMotionParams motion_params; | ||
| 178 | TouchParams touch_params; | ||
| 179 | |||
| 180 | ConsoleMotionDevices motion_devices; | ||
| 181 | TouchDevices touch_devices; | ||
| 182 | |||
| 183 | mutable std::mutex mutex; | ||
| 184 | mutable std::mutex callback_mutex; | ||
| 185 | std::unordered_map<int, ConsoleUpdateCallback> callback_list; | ||
| 186 | int last_callback_key = 0; | ||
| 187 | |||
| 188 | // Stores the current status of all console input | ||
| 189 | ConsoleStatus console; | ||
| 190 | }; | ||
| 191 | |||
| 192 | } // namespace Core::HID | ||
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp deleted file mode 100644 index a6e681e15..000000000 --- a/src/core/hid/emulated_controller.cpp +++ /dev/null | |||
| @@ -1,1972 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <common/scope_exit.h> | ||
| 6 | |||
| 7 | #include "common/polyfill_ranges.h" | ||
| 8 | #include "common/thread.h" | ||
| 9 | #include "core/hid/emulated_controller.h" | ||
| 10 | #include "core/hid/input_converter.h" | ||
| 11 | #include "core/hle/service/hid/hid_util.h" | ||
| 12 | |||
| 13 | namespace Core::HID { | ||
| 14 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | ||
| 15 | constexpr s32 HID_TRIGGER_MAX = 0x7fff; | ||
| 16 | constexpr u32 TURBO_BUTTON_DELAY = 4; | ||
| 17 | // Use a common UUID for TAS and Virtual Gamepad | ||
| 18 | constexpr Common::UUID TAS_UUID = | ||
| 19 | Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; | ||
| 20 | constexpr Common::UUID VIRTUAL_UUID = | ||
| 21 | Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; | ||
| 22 | |||
| 23 | EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {} | ||
| 24 | |||
| 25 | EmulatedController::~EmulatedController() = default; | ||
| 26 | |||
| 27 | NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { | ||
| 28 | switch (type) { | ||
| 29 | case Settings::ControllerType::ProController: | ||
| 30 | return NpadStyleIndex::ProController; | ||
| 31 | case Settings::ControllerType::DualJoyconDetached: | ||
| 32 | return NpadStyleIndex::JoyconDual; | ||
| 33 | case Settings::ControllerType::LeftJoycon: | ||
| 34 | return NpadStyleIndex::JoyconLeft; | ||
| 35 | case Settings::ControllerType::RightJoycon: | ||
| 36 | return NpadStyleIndex::JoyconRight; | ||
| 37 | case Settings::ControllerType::Handheld: | ||
| 38 | return NpadStyleIndex::Handheld; | ||
| 39 | case Settings::ControllerType::GameCube: | ||
| 40 | return NpadStyleIndex::GameCube; | ||
| 41 | case Settings::ControllerType::Pokeball: | ||
| 42 | return NpadStyleIndex::Pokeball; | ||
| 43 | case Settings::ControllerType::NES: | ||
| 44 | return NpadStyleIndex::NES; | ||
| 45 | case Settings::ControllerType::SNES: | ||
| 46 | return NpadStyleIndex::SNES; | ||
| 47 | case Settings::ControllerType::N64: | ||
| 48 | return NpadStyleIndex::N64; | ||
| 49 | case Settings::ControllerType::SegaGenesis: | ||
| 50 | return NpadStyleIndex::SegaGenesis; | ||
| 51 | default: | ||
| 52 | return NpadStyleIndex::ProController; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { | ||
| 57 | switch (type) { | ||
| 58 | case NpadStyleIndex::ProController: | ||
| 59 | return Settings::ControllerType::ProController; | ||
| 60 | case NpadStyleIndex::JoyconDual: | ||
| 61 | return Settings::ControllerType::DualJoyconDetached; | ||
| 62 | case NpadStyleIndex::JoyconLeft: | ||
| 63 | return Settings::ControllerType::LeftJoycon; | ||
| 64 | case NpadStyleIndex::JoyconRight: | ||
| 65 | return Settings::ControllerType::RightJoycon; | ||
| 66 | case NpadStyleIndex::Handheld: | ||
| 67 | return Settings::ControllerType::Handheld; | ||
| 68 | case NpadStyleIndex::GameCube: | ||
| 69 | return Settings::ControllerType::GameCube; | ||
| 70 | case NpadStyleIndex::Pokeball: | ||
| 71 | return Settings::ControllerType::Pokeball; | ||
| 72 | case NpadStyleIndex::NES: | ||
| 73 | return Settings::ControllerType::NES; | ||
| 74 | case NpadStyleIndex::SNES: | ||
| 75 | return Settings::ControllerType::SNES; | ||
| 76 | case NpadStyleIndex::N64: | ||
| 77 | return Settings::ControllerType::N64; | ||
| 78 | case NpadStyleIndex::SegaGenesis: | ||
| 79 | return Settings::ControllerType::SegaGenesis; | ||
| 80 | default: | ||
| 81 | return Settings::ControllerType::ProController; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | void EmulatedController::ReloadFromSettings() { | ||
| 86 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | ||
| 87 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 88 | |||
| 89 | for (std::size_t index = 0; index < player.buttons.size(); ++index) { | ||
| 90 | button_params[index] = Common::ParamPackage(player.buttons[index]); | ||
| 91 | } | ||
| 92 | for (std::size_t index = 0; index < player.analogs.size(); ++index) { | ||
| 93 | stick_params[index] = Common::ParamPackage(player.analogs[index]); | ||
| 94 | } | ||
| 95 | for (std::size_t index = 0; index < player.motions.size(); ++index) { | ||
| 96 | motion_params[index] = Common::ParamPackage(player.motions[index]); | ||
| 97 | } | ||
| 98 | |||
| 99 | controller.color_values = {}; | ||
| 100 | ReloadColorsFromSettings(); | ||
| 101 | |||
| 102 | ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs); | ||
| 103 | |||
| 104 | // Other or debug controller should always be a pro controller | ||
| 105 | if (npad_id_type != NpadIdType::Other) { | ||
| 106 | SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); | ||
| 107 | original_npad_type = npad_type; | ||
| 108 | } else { | ||
| 109 | SetNpadStyleIndex(NpadStyleIndex::ProController); | ||
| 110 | original_npad_type = npad_type; | ||
| 111 | } | ||
| 112 | |||
| 113 | Disconnect(); | ||
| 114 | if (player.connected) { | ||
| 115 | Connect(); | ||
| 116 | } | ||
| 117 | |||
| 118 | ReloadInput(); | ||
| 119 | } | ||
| 120 | |||
| 121 | void EmulatedController::ReloadColorsFromSettings() { | ||
| 122 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | ||
| 123 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 124 | |||
| 125 | // Avoid updating colors if overridden by physical controller | ||
| 126 | if (controller.color_values[LeftIndex].body != 0 && | ||
| 127 | controller.color_values[RightIndex].body != 0) { | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 131 | controller.colors_state.fullkey = { | ||
| 132 | .body = GetNpadColor(player.body_color_left), | ||
| 133 | .button = GetNpadColor(player.button_color_left), | ||
| 134 | }; | ||
| 135 | controller.colors_state.left = { | ||
| 136 | .body = GetNpadColor(player.body_color_left), | ||
| 137 | .button = GetNpadColor(player.button_color_left), | ||
| 138 | }; | ||
| 139 | controller.colors_state.right = { | ||
| 140 | .body = GetNpadColor(player.body_color_right), | ||
| 141 | .button = GetNpadColor(player.button_color_right), | ||
| 142 | }; | ||
| 143 | } | ||
| 144 | |||
| 145 | void EmulatedController::LoadDevices() { | ||
| 146 | // TODO(german77): Use more buttons to detect the correct device | ||
| 147 | const auto left_joycon = button_params[Settings::NativeButton::DRight]; | ||
| 148 | const auto right_joycon = button_params[Settings::NativeButton::A]; | ||
| 149 | |||
| 150 | // Triggers for GC controllers | ||
| 151 | trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; | ||
| 152 | trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR]; | ||
| 153 | |||
| 154 | color_params[LeftIndex] = left_joycon; | ||
| 155 | color_params[RightIndex] = right_joycon; | ||
| 156 | color_params[LeftIndex].Set("color", true); | ||
| 157 | color_params[RightIndex].Set("color", true); | ||
| 158 | |||
| 159 | battery_params[LeftIndex] = left_joycon; | ||
| 160 | battery_params[RightIndex] = right_joycon; | ||
| 161 | battery_params[LeftIndex].Set("battery", true); | ||
| 162 | battery_params[RightIndex].Set("battery", true); | ||
| 163 | |||
| 164 | camera_params[0] = right_joycon; | ||
| 165 | camera_params[0].Set("camera", true); | ||
| 166 | nfc_params[1] = right_joycon; | ||
| 167 | nfc_params[1].Set("nfc", true); | ||
| 168 | |||
| 169 | // Only map virtual devices to the first controller | ||
| 170 | if (npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld) { | ||
| 171 | camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"}; | ||
| 172 | ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; | ||
| 173 | nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; | ||
| 174 | } | ||
| 175 | |||
| 176 | output_params[LeftIndex] = left_joycon; | ||
| 177 | output_params[RightIndex] = right_joycon; | ||
| 178 | output_params[2] = camera_params[1]; | ||
| 179 | output_params[3] = nfc_params[0]; | ||
| 180 | output_params[LeftIndex].Set("output", true); | ||
| 181 | output_params[RightIndex].Set("output", true); | ||
| 182 | output_params[2].Set("output", true); | ||
| 183 | output_params[3].Set("output", true); | ||
| 184 | |||
| 185 | LoadTASParams(); | ||
| 186 | LoadVirtualGamepadParams(); | ||
| 187 | |||
| 188 | std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice); | ||
| 189 | std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice); | ||
| 190 | std::ranges::transform(motion_params, motion_devices.begin(), Common::Input::CreateInputDevice); | ||
| 191 | std::ranges::transform(trigger_params, trigger_devices.begin(), | ||
| 192 | Common::Input::CreateInputDevice); | ||
| 193 | std::ranges::transform(battery_params, battery_devices.begin(), | ||
| 194 | Common::Input::CreateInputDevice); | ||
| 195 | std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice); | ||
| 196 | std::ranges::transform(camera_params, camera_devices.begin(), Common::Input::CreateInputDevice); | ||
| 197 | std::ranges::transform(ring_params, ring_analog_devices.begin(), | ||
| 198 | Common::Input::CreateInputDevice); | ||
| 199 | std::ranges::transform(nfc_params, nfc_devices.begin(), Common::Input::CreateInputDevice); | ||
| 200 | std::ranges::transform(output_params, output_devices.begin(), | ||
| 201 | Common::Input::CreateOutputDevice); | ||
| 202 | |||
| 203 | // Initialize TAS devices | ||
| 204 | std::ranges::transform(tas_button_params, tas_button_devices.begin(), | ||
| 205 | Common::Input::CreateInputDevice); | ||
| 206 | std::ranges::transform(tas_stick_params, tas_stick_devices.begin(), | ||
| 207 | Common::Input::CreateInputDevice); | ||
| 208 | |||
| 209 | // Initialize virtual gamepad devices | ||
| 210 | std::ranges::transform(virtual_button_params, virtual_button_devices.begin(), | ||
| 211 | Common::Input::CreateInputDevice); | ||
| 212 | std::ranges::transform(virtual_stick_params, virtual_stick_devices.begin(), | ||
| 213 | Common::Input::CreateInputDevice); | ||
| 214 | std::ranges::transform(virtual_motion_params, virtual_motion_devices.begin(), | ||
| 215 | Common::Input::CreateInputDevice); | ||
| 216 | } | ||
| 217 | |||
| 218 | void EmulatedController::LoadTASParams() { | ||
| 219 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | ||
| 220 | Common::ParamPackage common_params{}; | ||
| 221 | common_params.Set("engine", "tas"); | ||
| 222 | common_params.Set("port", static_cast<int>(player_index)); | ||
| 223 | for (auto& param : tas_button_params) { | ||
| 224 | param = common_params; | ||
| 225 | } | ||
| 226 | for (auto& param : tas_stick_params) { | ||
| 227 | param = common_params; | ||
| 228 | } | ||
| 229 | |||
| 230 | // TODO(german77): Replace this with an input profile or something better | ||
| 231 | tas_button_params[Settings::NativeButton::A].Set("button", 0); | ||
| 232 | tas_button_params[Settings::NativeButton::B].Set("button", 1); | ||
| 233 | tas_button_params[Settings::NativeButton::X].Set("button", 2); | ||
| 234 | tas_button_params[Settings::NativeButton::Y].Set("button", 3); | ||
| 235 | tas_button_params[Settings::NativeButton::LStick].Set("button", 4); | ||
| 236 | tas_button_params[Settings::NativeButton::RStick].Set("button", 5); | ||
| 237 | tas_button_params[Settings::NativeButton::L].Set("button", 6); | ||
| 238 | tas_button_params[Settings::NativeButton::R].Set("button", 7); | ||
| 239 | tas_button_params[Settings::NativeButton::ZL].Set("button", 8); | ||
| 240 | tas_button_params[Settings::NativeButton::ZR].Set("button", 9); | ||
| 241 | tas_button_params[Settings::NativeButton::Plus].Set("button", 10); | ||
| 242 | tas_button_params[Settings::NativeButton::Minus].Set("button", 11); | ||
| 243 | tas_button_params[Settings::NativeButton::DLeft].Set("button", 12); | ||
| 244 | tas_button_params[Settings::NativeButton::DUp].Set("button", 13); | ||
| 245 | tas_button_params[Settings::NativeButton::DRight].Set("button", 14); | ||
| 246 | tas_button_params[Settings::NativeButton::DDown].Set("button", 15); | ||
| 247 | tas_button_params[Settings::NativeButton::SLLeft].Set("button", 16); | ||
| 248 | tas_button_params[Settings::NativeButton::SRLeft].Set("button", 17); | ||
| 249 | tas_button_params[Settings::NativeButton::Home].Set("button", 18); | ||
| 250 | tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19); | ||
| 251 | tas_button_params[Settings::NativeButton::SLRight].Set("button", 20); | ||
| 252 | tas_button_params[Settings::NativeButton::SRRight].Set("button", 21); | ||
| 253 | |||
| 254 | tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); | ||
| 255 | tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); | ||
| 256 | tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2); | ||
| 257 | tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); | ||
| 258 | |||
| 259 | // set to optimal stick to avoid sanitizing the stick and tweaking the coordinates | ||
| 260 | // making sure they play back in the game as originally written down in the script file | ||
| 261 | tas_stick_params[Settings::NativeAnalog::LStick].Set("deadzone", 0.0f); | ||
| 262 | tas_stick_params[Settings::NativeAnalog::LStick].Set("range", 1.0f); | ||
| 263 | tas_stick_params[Settings::NativeAnalog::RStick].Set("deadzone", 0.0f); | ||
| 264 | tas_stick_params[Settings::NativeAnalog::RStick].Set("range", 1.0f); | ||
| 265 | } | ||
| 266 | |||
| 267 | void EmulatedController::LoadVirtualGamepadParams() { | ||
| 268 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | ||
| 269 | Common::ParamPackage common_params{}; | ||
| 270 | common_params.Set("engine", "virtual_gamepad"); | ||
| 271 | common_params.Set("port", static_cast<int>(player_index)); | ||
| 272 | for (auto& param : virtual_button_params) { | ||
| 273 | param = common_params; | ||
| 274 | } | ||
| 275 | for (auto& param : virtual_stick_params) { | ||
| 276 | param = common_params; | ||
| 277 | } | ||
| 278 | for (auto& param : virtual_stick_params) { | ||
| 279 | param = common_params; | ||
| 280 | } | ||
| 281 | for (auto& param : virtual_motion_params) { | ||
| 282 | param = common_params; | ||
| 283 | } | ||
| 284 | |||
| 285 | // TODO(german77): Replace this with an input profile or something better | ||
| 286 | virtual_button_params[Settings::NativeButton::A].Set("button", 0); | ||
| 287 | virtual_button_params[Settings::NativeButton::B].Set("button", 1); | ||
| 288 | virtual_button_params[Settings::NativeButton::X].Set("button", 2); | ||
| 289 | virtual_button_params[Settings::NativeButton::Y].Set("button", 3); | ||
| 290 | virtual_button_params[Settings::NativeButton::LStick].Set("button", 4); | ||
| 291 | virtual_button_params[Settings::NativeButton::RStick].Set("button", 5); | ||
| 292 | virtual_button_params[Settings::NativeButton::L].Set("button", 6); | ||
| 293 | virtual_button_params[Settings::NativeButton::R].Set("button", 7); | ||
| 294 | virtual_button_params[Settings::NativeButton::ZL].Set("button", 8); | ||
| 295 | virtual_button_params[Settings::NativeButton::ZR].Set("button", 9); | ||
| 296 | virtual_button_params[Settings::NativeButton::Plus].Set("button", 10); | ||
| 297 | virtual_button_params[Settings::NativeButton::Minus].Set("button", 11); | ||
| 298 | virtual_button_params[Settings::NativeButton::DLeft].Set("button", 12); | ||
| 299 | virtual_button_params[Settings::NativeButton::DUp].Set("button", 13); | ||
| 300 | virtual_button_params[Settings::NativeButton::DRight].Set("button", 14); | ||
| 301 | virtual_button_params[Settings::NativeButton::DDown].Set("button", 15); | ||
| 302 | virtual_button_params[Settings::NativeButton::SLLeft].Set("button", 16); | ||
| 303 | virtual_button_params[Settings::NativeButton::SRLeft].Set("button", 17); | ||
| 304 | virtual_button_params[Settings::NativeButton::Home].Set("button", 18); | ||
| 305 | virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19); | ||
| 306 | virtual_button_params[Settings::NativeButton::SLRight].Set("button", 20); | ||
| 307 | virtual_button_params[Settings::NativeButton::SRRight].Set("button", 21); | ||
| 308 | |||
| 309 | virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); | ||
| 310 | virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); | ||
| 311 | virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2); | ||
| 312 | virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); | ||
| 313 | virtual_stick_params[Settings::NativeAnalog::LStick].Set("deadzone", 0.0f); | ||
| 314 | virtual_stick_params[Settings::NativeAnalog::LStick].Set("range", 1.0f); | ||
| 315 | virtual_stick_params[Settings::NativeAnalog::RStick].Set("deadzone", 0.0f); | ||
| 316 | virtual_stick_params[Settings::NativeAnalog::RStick].Set("range", 1.0f); | ||
| 317 | |||
| 318 | virtual_motion_params[Settings::NativeMotion::MotionLeft].Set("motion", 0); | ||
| 319 | virtual_motion_params[Settings::NativeMotion::MotionRight].Set("motion", 0); | ||
| 320 | } | ||
| 321 | |||
| 322 | void EmulatedController::ReloadInput() { | ||
| 323 | // If you load any device here add the equivalent to the UnloadInput() function | ||
| 324 | LoadDevices(); | ||
| 325 | for (std::size_t index = 0; index < button_devices.size(); ++index) { | ||
| 326 | if (!button_devices[index]) { | ||
| 327 | continue; | ||
| 328 | } | ||
| 329 | const auto uuid = Common::UUID{button_params[index].Get("guid", "")}; | ||
| 330 | button_devices[index]->SetCallback({ | ||
| 331 | .on_change = | ||
| 332 | [this, index, uuid](const Common::Input::CallbackStatus& callback) { | ||
| 333 | SetButton(callback, index, uuid); | ||
| 334 | }, | ||
| 335 | }); | ||
| 336 | button_devices[index]->ForceUpdate(); | ||
| 337 | } | ||
| 338 | |||
| 339 | for (std::size_t index = 0; index < stick_devices.size(); ++index) { | ||
| 340 | if (!stick_devices[index]) { | ||
| 341 | continue; | ||
| 342 | } | ||
| 343 | const auto uuid = Common::UUID{stick_params[index].Get("guid", "")}; | ||
| 344 | stick_devices[index]->SetCallback({ | ||
| 345 | .on_change = | ||
| 346 | [this, index, uuid](const Common::Input::CallbackStatus& callback) { | ||
| 347 | SetStick(callback, index, uuid); | ||
| 348 | }, | ||
| 349 | }); | ||
| 350 | stick_devices[index]->ForceUpdate(); | ||
| 351 | } | ||
| 352 | |||
| 353 | for (std::size_t index = 0; index < trigger_devices.size(); ++index) { | ||
| 354 | if (!trigger_devices[index]) { | ||
| 355 | continue; | ||
| 356 | } | ||
| 357 | const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")}; | ||
| 358 | trigger_devices[index]->SetCallback({ | ||
| 359 | .on_change = | ||
| 360 | [this, index, uuid](const Common::Input::CallbackStatus& callback) { | ||
| 361 | SetTrigger(callback, index, uuid); | ||
| 362 | }, | ||
| 363 | }); | ||
| 364 | trigger_devices[index]->ForceUpdate(); | ||
| 365 | } | ||
| 366 | |||
| 367 | for (std::size_t index = 0; index < battery_devices.size(); ++index) { | ||
| 368 | if (!battery_devices[index]) { | ||
| 369 | continue; | ||
| 370 | } | ||
| 371 | battery_devices[index]->SetCallback({ | ||
| 372 | .on_change = | ||
| 373 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 374 | SetBattery(callback, index); | ||
| 375 | }, | ||
| 376 | }); | ||
| 377 | battery_devices[index]->ForceUpdate(); | ||
| 378 | } | ||
| 379 | |||
| 380 | for (std::size_t index = 0; index < color_devices.size(); ++index) { | ||
| 381 | if (!color_devices[index]) { | ||
| 382 | continue; | ||
| 383 | } | ||
| 384 | color_devices[index]->SetCallback({ | ||
| 385 | .on_change = | ||
| 386 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 387 | SetColors(callback, index); | ||
| 388 | }, | ||
| 389 | }); | ||
| 390 | color_devices[index]->ForceUpdate(); | ||
| 391 | } | ||
| 392 | |||
| 393 | for (std::size_t index = 0; index < motion_devices.size(); ++index) { | ||
| 394 | if (!motion_devices[index]) { | ||
| 395 | continue; | ||
| 396 | } | ||
| 397 | motion_devices[index]->SetCallback({ | ||
| 398 | .on_change = | ||
| 399 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 400 | SetMotion(callback, index); | ||
| 401 | }, | ||
| 402 | }); | ||
| 403 | |||
| 404 | // Restore motion state | ||
| 405 | auto& emulated_motion = controller.motion_values[index].emulated; | ||
| 406 | auto& motion = controller.motion_state[index]; | ||
| 407 | emulated_motion.ResetRotations(); | ||
| 408 | emulated_motion.ResetQuaternion(); | ||
| 409 | motion.accel = emulated_motion.GetAcceleration(); | ||
| 410 | motion.gyro = emulated_motion.GetGyroscope(); | ||
| 411 | motion.rotation = emulated_motion.GetRotations(); | ||
| 412 | motion.euler = emulated_motion.GetEulerAngles(); | ||
| 413 | motion.orientation = emulated_motion.GetOrientation(); | ||
| 414 | motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); | ||
| 415 | } | ||
| 416 | |||
| 417 | for (std::size_t index = 0; index < camera_devices.size(); ++index) { | ||
| 418 | if (!camera_devices[index]) { | ||
| 419 | continue; | ||
| 420 | } | ||
| 421 | camera_devices[index]->SetCallback({ | ||
| 422 | .on_change = | ||
| 423 | [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); }, | ||
| 424 | }); | ||
| 425 | camera_devices[index]->ForceUpdate(); | ||
| 426 | } | ||
| 427 | |||
| 428 | for (std::size_t index = 0; index < ring_analog_devices.size(); ++index) { | ||
| 429 | if (!ring_analog_devices[index]) { | ||
| 430 | continue; | ||
| 431 | } | ||
| 432 | ring_analog_devices[index]->SetCallback({ | ||
| 433 | .on_change = | ||
| 434 | [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); }, | ||
| 435 | }); | ||
| 436 | ring_analog_devices[index]->ForceUpdate(); | ||
| 437 | } | ||
| 438 | |||
| 439 | for (std::size_t index = 0; index < nfc_devices.size(); ++index) { | ||
| 440 | if (!nfc_devices[index]) { | ||
| 441 | continue; | ||
| 442 | } | ||
| 443 | nfc_devices[index]->SetCallback({ | ||
| 444 | .on_change = | ||
| 445 | [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); }, | ||
| 446 | }); | ||
| 447 | nfc_devices[index]->ForceUpdate(); | ||
| 448 | } | ||
| 449 | |||
| 450 | // Register TAS devices. No need to force update | ||
| 451 | for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { | ||
| 452 | if (!tas_button_devices[index]) { | ||
| 453 | continue; | ||
| 454 | } | ||
| 455 | tas_button_devices[index]->SetCallback({ | ||
| 456 | .on_change = | ||
| 457 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 458 | SetButton(callback, index, TAS_UUID); | ||
| 459 | }, | ||
| 460 | }); | ||
| 461 | } | ||
| 462 | |||
| 463 | for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) { | ||
| 464 | if (!tas_stick_devices[index]) { | ||
| 465 | continue; | ||
| 466 | } | ||
| 467 | tas_stick_devices[index]->SetCallback({ | ||
| 468 | .on_change = | ||
| 469 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 470 | SetStick(callback, index, TAS_UUID); | ||
| 471 | }, | ||
| 472 | }); | ||
| 473 | } | ||
| 474 | |||
| 475 | // Register virtual devices. No need to force update | ||
| 476 | for (std::size_t index = 0; index < virtual_button_devices.size(); ++index) { | ||
| 477 | if (!virtual_button_devices[index]) { | ||
| 478 | continue; | ||
| 479 | } | ||
| 480 | virtual_button_devices[index]->SetCallback({ | ||
| 481 | .on_change = | ||
| 482 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 483 | SetButton(callback, index, VIRTUAL_UUID); | ||
| 484 | }, | ||
| 485 | }); | ||
| 486 | } | ||
| 487 | |||
| 488 | for (std::size_t index = 0; index < virtual_stick_devices.size(); ++index) { | ||
| 489 | if (!virtual_stick_devices[index]) { | ||
| 490 | continue; | ||
| 491 | } | ||
| 492 | virtual_stick_devices[index]->SetCallback({ | ||
| 493 | .on_change = | ||
| 494 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 495 | SetStick(callback, index, VIRTUAL_UUID); | ||
| 496 | }, | ||
| 497 | }); | ||
| 498 | } | ||
| 499 | |||
| 500 | for (std::size_t index = 0; index < virtual_motion_devices.size(); ++index) { | ||
| 501 | if (!virtual_motion_devices[index]) { | ||
| 502 | continue; | ||
| 503 | } | ||
| 504 | virtual_motion_devices[index]->SetCallback({ | ||
| 505 | .on_change = | ||
| 506 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 507 | SetMotion(callback, index); | ||
| 508 | }, | ||
| 509 | }); | ||
| 510 | } | ||
| 511 | turbo_button_state = 0; | ||
| 512 | is_initalized = true; | ||
| 513 | } | ||
| 514 | |||
| 515 | void EmulatedController::UnloadInput() { | ||
| 516 | is_initalized = false; | ||
| 517 | for (auto& button : button_devices) { | ||
| 518 | button.reset(); | ||
| 519 | } | ||
| 520 | for (auto& stick : stick_devices) { | ||
| 521 | stick.reset(); | ||
| 522 | } | ||
| 523 | for (auto& motion : motion_devices) { | ||
| 524 | motion.reset(); | ||
| 525 | } | ||
| 526 | for (auto& trigger : trigger_devices) { | ||
| 527 | trigger.reset(); | ||
| 528 | } | ||
| 529 | for (auto& battery : battery_devices) { | ||
| 530 | battery.reset(); | ||
| 531 | } | ||
| 532 | for (auto& color : color_devices) { | ||
| 533 | color.reset(); | ||
| 534 | } | ||
| 535 | for (auto& output : output_devices) { | ||
| 536 | output.reset(); | ||
| 537 | } | ||
| 538 | for (auto& button : tas_button_devices) { | ||
| 539 | button.reset(); | ||
| 540 | } | ||
| 541 | for (auto& stick : tas_stick_devices) { | ||
| 542 | stick.reset(); | ||
| 543 | } | ||
| 544 | for (auto& button : virtual_button_devices) { | ||
| 545 | button.reset(); | ||
| 546 | } | ||
| 547 | for (auto& stick : virtual_stick_devices) { | ||
| 548 | stick.reset(); | ||
| 549 | } | ||
| 550 | for (auto& motion : virtual_motion_devices) { | ||
| 551 | motion.reset(); | ||
| 552 | } | ||
| 553 | for (auto& camera : camera_devices) { | ||
| 554 | camera.reset(); | ||
| 555 | } | ||
| 556 | for (auto& ring : ring_analog_devices) { | ||
| 557 | ring.reset(); | ||
| 558 | } | ||
| 559 | for (auto& nfc : nfc_devices) { | ||
| 560 | nfc.reset(); | ||
| 561 | } | ||
| 562 | } | ||
| 563 | |||
| 564 | void EmulatedController::EnableConfiguration() { | ||
| 565 | std::scoped_lock lock{connect_mutex, npad_mutex}; | ||
| 566 | is_configuring = true; | ||
| 567 | tmp_is_connected = is_connected; | ||
| 568 | tmp_npad_type = npad_type; | ||
| 569 | } | ||
| 570 | |||
| 571 | void EmulatedController::DisableConfiguration() { | ||
| 572 | is_configuring = false; | ||
| 573 | |||
| 574 | // Get Joycon colors before turning on the controller | ||
| 575 | for (const auto& color_device : color_devices) { | ||
| 576 | color_device->ForceUpdate(); | ||
| 577 | } | ||
| 578 | |||
| 579 | // Apply temporary npad type to the real controller | ||
| 580 | if (tmp_npad_type != npad_type) { | ||
| 581 | if (is_connected) { | ||
| 582 | Disconnect(); | ||
| 583 | } | ||
| 584 | SetNpadStyleIndex(tmp_npad_type); | ||
| 585 | original_npad_type = tmp_npad_type; | ||
| 586 | } | ||
| 587 | |||
| 588 | // Apply temporary connected status to the real controller | ||
| 589 | if (tmp_is_connected != is_connected) { | ||
| 590 | if (tmp_is_connected) { | ||
| 591 | Connect(); | ||
| 592 | return; | ||
| 593 | } | ||
| 594 | Disconnect(); | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 598 | void EmulatedController::EnableSystemButtons() { | ||
| 599 | std::scoped_lock lock{mutex}; | ||
| 600 | system_buttons_enabled = true; | ||
| 601 | } | ||
| 602 | |||
| 603 | void EmulatedController::DisableSystemButtons() { | ||
| 604 | std::scoped_lock lock{mutex}; | ||
| 605 | system_buttons_enabled = false; | ||
| 606 | controller.home_button_state.raw = 0; | ||
| 607 | controller.capture_button_state.raw = 0; | ||
| 608 | } | ||
| 609 | |||
| 610 | void EmulatedController::ResetSystemButtons() { | ||
| 611 | std::scoped_lock lock{mutex}; | ||
| 612 | controller.home_button_state.home.Assign(false); | ||
| 613 | controller.capture_button_state.capture.Assign(false); | ||
| 614 | } | ||
| 615 | |||
| 616 | bool EmulatedController::IsConfiguring() const { | ||
| 617 | return is_configuring; | ||
| 618 | } | ||
| 619 | |||
| 620 | void EmulatedController::SaveCurrentConfig() { | ||
| 621 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | ||
| 622 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 623 | player.connected = is_connected; | ||
| 624 | player.controller_type = MapNPadToSettingsType(npad_type); | ||
| 625 | for (std::size_t index = 0; index < player.buttons.size(); ++index) { | ||
| 626 | player.buttons[index] = button_params[index].Serialize(); | ||
| 627 | } | ||
| 628 | for (std::size_t index = 0; index < player.analogs.size(); ++index) { | ||
| 629 | player.analogs[index] = stick_params[index].Serialize(); | ||
| 630 | } | ||
| 631 | for (std::size_t index = 0; index < player.motions.size(); ++index) { | ||
| 632 | player.motions[index] = motion_params[index].Serialize(); | ||
| 633 | } | ||
| 634 | if (npad_id_type == NpadIdType::Player1) { | ||
| 635 | Settings::values.ringcon_analogs = ring_params[0].Serialize(); | ||
| 636 | } | ||
| 637 | } | ||
| 638 | |||
| 639 | void EmulatedController::RestoreConfig() { | ||
| 640 | if (!is_configuring) { | ||
| 641 | return; | ||
| 642 | } | ||
| 643 | ReloadFromSettings(); | ||
| 644 | } | ||
| 645 | |||
| 646 | std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const { | ||
| 647 | std::vector<Common::ParamPackage> devices; | ||
| 648 | for (const auto& param : button_params) { | ||
| 649 | if (!param.Has("engine")) { | ||
| 650 | continue; | ||
| 651 | } | ||
| 652 | const auto devices_it = std::find_if( | ||
| 653 | devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) { | ||
| 654 | return param.Get("engine", "") == param_.Get("engine", "") && | ||
| 655 | param.Get("guid", "") == param_.Get("guid", "") && | ||
| 656 | param.Get("port", 0) == param_.Get("port", 0) && | ||
| 657 | param.Get("pad", 0) == param_.Get("pad", 0); | ||
| 658 | }); | ||
| 659 | if (devices_it != devices.end()) { | ||
| 660 | continue; | ||
| 661 | } | ||
| 662 | |||
| 663 | auto& device = devices.emplace_back(); | ||
| 664 | device.Set("engine", param.Get("engine", "")); | ||
| 665 | device.Set("guid", param.Get("guid", "")); | ||
| 666 | device.Set("port", param.Get("port", 0)); | ||
| 667 | device.Set("pad", param.Get("pad", 0)); | ||
| 668 | } | ||
| 669 | |||
| 670 | for (const auto& param : stick_params) { | ||
| 671 | if (!param.Has("engine")) { | ||
| 672 | continue; | ||
| 673 | } | ||
| 674 | if (param.Get("engine", "") == "analog_from_button") { | ||
| 675 | continue; | ||
| 676 | } | ||
| 677 | const auto devices_it = std::find_if( | ||
| 678 | devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) { | ||
| 679 | return param.Get("engine", "") == param_.Get("engine", "") && | ||
| 680 | param.Get("guid", "") == param_.Get("guid", "") && | ||
| 681 | param.Get("port", 0) == param_.Get("port", 0) && | ||
| 682 | param.Get("pad", 0) == param_.Get("pad", 0); | ||
| 683 | }); | ||
| 684 | if (devices_it != devices.end()) { | ||
| 685 | continue; | ||
| 686 | } | ||
| 687 | |||
| 688 | auto& device = devices.emplace_back(); | ||
| 689 | device.Set("engine", param.Get("engine", "")); | ||
| 690 | device.Set("guid", param.Get("guid", "")); | ||
| 691 | device.Set("port", param.Get("port", 0)); | ||
| 692 | device.Set("pad", param.Get("pad", 0)); | ||
| 693 | } | ||
| 694 | return devices; | ||
| 695 | } | ||
| 696 | |||
| 697 | Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const { | ||
| 698 | if (index >= button_params.size()) { | ||
| 699 | return {}; | ||
| 700 | } | ||
| 701 | return button_params[index]; | ||
| 702 | } | ||
| 703 | |||
| 704 | Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const { | ||
| 705 | if (index >= stick_params.size()) { | ||
| 706 | return {}; | ||
| 707 | } | ||
| 708 | return stick_params[index]; | ||
| 709 | } | ||
| 710 | |||
| 711 | Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const { | ||
| 712 | if (index >= motion_params.size()) { | ||
| 713 | return {}; | ||
| 714 | } | ||
| 715 | return motion_params[index]; | ||
| 716 | } | ||
| 717 | |||
| 718 | void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) { | ||
| 719 | if (index >= button_params.size()) { | ||
| 720 | return; | ||
| 721 | } | ||
| 722 | button_params[index] = std::move(param); | ||
| 723 | ReloadInput(); | ||
| 724 | } | ||
| 725 | |||
| 726 | void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) { | ||
| 727 | if (index >= stick_params.size()) { | ||
| 728 | return; | ||
| 729 | } | ||
| 730 | stick_params[index] = std::move(param); | ||
| 731 | ReloadInput(); | ||
| 732 | } | ||
| 733 | |||
| 734 | void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) { | ||
| 735 | if (index >= motion_params.size()) { | ||
| 736 | return; | ||
| 737 | } | ||
| 738 | motion_params[index] = std::move(param); | ||
| 739 | ReloadInput(); | ||
| 740 | } | ||
| 741 | |||
| 742 | void EmulatedController::StartMotionCalibration() { | ||
| 743 | for (ControllerMotionInfo& motion : controller.motion_values) { | ||
| 744 | motion.emulated.Calibrate(); | ||
| 745 | } | ||
| 746 | } | ||
| 747 | |||
| 748 | void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 749 | Common::UUID uuid) { | ||
| 750 | if (index >= controller.button_values.size()) { | ||
| 751 | return; | ||
| 752 | } | ||
| 753 | std::unique_lock lock{mutex}; | ||
| 754 | bool value_changed = false; | ||
| 755 | const auto new_status = TransformToButton(callback); | ||
| 756 | auto& current_status = controller.button_values[index]; | ||
| 757 | |||
| 758 | // Only read button values that have the same uuid or are pressed once | ||
| 759 | if (current_status.uuid != uuid) { | ||
| 760 | if (!new_status.value) { | ||
| 761 | return; | ||
| 762 | } | ||
| 763 | } | ||
| 764 | |||
| 765 | current_status.toggle = new_status.toggle; | ||
| 766 | current_status.turbo = new_status.turbo; | ||
| 767 | current_status.uuid = uuid; | ||
| 768 | |||
| 769 | // Update button status with current | ||
| 770 | if (!current_status.toggle) { | ||
| 771 | current_status.locked = false; | ||
| 772 | if (current_status.value != new_status.value) { | ||
| 773 | current_status.value = new_status.value; | ||
| 774 | value_changed = true; | ||
| 775 | } | ||
| 776 | } else { | ||
| 777 | // Toggle button and lock status | ||
| 778 | if (new_status.value && !current_status.locked) { | ||
| 779 | current_status.locked = true; | ||
| 780 | current_status.value = !current_status.value; | ||
| 781 | value_changed = true; | ||
| 782 | } | ||
| 783 | |||
| 784 | // Unlock button ready for next press | ||
| 785 | if (!new_status.value && current_status.locked) { | ||
| 786 | current_status.locked = false; | ||
| 787 | } | ||
| 788 | } | ||
| 789 | |||
| 790 | if (!value_changed) { | ||
| 791 | return; | ||
| 792 | } | ||
| 793 | |||
| 794 | if (is_configuring) { | ||
| 795 | controller.npad_button_state.raw = NpadButton::None; | ||
| 796 | controller.debug_pad_button_state.raw = 0; | ||
| 797 | controller.home_button_state.raw = 0; | ||
| 798 | controller.capture_button_state.raw = 0; | ||
| 799 | lock.unlock(); | ||
| 800 | TriggerOnChange(ControllerTriggerType::Button, false); | ||
| 801 | return; | ||
| 802 | } | ||
| 803 | |||
| 804 | // GC controllers have triggers not buttons | ||
| 805 | if (npad_type == NpadStyleIndex::GameCube) { | ||
| 806 | if (index == Settings::NativeButton::ZR) { | ||
| 807 | return; | ||
| 808 | } | ||
| 809 | if (index == Settings::NativeButton::ZL) { | ||
| 810 | return; | ||
| 811 | } | ||
| 812 | } | ||
| 813 | |||
| 814 | switch (index) { | ||
| 815 | case Settings::NativeButton::A: | ||
| 816 | controller.npad_button_state.a.Assign(current_status.value); | ||
| 817 | controller.debug_pad_button_state.a.Assign(current_status.value); | ||
| 818 | break; | ||
| 819 | case Settings::NativeButton::B: | ||
| 820 | controller.npad_button_state.b.Assign(current_status.value); | ||
| 821 | controller.debug_pad_button_state.b.Assign(current_status.value); | ||
| 822 | break; | ||
| 823 | case Settings::NativeButton::X: | ||
| 824 | controller.npad_button_state.x.Assign(current_status.value); | ||
| 825 | controller.debug_pad_button_state.x.Assign(current_status.value); | ||
| 826 | break; | ||
| 827 | case Settings::NativeButton::Y: | ||
| 828 | controller.npad_button_state.y.Assign(current_status.value); | ||
| 829 | controller.debug_pad_button_state.y.Assign(current_status.value); | ||
| 830 | break; | ||
| 831 | case Settings::NativeButton::LStick: | ||
| 832 | controller.npad_button_state.stick_l.Assign(current_status.value); | ||
| 833 | break; | ||
| 834 | case Settings::NativeButton::RStick: | ||
| 835 | controller.npad_button_state.stick_r.Assign(current_status.value); | ||
| 836 | break; | ||
| 837 | case Settings::NativeButton::L: | ||
| 838 | controller.npad_button_state.l.Assign(current_status.value); | ||
| 839 | controller.debug_pad_button_state.l.Assign(current_status.value); | ||
| 840 | break; | ||
| 841 | case Settings::NativeButton::R: | ||
| 842 | controller.npad_button_state.r.Assign(current_status.value); | ||
| 843 | controller.debug_pad_button_state.r.Assign(current_status.value); | ||
| 844 | break; | ||
| 845 | case Settings::NativeButton::ZL: | ||
| 846 | controller.npad_button_state.zl.Assign(current_status.value); | ||
| 847 | controller.debug_pad_button_state.zl.Assign(current_status.value); | ||
| 848 | break; | ||
| 849 | case Settings::NativeButton::ZR: | ||
| 850 | controller.npad_button_state.zr.Assign(current_status.value); | ||
| 851 | controller.debug_pad_button_state.zr.Assign(current_status.value); | ||
| 852 | break; | ||
| 853 | case Settings::NativeButton::Plus: | ||
| 854 | controller.npad_button_state.plus.Assign(current_status.value); | ||
| 855 | controller.debug_pad_button_state.plus.Assign(current_status.value); | ||
| 856 | break; | ||
| 857 | case Settings::NativeButton::Minus: | ||
| 858 | controller.npad_button_state.minus.Assign(current_status.value); | ||
| 859 | controller.debug_pad_button_state.minus.Assign(current_status.value); | ||
| 860 | break; | ||
| 861 | case Settings::NativeButton::DLeft: | ||
| 862 | controller.npad_button_state.left.Assign(current_status.value); | ||
| 863 | controller.debug_pad_button_state.d_left.Assign(current_status.value); | ||
| 864 | break; | ||
| 865 | case Settings::NativeButton::DUp: | ||
| 866 | controller.npad_button_state.up.Assign(current_status.value); | ||
| 867 | controller.debug_pad_button_state.d_up.Assign(current_status.value); | ||
| 868 | break; | ||
| 869 | case Settings::NativeButton::DRight: | ||
| 870 | controller.npad_button_state.right.Assign(current_status.value); | ||
| 871 | controller.debug_pad_button_state.d_right.Assign(current_status.value); | ||
| 872 | break; | ||
| 873 | case Settings::NativeButton::DDown: | ||
| 874 | controller.npad_button_state.down.Assign(current_status.value); | ||
| 875 | controller.debug_pad_button_state.d_down.Assign(current_status.value); | ||
| 876 | break; | ||
| 877 | case Settings::NativeButton::SLLeft: | ||
| 878 | controller.npad_button_state.left_sl.Assign(current_status.value); | ||
| 879 | break; | ||
| 880 | case Settings::NativeButton::SLRight: | ||
| 881 | controller.npad_button_state.right_sl.Assign(current_status.value); | ||
| 882 | break; | ||
| 883 | case Settings::NativeButton::SRLeft: | ||
| 884 | controller.npad_button_state.left_sr.Assign(current_status.value); | ||
| 885 | break; | ||
| 886 | case Settings::NativeButton::SRRight: | ||
| 887 | controller.npad_button_state.right_sr.Assign(current_status.value); | ||
| 888 | break; | ||
| 889 | case Settings::NativeButton::Home: | ||
| 890 | if (!system_buttons_enabled) { | ||
| 891 | break; | ||
| 892 | } | ||
| 893 | controller.home_button_state.home.Assign(current_status.value); | ||
| 894 | break; | ||
| 895 | case Settings::NativeButton::Screenshot: | ||
| 896 | if (!system_buttons_enabled) { | ||
| 897 | break; | ||
| 898 | } | ||
| 899 | controller.capture_button_state.capture.Assign(current_status.value); | ||
| 900 | break; | ||
| 901 | } | ||
| 902 | |||
| 903 | lock.unlock(); | ||
| 904 | |||
| 905 | if (!is_connected) { | ||
| 906 | if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) { | ||
| 907 | Connect(); | ||
| 908 | } | ||
| 909 | if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) { | ||
| 910 | Connect(); | ||
| 911 | } | ||
| 912 | } | ||
| 913 | TriggerOnChange(ControllerTriggerType::Button, true); | ||
| 914 | } | ||
| 915 | |||
| 916 | void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 917 | Common::UUID uuid) { | ||
| 918 | if (index >= controller.stick_values.size()) { | ||
| 919 | return; | ||
| 920 | } | ||
| 921 | auto trigger_guard = | ||
| 922 | SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); }); | ||
| 923 | std::scoped_lock lock{mutex}; | ||
| 924 | const auto stick_value = TransformToStick(callback); | ||
| 925 | |||
| 926 | // Only read stick values that have the same uuid or are over the threshold to avoid flapping | ||
| 927 | if (controller.stick_values[index].uuid != uuid) { | ||
| 928 | const bool is_tas = uuid == TAS_UUID; | ||
| 929 | if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) { | ||
| 930 | trigger_guard.Cancel(); | ||
| 931 | return; | ||
| 932 | } | ||
| 933 | if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left && | ||
| 934 | !stick_value.right) { | ||
| 935 | trigger_guard.Cancel(); | ||
| 936 | return; | ||
| 937 | } | ||
| 938 | } | ||
| 939 | |||
| 940 | controller.stick_values[index] = stick_value; | ||
| 941 | controller.stick_values[index].uuid = uuid; | ||
| 942 | |||
| 943 | if (is_configuring) { | ||
| 944 | controller.analog_stick_state.left = {}; | ||
| 945 | controller.analog_stick_state.right = {}; | ||
| 946 | return; | ||
| 947 | } | ||
| 948 | |||
| 949 | const AnalogStickState stick{ | ||
| 950 | .x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX), | ||
| 951 | .y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX), | ||
| 952 | }; | ||
| 953 | |||
| 954 | switch (index) { | ||
| 955 | case Settings::NativeAnalog::LStick: | ||
| 956 | controller.analog_stick_state.left = stick; | ||
| 957 | controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left); | ||
| 958 | controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up); | ||
| 959 | controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right); | ||
| 960 | controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down); | ||
| 961 | break; | ||
| 962 | case Settings::NativeAnalog::RStick: | ||
| 963 | controller.analog_stick_state.right = stick; | ||
| 964 | controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left); | ||
| 965 | controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up); | ||
| 966 | controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right); | ||
| 967 | controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); | ||
| 968 | break; | ||
| 969 | } | ||
| 970 | } | ||
| 971 | |||
| 972 | void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback, | ||
| 973 | std::size_t index, Common::UUID uuid) { | ||
| 974 | if (index >= controller.trigger_values.size()) { | ||
| 975 | return; | ||
| 976 | } | ||
| 977 | auto trigger_guard = | ||
| 978 | SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); }); | ||
| 979 | std::scoped_lock lock{mutex}; | ||
| 980 | const auto trigger_value = TransformToTrigger(callback); | ||
| 981 | |||
| 982 | // Only read trigger values that have the same uuid or are pressed once | ||
| 983 | if (controller.trigger_values[index].uuid != uuid) { | ||
| 984 | if (!trigger_value.pressed.value) { | ||
| 985 | return; | ||
| 986 | } | ||
| 987 | } | ||
| 988 | |||
| 989 | controller.trigger_values[index] = trigger_value; | ||
| 990 | controller.trigger_values[index].uuid = uuid; | ||
| 991 | |||
| 992 | if (is_configuring) { | ||
| 993 | controller.gc_trigger_state.left = 0; | ||
| 994 | controller.gc_trigger_state.right = 0; | ||
| 995 | return; | ||
| 996 | } | ||
| 997 | |||
| 998 | // Only GC controllers have analog triggers | ||
| 999 | if (npad_type != NpadStyleIndex::GameCube) { | ||
| 1000 | trigger_guard.Cancel(); | ||
| 1001 | return; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | const auto& trigger = controller.trigger_values[index]; | ||
| 1005 | |||
| 1006 | switch (index) { | ||
| 1007 | case Settings::NativeTrigger::LTrigger: | ||
| 1008 | controller.gc_trigger_state.left = static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX); | ||
| 1009 | controller.npad_button_state.zl.Assign(trigger.pressed.value); | ||
| 1010 | break; | ||
| 1011 | case Settings::NativeTrigger::RTrigger: | ||
| 1012 | controller.gc_trigger_state.right = | ||
| 1013 | static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX); | ||
| 1014 | controller.npad_button_state.zr.Assign(trigger.pressed.value); | ||
| 1015 | break; | ||
| 1016 | } | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback, | ||
| 1020 | std::size_t index) { | ||
| 1021 | if (index >= controller.motion_values.size()) { | ||
| 1022 | return; | ||
| 1023 | } | ||
| 1024 | SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); }); | ||
| 1025 | std::scoped_lock lock{mutex}; | ||
| 1026 | auto& raw_status = controller.motion_values[index].raw_status; | ||
| 1027 | auto& emulated = controller.motion_values[index].emulated; | ||
| 1028 | |||
| 1029 | raw_status = TransformToMotion(callback); | ||
| 1030 | emulated.SetAcceleration(Common::Vec3f{ | ||
| 1031 | raw_status.accel.x.value, | ||
| 1032 | raw_status.accel.y.value, | ||
| 1033 | raw_status.accel.z.value, | ||
| 1034 | }); | ||
| 1035 | emulated.SetGyroscope(Common::Vec3f{ | ||
| 1036 | raw_status.gyro.x.value, | ||
| 1037 | raw_status.gyro.y.value, | ||
| 1038 | raw_status.gyro.z.value, | ||
| 1039 | }); | ||
| 1040 | emulated.SetUserGyroThreshold(raw_status.gyro.x.properties.threshold); | ||
| 1041 | emulated.UpdateRotation(raw_status.delta_timestamp); | ||
| 1042 | emulated.UpdateOrientation(raw_status.delta_timestamp); | ||
| 1043 | |||
| 1044 | auto& motion = controller.motion_state[index]; | ||
| 1045 | motion.accel = emulated.GetAcceleration(); | ||
| 1046 | motion.gyro = emulated.GetGyroscope(); | ||
| 1047 | motion.rotation = emulated.GetRotations(); | ||
| 1048 | motion.euler = emulated.GetEulerAngles(); | ||
| 1049 | motion.orientation = emulated.GetOrientation(); | ||
| 1050 | motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback, | ||
| 1054 | std::size_t index) { | ||
| 1055 | if (index >= controller.color_values.size()) { | ||
| 1056 | return; | ||
| 1057 | } | ||
| 1058 | auto trigger_guard = | ||
| 1059 | SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); }); | ||
| 1060 | std::scoped_lock lock{mutex}; | ||
| 1061 | controller.color_values[index] = TransformToColor(callback); | ||
| 1062 | |||
| 1063 | if (is_configuring) { | ||
| 1064 | return; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | if (controller.color_values[index].body == 0) { | ||
| 1068 | trigger_guard.Cancel(); | ||
| 1069 | return; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | controller.colors_state.fullkey = { | ||
| 1073 | .body = GetNpadColor(controller.color_values[index].body), | ||
| 1074 | .button = GetNpadColor(controller.color_values[index].buttons), | ||
| 1075 | }; | ||
| 1076 | if (npad_type == NpadStyleIndex::ProController) { | ||
| 1077 | controller.colors_state.left = { | ||
| 1078 | .body = GetNpadColor(controller.color_values[index].left_grip), | ||
| 1079 | .button = GetNpadColor(controller.color_values[index].buttons), | ||
| 1080 | }; | ||
| 1081 | controller.colors_state.right = { | ||
| 1082 | .body = GetNpadColor(controller.color_values[index].right_grip), | ||
| 1083 | .button = GetNpadColor(controller.color_values[index].buttons), | ||
| 1084 | }; | ||
| 1085 | } else { | ||
| 1086 | switch (index) { | ||
| 1087 | case LeftIndex: | ||
| 1088 | controller.colors_state.left = { | ||
| 1089 | .body = GetNpadColor(controller.color_values[index].body), | ||
| 1090 | .button = GetNpadColor(controller.color_values[index].buttons), | ||
| 1091 | }; | ||
| 1092 | break; | ||
| 1093 | case RightIndex: | ||
| 1094 | controller.colors_state.right = { | ||
| 1095 | .body = GetNpadColor(controller.color_values[index].body), | ||
| 1096 | .button = GetNpadColor(controller.color_values[index].buttons), | ||
| 1097 | }; | ||
| 1098 | break; | ||
| 1099 | } | ||
| 1100 | } | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, | ||
| 1104 | std::size_t index) { | ||
| 1105 | if (index >= controller.battery_values.size()) { | ||
| 1106 | return; | ||
| 1107 | } | ||
| 1108 | SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); }); | ||
| 1109 | std::scoped_lock lock{mutex}; | ||
| 1110 | controller.battery_values[index] = TransformToBattery(callback); | ||
| 1111 | |||
| 1112 | if (is_configuring) { | ||
| 1113 | return; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | bool is_charging = false; | ||
| 1117 | bool is_powered = false; | ||
| 1118 | NpadBatteryLevel battery_level = NpadBatteryLevel::Empty; | ||
| 1119 | switch (controller.battery_values[index]) { | ||
| 1120 | case Common::Input::BatteryLevel::Charging: | ||
| 1121 | is_charging = true; | ||
| 1122 | is_powered = true; | ||
| 1123 | battery_level = NpadBatteryLevel::Full; | ||
| 1124 | break; | ||
| 1125 | case Common::Input::BatteryLevel::Medium: | ||
| 1126 | battery_level = NpadBatteryLevel::High; | ||
| 1127 | break; | ||
| 1128 | case Common::Input::BatteryLevel::Low: | ||
| 1129 | battery_level = NpadBatteryLevel::Low; | ||
| 1130 | break; | ||
| 1131 | case Common::Input::BatteryLevel::Critical: | ||
| 1132 | battery_level = NpadBatteryLevel::Critical; | ||
| 1133 | break; | ||
| 1134 | case Common::Input::BatteryLevel::Empty: | ||
| 1135 | battery_level = NpadBatteryLevel::Empty; | ||
| 1136 | break; | ||
| 1137 | case Common::Input::BatteryLevel::None: | ||
| 1138 | case Common::Input::BatteryLevel::Full: | ||
| 1139 | default: | ||
| 1140 | is_powered = true; | ||
| 1141 | battery_level = NpadBatteryLevel::Full; | ||
| 1142 | break; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | switch (index) { | ||
| 1146 | case LeftIndex: | ||
| 1147 | controller.battery_state.left = { | ||
| 1148 | .is_powered = is_powered, | ||
| 1149 | .is_charging = is_charging, | ||
| 1150 | .battery_level = battery_level, | ||
| 1151 | }; | ||
| 1152 | break; | ||
| 1153 | case RightIndex: | ||
| 1154 | controller.battery_state.right = { | ||
| 1155 | .is_powered = is_powered, | ||
| 1156 | .is_charging = is_charging, | ||
| 1157 | .battery_level = battery_level, | ||
| 1158 | }; | ||
| 1159 | break; | ||
| 1160 | case DualIndex: | ||
| 1161 | controller.battery_state.dual = { | ||
| 1162 | .is_powered = is_powered, | ||
| 1163 | .is_charging = is_charging, | ||
| 1164 | .battery_level = battery_level, | ||
| 1165 | }; | ||
| 1166 | break; | ||
| 1167 | } | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) { | ||
| 1171 | SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); }); | ||
| 1172 | std::scoped_lock lock{mutex}; | ||
| 1173 | controller.camera_values = TransformToCamera(callback); | ||
| 1174 | |||
| 1175 | if (is_configuring) { | ||
| 1176 | return; | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | controller.camera_state.sample++; | ||
| 1180 | controller.camera_state.format = | ||
| 1181 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format); | ||
| 1182 | controller.camera_state.data = controller.camera_values.data; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) { | ||
| 1186 | SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); }); | ||
| 1187 | std::scoped_lock lock{mutex}; | ||
| 1188 | const auto force_value = TransformToStick(callback); | ||
| 1189 | |||
| 1190 | controller.ring_analog_value = force_value.x; | ||
| 1191 | |||
| 1192 | if (is_configuring) { | ||
| 1193 | return; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | controller.ring_analog_state.force = force_value.x.value; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { | ||
| 1200 | SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); }); | ||
| 1201 | std::scoped_lock lock{mutex}; | ||
| 1202 | controller.nfc_values = TransformToNfc(callback); | ||
| 1203 | |||
| 1204 | if (is_configuring) { | ||
| 1205 | return; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | controller.nfc_state = controller.nfc_values; | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { | ||
| 1212 | if (!is_initalized) { | ||
| 1213 | return false; | ||
| 1214 | } | ||
| 1215 | if (device_index >= output_devices.size()) { | ||
| 1216 | return false; | ||
| 1217 | } | ||
| 1218 | if (!output_devices[device_index]) { | ||
| 1219 | return false; | ||
| 1220 | } | ||
| 1221 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | ||
| 1222 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 1223 | const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; | ||
| 1224 | |||
| 1225 | if (!player.vibration_enabled) { | ||
| 1226 | return false; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | // Exponential amplification is too strong at low amplitudes. Switch to a linear | ||
| 1230 | // amplification if strength is set below 0.7f | ||
| 1231 | const Common::Input::VibrationAmplificationType type = | ||
| 1232 | strength > 0.7f ? Common::Input::VibrationAmplificationType::Exponential | ||
| 1233 | : Common::Input::VibrationAmplificationType::Linear; | ||
| 1234 | |||
| 1235 | const Common::Input::VibrationStatus status = { | ||
| 1236 | .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), | ||
| 1237 | .low_frequency = vibration.low_frequency, | ||
| 1238 | .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), | ||
| 1239 | .high_frequency = vibration.high_frequency, | ||
| 1240 | .type = type, | ||
| 1241 | }; | ||
| 1242 | return output_devices[device_index]->SetVibration(status) == | ||
| 1243 | Common::Input::DriverResult::Success; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { | ||
| 1247 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | ||
| 1248 | const auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 1249 | |||
| 1250 | if (!is_initalized) { | ||
| 1251 | return false; | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | if (!player.vibration_enabled) { | ||
| 1255 | return false; | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | if (device_index >= output_devices.size()) { | ||
| 1259 | return false; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | if (!output_devices[device_index]) { | ||
| 1263 | return false; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | return output_devices[device_index]->IsVibrationEnabled(); | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | Common::Input::DriverResult EmulatedController::SetPollingMode( | ||
| 1270 | EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) { | ||
| 1271 | LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index); | ||
| 1272 | |||
| 1273 | if (!is_initalized) { | ||
| 1274 | return Common::Input::DriverResult::InvalidHandle; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | auto& left_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Left)]; | ||
| 1278 | auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1279 | auto& nfc_output_device = output_devices[3]; | ||
| 1280 | |||
| 1281 | if (device_index == EmulatedDeviceIndex::LeftIndex) { | ||
| 1282 | controller.left_polling_mode = polling_mode; | ||
| 1283 | return left_output_device->SetPollingMode(polling_mode); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | if (device_index == EmulatedDeviceIndex::RightIndex) { | ||
| 1287 | controller.right_polling_mode = polling_mode; | ||
| 1288 | const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); | ||
| 1289 | const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode); | ||
| 1290 | |||
| 1291 | // Restore previous state | ||
| 1292 | if (mapped_nfc_result != Common::Input::DriverResult::Success) { | ||
| 1293 | right_output_device->SetPollingMode(Common::Input::PollingMode::Active); | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | if (virtual_nfc_result == Common::Input::DriverResult::Success) { | ||
| 1297 | return virtual_nfc_result; | ||
| 1298 | } | ||
| 1299 | return mapped_nfc_result; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | controller.left_polling_mode = polling_mode; | ||
| 1303 | controller.right_polling_mode = polling_mode; | ||
| 1304 | left_output_device->SetPollingMode(polling_mode); | ||
| 1305 | right_output_device->SetPollingMode(polling_mode); | ||
| 1306 | nfc_output_device->SetPollingMode(polling_mode); | ||
| 1307 | return Common::Input::DriverResult::Success; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | Common::Input::PollingMode EmulatedController::GetPollingMode( | ||
| 1311 | EmulatedDeviceIndex device_index) const { | ||
| 1312 | if (device_index == EmulatedDeviceIndex::LeftIndex) { | ||
| 1313 | return controller.left_polling_mode; | ||
| 1314 | } | ||
| 1315 | return controller.right_polling_mode; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | bool EmulatedController::SetCameraFormat( | ||
| 1319 | Core::IrSensor::ImageTransferProcessorFormat camera_format) { | ||
| 1320 | LOG_INFO(Service_HID, "Set camera format {}", camera_format); | ||
| 1321 | |||
| 1322 | if (!is_initalized) { | ||
| 1323 | return false; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1327 | auto& camera_output_device = output_devices[2]; | ||
| 1328 | |||
| 1329 | if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( | ||
| 1330 | camera_format)) == Common::Input::DriverResult::Success) { | ||
| 1331 | return true; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | // Fallback to Qt camera if native device doesn't have support | ||
| 1335 | return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( | ||
| 1336 | camera_format)) == Common::Input::DriverResult::Success; | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | Common::ParamPackage EmulatedController::GetRingParam() const { | ||
| 1340 | return ring_params[0]; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | void EmulatedController::SetRingParam(Common::ParamPackage param) { | ||
| 1344 | ring_params[0] = std::move(param); | ||
| 1345 | ReloadInput(); | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | bool EmulatedController::HasNfc() const { | ||
| 1349 | |||
| 1350 | if (!is_initalized) { | ||
| 1351 | return false; | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | const auto& nfc_output_device = output_devices[3]; | ||
| 1355 | |||
| 1356 | switch (npad_type) { | ||
| 1357 | case NpadStyleIndex::JoyconRight: | ||
| 1358 | case NpadStyleIndex::JoyconDual: | ||
| 1359 | case NpadStyleIndex::ProController: | ||
| 1360 | case NpadStyleIndex::Handheld: | ||
| 1361 | break; | ||
| 1362 | default: | ||
| 1363 | return false; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | const bool has_virtual_nfc = | ||
| 1367 | npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld; | ||
| 1368 | const bool is_virtual_nfc_supported = | ||
| 1369 | nfc_output_device->SupportsNfc() != Common::Input::NfcState::NotSupported; | ||
| 1370 | |||
| 1371 | return is_connected && (has_virtual_nfc && is_virtual_nfc_supported); | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | bool EmulatedController::AddNfcHandle() { | ||
| 1375 | nfc_handles++; | ||
| 1376 | return SetPollingMode(EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::NFC) == | ||
| 1377 | Common::Input::DriverResult::Success; | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | bool EmulatedController::RemoveNfcHandle() { | ||
| 1381 | nfc_handles--; | ||
| 1382 | if (nfc_handles <= 0) { | ||
| 1383 | return SetPollingMode(EmulatedDeviceIndex::RightIndex, | ||
| 1384 | Common::Input::PollingMode::Active) == | ||
| 1385 | Common::Input::DriverResult::Success; | ||
| 1386 | } | ||
| 1387 | return true; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | bool EmulatedController::StartNfcPolling() { | ||
| 1391 | if (!is_initalized) { | ||
| 1392 | return false; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1396 | auto& nfc_virtual_output_device = output_devices[3]; | ||
| 1397 | |||
| 1398 | const auto device_result = nfc_output_device->StartNfcPolling(); | ||
| 1399 | const auto virtual_device_result = nfc_virtual_output_device->StartNfcPolling(); | ||
| 1400 | |||
| 1401 | return device_result == Common::Input::NfcState::Success || | ||
| 1402 | virtual_device_result == Common::Input::NfcState::Success; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | bool EmulatedController::StopNfcPolling() { | ||
| 1406 | if (!is_initalized) { | ||
| 1407 | return false; | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1411 | auto& nfc_virtual_output_device = output_devices[3]; | ||
| 1412 | |||
| 1413 | const auto device_result = nfc_output_device->StopNfcPolling(); | ||
| 1414 | const auto virtual_device_result = nfc_virtual_output_device->StopNfcPolling(); | ||
| 1415 | |||
| 1416 | return device_result == Common::Input::NfcState::Success || | ||
| 1417 | virtual_device_result == Common::Input::NfcState::Success; | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) { | ||
| 1421 | if (!is_initalized) { | ||
| 1422 | return false; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1426 | auto& nfc_virtual_output_device = output_devices[3]; | ||
| 1427 | |||
| 1428 | if (nfc_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success) { | ||
| 1429 | return true; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | return nfc_virtual_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success; | ||
| 1433 | } | ||
| 1434 | |||
| 1435 | bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& request, | ||
| 1436 | Common::Input::MifareRequest& out_data) { | ||
| 1437 | if (!is_initalized) { | ||
| 1438 | return false; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1442 | auto& nfc_virtual_output_device = output_devices[3]; | ||
| 1443 | |||
| 1444 | if (nfc_output_device->ReadMifareData(request, out_data) == Common::Input::NfcState::Success) { | ||
| 1445 | return true; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | return nfc_virtual_output_device->ReadMifareData(request, out_data) == | ||
| 1449 | Common::Input::NfcState::Success; | ||
| 1450 | } | ||
| 1451 | |||
| 1452 | bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& request) { | ||
| 1453 | if (!is_initalized) { | ||
| 1454 | return false; | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1458 | auto& nfc_virtual_output_device = output_devices[3]; | ||
| 1459 | |||
| 1460 | if (nfc_output_device->WriteMifareData(request) == Common::Input::NfcState::Success) { | ||
| 1461 | return true; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | return nfc_virtual_output_device->WriteMifareData(request) == Common::Input::NfcState::Success; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | bool EmulatedController::WriteNfc(const std::vector<u8>& data) { | ||
| 1468 | if (!is_initalized) { | ||
| 1469 | return false; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; | ||
| 1473 | auto& nfc_virtual_output_device = output_devices[3]; | ||
| 1474 | |||
| 1475 | if (nfc_output_device->SupportsNfc() != Common::Input::NfcState::NotSupported) { | ||
| 1476 | return nfc_output_device->WriteNfcData(data) == Common::Input::NfcState::Success; | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | return nfc_virtual_output_device->WriteNfcData(data) == Common::Input::NfcState::Success; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | void EmulatedController::SetLedPattern() { | ||
| 1483 | if (!is_initalized) { | ||
| 1484 | return; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | for (auto& device : output_devices) { | ||
| 1488 | if (!device) { | ||
| 1489 | continue; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | const LedPattern pattern = GetLedPattern(); | ||
| 1493 | const Common::Input::LedStatus status = { | ||
| 1494 | .led_1 = pattern.position1 != 0, | ||
| 1495 | .led_2 = pattern.position2 != 0, | ||
| 1496 | .led_3 = pattern.position3 != 0, | ||
| 1497 | .led_4 = pattern.position4 != 0, | ||
| 1498 | }; | ||
| 1499 | device->SetLED(status); | ||
| 1500 | } | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | void EmulatedController::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode) { | ||
| 1504 | for (auto& motion : controller.motion_values) { | ||
| 1505 | switch (mode) { | ||
| 1506 | case GyroscopeZeroDriftMode::Loose: | ||
| 1507 | motion_sensitivity = motion.emulated.IsAtRestLoose; | ||
| 1508 | motion.emulated.SetGyroThreshold(motion.emulated.ThresholdLoose); | ||
| 1509 | break; | ||
| 1510 | case GyroscopeZeroDriftMode::Tight: | ||
| 1511 | motion_sensitivity = motion.emulated.IsAtRestThight; | ||
| 1512 | motion.emulated.SetGyroThreshold(motion.emulated.ThresholdThight); | ||
| 1513 | break; | ||
| 1514 | case GyroscopeZeroDriftMode::Standard: | ||
| 1515 | default: | ||
| 1516 | motion_sensitivity = motion.emulated.IsAtRestStandard; | ||
| 1517 | motion.emulated.SetGyroThreshold(motion.emulated.ThresholdStandard); | ||
| 1518 | break; | ||
| 1519 | } | ||
| 1520 | } | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) { | ||
| 1524 | supported_style_tag = supported_styles; | ||
| 1525 | if (!is_connected) { | ||
| 1526 | return; | ||
| 1527 | } | ||
| 1528 | |||
| 1529 | // Attempt to reconnect with the original type | ||
| 1530 | if (npad_type != original_npad_type) { | ||
| 1531 | Disconnect(); | ||
| 1532 | const auto current_npad_type = npad_type; | ||
| 1533 | SetNpadStyleIndex(original_npad_type); | ||
| 1534 | if (IsControllerSupported()) { | ||
| 1535 | Connect(); | ||
| 1536 | return; | ||
| 1537 | } | ||
| 1538 | SetNpadStyleIndex(current_npad_type); | ||
| 1539 | Connect(); | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | if (IsControllerSupported()) { | ||
| 1543 | return; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | Disconnect(); | ||
| 1547 | |||
| 1548 | // Fallback Fullkey controllers to Pro controllers | ||
| 1549 | if (IsControllerFullkey() && supported_style_tag.fullkey) { | ||
| 1550 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | ||
| 1551 | SetNpadStyleIndex(NpadStyleIndex::ProController); | ||
| 1552 | Connect(); | ||
| 1553 | return; | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | // Fallback Dual joycon controllers to Pro controllers | ||
| 1557 | if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) { | ||
| 1558 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); | ||
| 1559 | SetNpadStyleIndex(NpadStyleIndex::ProController); | ||
| 1560 | Connect(); | ||
| 1561 | return; | ||
| 1562 | } | ||
| 1563 | |||
| 1564 | // Fallback Pro controllers to Dual joycon | ||
| 1565 | if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) { | ||
| 1566 | LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type); | ||
| 1567 | SetNpadStyleIndex(NpadStyleIndex::JoyconDual); | ||
| 1568 | Connect(); | ||
| 1569 | return; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller", | ||
| 1573 | npad_type); | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { | ||
| 1577 | std::scoped_lock lock{mutex}; | ||
| 1578 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | ||
| 1579 | switch (type) { | ||
| 1580 | case NpadStyleIndex::ProController: | ||
| 1581 | case NpadStyleIndex::GameCube: | ||
| 1582 | case NpadStyleIndex::NES: | ||
| 1583 | case NpadStyleIndex::SNES: | ||
| 1584 | case NpadStyleIndex::N64: | ||
| 1585 | case NpadStyleIndex::SegaGenesis: | ||
| 1586 | return true; | ||
| 1587 | default: | ||
| 1588 | return false; | ||
| 1589 | } | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | bool EmulatedController::IsControllerSupported(bool use_temporary_value) const { | ||
| 1593 | std::scoped_lock lock{mutex}; | ||
| 1594 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | ||
| 1595 | switch (type) { | ||
| 1596 | case NpadStyleIndex::ProController: | ||
| 1597 | return supported_style_tag.fullkey.As<bool>(); | ||
| 1598 | case NpadStyleIndex::Handheld: | ||
| 1599 | return supported_style_tag.handheld.As<bool>(); | ||
| 1600 | case NpadStyleIndex::JoyconDual: | ||
| 1601 | return supported_style_tag.joycon_dual.As<bool>(); | ||
| 1602 | case NpadStyleIndex::JoyconLeft: | ||
| 1603 | return supported_style_tag.joycon_left.As<bool>(); | ||
| 1604 | case NpadStyleIndex::JoyconRight: | ||
| 1605 | return supported_style_tag.joycon_right.As<bool>(); | ||
| 1606 | case NpadStyleIndex::GameCube: | ||
| 1607 | return supported_style_tag.gamecube.As<bool>(); | ||
| 1608 | case NpadStyleIndex::Pokeball: | ||
| 1609 | return supported_style_tag.palma.As<bool>(); | ||
| 1610 | case NpadStyleIndex::NES: | ||
| 1611 | return supported_style_tag.lark.As<bool>(); | ||
| 1612 | case NpadStyleIndex::SNES: | ||
| 1613 | return supported_style_tag.lucia.As<bool>(); | ||
| 1614 | case NpadStyleIndex::N64: | ||
| 1615 | return supported_style_tag.lagoon.As<bool>(); | ||
| 1616 | case NpadStyleIndex::SegaGenesis: | ||
| 1617 | return supported_style_tag.lager.As<bool>(); | ||
| 1618 | default: | ||
| 1619 | return false; | ||
| 1620 | } | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | void EmulatedController::Connect(bool use_temporary_value) { | ||
| 1624 | if (!IsControllerSupported(use_temporary_value)) { | ||
| 1625 | const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; | ||
| 1626 | LOG_ERROR(Service_HID, "Controller type {} is not supported", type); | ||
| 1627 | return; | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | auto trigger_guard = | ||
| 1631 | SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); }); | ||
| 1632 | std::scoped_lock lock{connect_mutex, mutex}; | ||
| 1633 | if (is_configuring) { | ||
| 1634 | tmp_is_connected = true; | ||
| 1635 | return; | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | if (is_connected) { | ||
| 1639 | trigger_guard.Cancel(); | ||
| 1640 | return; | ||
| 1641 | } | ||
| 1642 | is_connected = true; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | void EmulatedController::Disconnect() { | ||
| 1646 | auto trigger_guard = | ||
| 1647 | SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); }); | ||
| 1648 | std::scoped_lock lock{connect_mutex, mutex}; | ||
| 1649 | if (is_configuring) { | ||
| 1650 | tmp_is_connected = false; | ||
| 1651 | return; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | if (!is_connected) { | ||
| 1655 | trigger_guard.Cancel(); | ||
| 1656 | return; | ||
| 1657 | } | ||
| 1658 | is_connected = false; | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | bool EmulatedController::IsConnected(bool get_temporary_value) const { | ||
| 1662 | std::scoped_lock lock{connect_mutex}; | ||
| 1663 | if (get_temporary_value && is_configuring) { | ||
| 1664 | return tmp_is_connected; | ||
| 1665 | } | ||
| 1666 | return is_connected; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | NpadIdType EmulatedController::GetNpadIdType() const { | ||
| 1670 | std::scoped_lock lock{mutex}; | ||
| 1671 | return npad_id_type; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { | ||
| 1675 | std::scoped_lock lock{npad_mutex}; | ||
| 1676 | if (get_temporary_value && is_configuring) { | ||
| 1677 | return tmp_npad_type; | ||
| 1678 | } | ||
| 1679 | return npad_type; | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { | ||
| 1683 | auto trigger_guard = | ||
| 1684 | SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); }); | ||
| 1685 | std::scoped_lock lock{mutex, npad_mutex}; | ||
| 1686 | |||
| 1687 | if (is_configuring) { | ||
| 1688 | if (tmp_npad_type == npad_type_) { | ||
| 1689 | trigger_guard.Cancel(); | ||
| 1690 | return; | ||
| 1691 | } | ||
| 1692 | tmp_npad_type = npad_type_; | ||
| 1693 | return; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | if (npad_type == npad_type_) { | ||
| 1697 | trigger_guard.Cancel(); | ||
| 1698 | return; | ||
| 1699 | } | ||
| 1700 | if (is_connected) { | ||
| 1701 | LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", | ||
| 1702 | Service::HID::NpadIdTypeToIndex(npad_id_type)); | ||
| 1703 | } | ||
| 1704 | npad_type = npad_type_; | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | LedPattern EmulatedController::GetLedPattern() const { | ||
| 1708 | switch (npad_id_type) { | ||
| 1709 | case NpadIdType::Player1: | ||
| 1710 | return LedPattern{1, 0, 0, 0}; | ||
| 1711 | case NpadIdType::Player2: | ||
| 1712 | return LedPattern{1, 1, 0, 0}; | ||
| 1713 | case NpadIdType::Player3: | ||
| 1714 | return LedPattern{1, 1, 1, 0}; | ||
| 1715 | case NpadIdType::Player4: | ||
| 1716 | return LedPattern{1, 1, 1, 1}; | ||
| 1717 | case NpadIdType::Player5: | ||
| 1718 | return LedPattern{1, 0, 0, 1}; | ||
| 1719 | case NpadIdType::Player6: | ||
| 1720 | return LedPattern{1, 0, 1, 0}; | ||
| 1721 | case NpadIdType::Player7: | ||
| 1722 | return LedPattern{1, 0, 1, 1}; | ||
| 1723 | case NpadIdType::Player8: | ||
| 1724 | return LedPattern{0, 1, 1, 0}; | ||
| 1725 | default: | ||
| 1726 | return LedPattern{0, 0, 0, 0}; | ||
| 1727 | } | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | ButtonValues EmulatedController::GetButtonsValues() const { | ||
| 1731 | std::scoped_lock lock{mutex}; | ||
| 1732 | return controller.button_values; | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | SticksValues EmulatedController::GetSticksValues() const { | ||
| 1736 | std::scoped_lock lock{mutex}; | ||
| 1737 | return controller.stick_values; | ||
| 1738 | } | ||
| 1739 | |||
| 1740 | TriggerValues EmulatedController::GetTriggersValues() const { | ||
| 1741 | std::scoped_lock lock{mutex}; | ||
| 1742 | return controller.trigger_values; | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | ControllerMotionValues EmulatedController::GetMotionValues() const { | ||
| 1746 | std::scoped_lock lock{mutex}; | ||
| 1747 | return controller.motion_values; | ||
| 1748 | } | ||
| 1749 | |||
| 1750 | ColorValues EmulatedController::GetColorsValues() const { | ||
| 1751 | std::scoped_lock lock{mutex}; | ||
| 1752 | return controller.color_values; | ||
| 1753 | } | ||
| 1754 | |||
| 1755 | BatteryValues EmulatedController::GetBatteryValues() const { | ||
| 1756 | std::scoped_lock lock{mutex}; | ||
| 1757 | return controller.battery_values; | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | CameraValues EmulatedController::GetCameraValues() const { | ||
| 1761 | std::scoped_lock lock{mutex}; | ||
| 1762 | return controller.camera_values; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | RingAnalogValue EmulatedController::GetRingSensorValues() const { | ||
| 1766 | return controller.ring_analog_value; | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | HomeButtonState EmulatedController::GetHomeButtons() const { | ||
| 1770 | std::scoped_lock lock{mutex}; | ||
| 1771 | if (is_configuring) { | ||
| 1772 | return {}; | ||
| 1773 | } | ||
| 1774 | return controller.home_button_state; | ||
| 1775 | } | ||
| 1776 | |||
| 1777 | CaptureButtonState EmulatedController::GetCaptureButtons() const { | ||
| 1778 | std::scoped_lock lock{mutex}; | ||
| 1779 | if (is_configuring) { | ||
| 1780 | return {}; | ||
| 1781 | } | ||
| 1782 | return controller.capture_button_state; | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | NpadButtonState EmulatedController::GetNpadButtons() const { | ||
| 1786 | std::scoped_lock lock{mutex}; | ||
| 1787 | if (is_configuring) { | ||
| 1788 | return {}; | ||
| 1789 | } | ||
| 1790 | return {controller.npad_button_state.raw & GetTurboButtonMask()}; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | DebugPadButton EmulatedController::GetDebugPadButtons() const { | ||
| 1794 | std::scoped_lock lock{mutex}; | ||
| 1795 | if (is_configuring) { | ||
| 1796 | return {}; | ||
| 1797 | } | ||
| 1798 | return controller.debug_pad_button_state; | ||
| 1799 | } | ||
| 1800 | |||
| 1801 | AnalogSticks EmulatedController::GetSticks() const { | ||
| 1802 | std::scoped_lock lock{mutex}; | ||
| 1803 | |||
| 1804 | if (is_configuring) { | ||
| 1805 | return {}; | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | return controller.analog_stick_state; | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | NpadGcTriggerState EmulatedController::GetTriggers() const { | ||
| 1812 | std::scoped_lock lock{mutex}; | ||
| 1813 | if (is_configuring) { | ||
| 1814 | return {}; | ||
| 1815 | } | ||
| 1816 | return controller.gc_trigger_state; | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | MotionState EmulatedController::GetMotions() const { | ||
| 1820 | std::unique_lock lock{mutex}; | ||
| 1821 | return controller.motion_state; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | ControllerColors EmulatedController::GetColors() const { | ||
| 1825 | std::scoped_lock lock{mutex}; | ||
| 1826 | return controller.colors_state; | ||
| 1827 | } | ||
| 1828 | |||
| 1829 | BatteryLevelState EmulatedController::GetBattery() const { | ||
| 1830 | std::scoped_lock lock{mutex}; | ||
| 1831 | return controller.battery_state; | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | const CameraState& EmulatedController::GetCamera() const { | ||
| 1835 | std::scoped_lock lock{mutex}; | ||
| 1836 | return controller.camera_state; | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | RingSensorForce EmulatedController::GetRingSensorForce() const { | ||
| 1840 | return controller.ring_analog_state; | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | const NfcState& EmulatedController::GetNfc() const { | ||
| 1844 | std::scoped_lock lock{mutex}; | ||
| 1845 | return controller.nfc_state; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | NpadColor EmulatedController::GetNpadColor(u32 color) { | ||
| 1849 | return { | ||
| 1850 | .r = static_cast<u8>((color >> 16) & 0xFF), | ||
| 1851 | .g = static_cast<u8>((color >> 8) & 0xFF), | ||
| 1852 | .b = static_cast<u8>(color & 0xFF), | ||
| 1853 | .a = 0xff, | ||
| 1854 | }; | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { | ||
| 1858 | std::scoped_lock lock{callback_mutex}; | ||
| 1859 | for (const auto& poller_pair : callback_list) { | ||
| 1860 | const ControllerUpdateCallback& poller = poller_pair.second; | ||
| 1861 | if (!is_npad_service_update && poller.is_npad_service) { | ||
| 1862 | continue; | ||
| 1863 | } | ||
| 1864 | if (poller.on_change) { | ||
| 1865 | poller.on_change(type); | ||
| 1866 | } | ||
| 1867 | } | ||
| 1868 | } | ||
| 1869 | |||
| 1870 | int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { | ||
| 1871 | std::scoped_lock lock{callback_mutex}; | ||
| 1872 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); | ||
| 1873 | return last_callback_key++; | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | void EmulatedController::DeleteCallback(int key) { | ||
| 1877 | std::scoped_lock lock{callback_mutex}; | ||
| 1878 | const auto& iterator = callback_list.find(key); | ||
| 1879 | if (iterator == callback_list.end()) { | ||
| 1880 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | ||
| 1881 | return; | ||
| 1882 | } | ||
| 1883 | callback_list.erase(iterator); | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | void EmulatedController::StatusUpdate() { | ||
| 1887 | turbo_button_state = (turbo_button_state + 1) % (TURBO_BUTTON_DELAY * 2); | ||
| 1888 | |||
| 1889 | // Some drivers like key motion need constant refreshing | ||
| 1890 | for (std::size_t index = 0; index < motion_devices.size(); ++index) { | ||
| 1891 | const auto& raw_status = controller.motion_values[index].raw_status; | ||
| 1892 | auto& device = motion_devices[index]; | ||
| 1893 | if (!raw_status.force_update) { | ||
| 1894 | continue; | ||
| 1895 | } | ||
| 1896 | if (!device) { | ||
| 1897 | continue; | ||
| 1898 | } | ||
| 1899 | device->ForceUpdate(); | ||
| 1900 | } | ||
| 1901 | } | ||
| 1902 | |||
| 1903 | NpadButton EmulatedController::GetTurboButtonMask() const { | ||
| 1904 | // Apply no mask when disabled | ||
| 1905 | if (turbo_button_state < TURBO_BUTTON_DELAY) { | ||
| 1906 | return {NpadButton::All}; | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | NpadButtonState button_mask{}; | ||
| 1910 | for (std::size_t index = 0; index < controller.button_values.size(); ++index) { | ||
| 1911 | if (!controller.button_values[index].turbo) { | ||
| 1912 | continue; | ||
| 1913 | } | ||
| 1914 | |||
| 1915 | switch (index) { | ||
| 1916 | case Settings::NativeButton::A: | ||
| 1917 | button_mask.a.Assign(1); | ||
| 1918 | break; | ||
| 1919 | case Settings::NativeButton::B: | ||
| 1920 | button_mask.b.Assign(1); | ||
| 1921 | break; | ||
| 1922 | case Settings::NativeButton::X: | ||
| 1923 | button_mask.x.Assign(1); | ||
| 1924 | break; | ||
| 1925 | case Settings::NativeButton::Y: | ||
| 1926 | button_mask.y.Assign(1); | ||
| 1927 | break; | ||
| 1928 | case Settings::NativeButton::L: | ||
| 1929 | button_mask.l.Assign(1); | ||
| 1930 | break; | ||
| 1931 | case Settings::NativeButton::R: | ||
| 1932 | button_mask.r.Assign(1); | ||
| 1933 | break; | ||
| 1934 | case Settings::NativeButton::ZL: | ||
| 1935 | button_mask.zl.Assign(1); | ||
| 1936 | break; | ||
| 1937 | case Settings::NativeButton::ZR: | ||
| 1938 | button_mask.zr.Assign(1); | ||
| 1939 | break; | ||
| 1940 | case Settings::NativeButton::DLeft: | ||
| 1941 | button_mask.left.Assign(1); | ||
| 1942 | break; | ||
| 1943 | case Settings::NativeButton::DUp: | ||
| 1944 | button_mask.up.Assign(1); | ||
| 1945 | break; | ||
| 1946 | case Settings::NativeButton::DRight: | ||
| 1947 | button_mask.right.Assign(1); | ||
| 1948 | break; | ||
| 1949 | case Settings::NativeButton::DDown: | ||
| 1950 | button_mask.down.Assign(1); | ||
| 1951 | break; | ||
| 1952 | case Settings::NativeButton::SLLeft: | ||
| 1953 | button_mask.left_sl.Assign(1); | ||
| 1954 | break; | ||
| 1955 | case Settings::NativeButton::SLRight: | ||
| 1956 | button_mask.right_sl.Assign(1); | ||
| 1957 | break; | ||
| 1958 | case Settings::NativeButton::SRLeft: | ||
| 1959 | button_mask.left_sr.Assign(1); | ||
| 1960 | break; | ||
| 1961 | case Settings::NativeButton::SRRight: | ||
| 1962 | button_mask.right_sr.Assign(1); | ||
| 1963 | break; | ||
| 1964 | default: | ||
| 1965 | break; | ||
| 1966 | } | ||
| 1967 | } | ||
| 1968 | |||
| 1969 | return static_cast<NpadButton>(~button_mask.raw); | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | } // namespace Core::HID | ||
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h deleted file mode 100644 index d6e20ab66..000000000 --- a/src/core/hid/emulated_controller.h +++ /dev/null | |||
| @@ -1,619 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <functional> | ||
| 8 | #include <memory> | ||
| 9 | #include <mutex> | ||
| 10 | #include <unordered_map> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "common/input.h" | ||
| 15 | #include "common/param_package.h" | ||
| 16 | #include "common/settings.h" | ||
| 17 | #include "common/vector_math.h" | ||
| 18 | #include "core/hid/hid_types.h" | ||
| 19 | #include "core/hid/irs_types.h" | ||
| 20 | #include "core/hid/motion_input.h" | ||
| 21 | |||
| 22 | namespace Core::HID { | ||
| 23 | const std::size_t max_emulated_controllers = 2; | ||
| 24 | const std::size_t output_devices_size = 4; | ||
| 25 | struct ControllerMotionInfo { | ||
| 26 | Common::Input::MotionStatus raw_status{}; | ||
| 27 | MotionInput emulated{}; | ||
| 28 | }; | ||
| 29 | |||
| 30 | using ButtonDevices = | ||
| 31 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeButton::NumButtons>; | ||
| 32 | using StickDevices = | ||
| 33 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>; | ||
| 34 | using ControllerMotionDevices = | ||
| 35 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>; | ||
| 36 | using TriggerDevices = | ||
| 37 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>; | ||
| 38 | using ColorDevices = | ||
| 39 | std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; | ||
| 40 | using BatteryDevices = | ||
| 41 | std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; | ||
| 42 | using CameraDevices = | ||
| 43 | std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; | ||
| 44 | using RingAnalogDevices = | ||
| 45 | std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; | ||
| 46 | using NfcDevices = | ||
| 47 | std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; | ||
| 48 | using OutputDevices = std::array<std::unique_ptr<Common::Input::OutputDevice>, output_devices_size>; | ||
| 49 | |||
| 50 | using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>; | ||
| 51 | using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>; | ||
| 52 | using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>; | ||
| 53 | using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>; | ||
| 54 | using ColorParams = std::array<Common::ParamPackage, max_emulated_controllers>; | ||
| 55 | using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>; | ||
| 56 | using CameraParams = std::array<Common::ParamPackage, max_emulated_controllers>; | ||
| 57 | using RingAnalogParams = std::array<Common::ParamPackage, max_emulated_controllers>; | ||
| 58 | using NfcParams = std::array<Common::ParamPackage, max_emulated_controllers>; | ||
| 59 | using OutputParams = std::array<Common::ParamPackage, output_devices_size>; | ||
| 60 | |||
| 61 | using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>; | ||
| 62 | using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>; | ||
| 63 | using TriggerValues = | ||
| 64 | std::array<Common::Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>; | ||
| 65 | using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>; | ||
| 66 | using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>; | ||
| 67 | using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>; | ||
| 68 | using CameraValues = Common::Input::CameraStatus; | ||
| 69 | using RingAnalogValue = Common::Input::AnalogStatus; | ||
| 70 | using NfcValues = Common::Input::NfcStatus; | ||
| 71 | using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>; | ||
| 72 | |||
| 73 | struct AnalogSticks { | ||
| 74 | AnalogStickState left{}; | ||
| 75 | AnalogStickState right{}; | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct ControllerColors { | ||
| 79 | NpadControllerColor fullkey{}; | ||
| 80 | NpadControllerColor left{}; | ||
| 81 | NpadControllerColor right{}; | ||
| 82 | }; | ||
| 83 | |||
| 84 | struct BatteryLevelState { | ||
| 85 | NpadPowerInfo dual{}; | ||
| 86 | NpadPowerInfo left{}; | ||
| 87 | NpadPowerInfo right{}; | ||
| 88 | }; | ||
| 89 | |||
| 90 | struct CameraState { | ||
| 91 | Core::IrSensor::ImageTransferProcessorFormat format{}; | ||
| 92 | std::vector<u8> data{}; | ||
| 93 | std::size_t sample{}; | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct RingSensorForce { | ||
| 97 | f32 force; | ||
| 98 | }; | ||
| 99 | |||
| 100 | using NfcState = Common::Input::NfcStatus; | ||
| 101 | |||
| 102 | struct ControllerMotion { | ||
| 103 | Common::Vec3f accel{}; | ||
| 104 | Common::Vec3f gyro{}; | ||
| 105 | Common::Vec3f rotation{}; | ||
| 106 | Common::Vec3f euler{}; | ||
| 107 | std::array<Common::Vec3f, 3> orientation{}; | ||
| 108 | bool is_at_rest{}; | ||
| 109 | }; | ||
| 110 | |||
| 111 | enum EmulatedDeviceIndex : u8 { | ||
| 112 | LeftIndex, | ||
| 113 | RightIndex, | ||
| 114 | DualIndex, | ||
| 115 | AllDevices, | ||
| 116 | }; | ||
| 117 | |||
| 118 | using MotionState = std::array<ControllerMotion, 2>; | ||
| 119 | |||
| 120 | struct ControllerStatus { | ||
| 121 | // Data from input_common | ||
| 122 | ButtonValues button_values{}; | ||
| 123 | SticksValues stick_values{}; | ||
| 124 | ControllerMotionValues motion_values{}; | ||
| 125 | TriggerValues trigger_values{}; | ||
| 126 | ColorValues color_values{}; | ||
| 127 | BatteryValues battery_values{}; | ||
| 128 | VibrationValues vibration_values{}; | ||
| 129 | CameraValues camera_values{}; | ||
| 130 | RingAnalogValue ring_analog_value{}; | ||
| 131 | NfcValues nfc_values{}; | ||
| 132 | |||
| 133 | // Data for HID services | ||
| 134 | HomeButtonState home_button_state{}; | ||
| 135 | CaptureButtonState capture_button_state{}; | ||
| 136 | NpadButtonState npad_button_state{}; | ||
| 137 | DebugPadButton debug_pad_button_state{}; | ||
| 138 | AnalogSticks analog_stick_state{}; | ||
| 139 | MotionState motion_state{}; | ||
| 140 | NpadGcTriggerState gc_trigger_state{}; | ||
| 141 | ControllerColors colors_state{}; | ||
| 142 | BatteryLevelState battery_state{}; | ||
| 143 | CameraState camera_state{}; | ||
| 144 | RingSensorForce ring_analog_state{}; | ||
| 145 | NfcState nfc_state{}; | ||
| 146 | Common::Input::PollingMode left_polling_mode{}; | ||
| 147 | Common::Input::PollingMode right_polling_mode{}; | ||
| 148 | }; | ||
| 149 | |||
| 150 | enum class ControllerTriggerType { | ||
| 151 | Button, | ||
| 152 | Stick, | ||
| 153 | Trigger, | ||
| 154 | Motion, | ||
| 155 | Color, | ||
| 156 | Battery, | ||
| 157 | Vibration, | ||
| 158 | IrSensor, | ||
| 159 | RingController, | ||
| 160 | Nfc, | ||
| 161 | Connected, | ||
| 162 | Disconnected, | ||
| 163 | Type, | ||
| 164 | All, | ||
| 165 | }; | ||
| 166 | |||
| 167 | struct ControllerUpdateCallback { | ||
| 168 | std::function<void(ControllerTriggerType)> on_change; | ||
| 169 | bool is_npad_service; | ||
| 170 | }; | ||
| 171 | |||
| 172 | class EmulatedController { | ||
| 173 | public: | ||
| 174 | /** | ||
| 175 | * Contains all input data (buttons, joysticks, vibration, and motion) within this controller. | ||
| 176 | * @param npad_id_type npad id type for this specific controller | ||
| 177 | */ | ||
| 178 | explicit EmulatedController(NpadIdType npad_id_type_); | ||
| 179 | ~EmulatedController(); | ||
| 180 | |||
| 181 | YUZU_NON_COPYABLE(EmulatedController); | ||
| 182 | YUZU_NON_MOVEABLE(EmulatedController); | ||
| 183 | |||
| 184 | /// Converts the controller type from settings to npad type | ||
| 185 | static NpadStyleIndex MapSettingsTypeToNPad(Settings::ControllerType type); | ||
| 186 | |||
| 187 | /// Converts npad type to the equivalent of controller type from settings | ||
| 188 | static Settings::ControllerType MapNPadToSettingsType(NpadStyleIndex type); | ||
| 189 | |||
| 190 | /// Gets the NpadIdType for this controller | ||
| 191 | NpadIdType GetNpadIdType() const; | ||
| 192 | |||
| 193 | /// Sets the NpadStyleIndex for this controller | ||
| 194 | void SetNpadStyleIndex(NpadStyleIndex npad_type_); | ||
| 195 | |||
| 196 | /** | ||
| 197 | * Gets the NpadStyleIndex for this controller | ||
| 198 | * @param get_temporary_value If true tmp_npad_type will be returned | ||
| 199 | * @return NpadStyleIndex set on the controller | ||
| 200 | */ | ||
| 201 | NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; | ||
| 202 | |||
| 203 | /** | ||
| 204 | * Sets the supported controller types. Disconnects the controller if current type is not | ||
| 205 | * supported | ||
| 206 | * @param supported_styles bitflag with supported types | ||
| 207 | */ | ||
| 208 | void SetSupportedNpadStyleTag(NpadStyleTag supported_styles); | ||
| 209 | |||
| 210 | /** | ||
| 211 | * Sets the connected status to true | ||
| 212 | * @param use_temporary_value If true tmp_npad_type will be used | ||
| 213 | */ | ||
| 214 | void Connect(bool use_temporary_value = false); | ||
| 215 | |||
| 216 | /// Sets the connected status to false | ||
| 217 | void Disconnect(); | ||
| 218 | |||
| 219 | /** | ||
| 220 | * Is the emulated connected | ||
| 221 | * @param get_temporary_value If true tmp_is_connected will be returned | ||
| 222 | * @return true if the controller has the connected status | ||
| 223 | */ | ||
| 224 | bool IsConnected(bool get_temporary_value = false) const; | ||
| 225 | |||
| 226 | /// Removes all callbacks created from input devices | ||
| 227 | void UnloadInput(); | ||
| 228 | |||
| 229 | /** | ||
| 230 | * Sets the emulated controller into configuring mode | ||
| 231 | * This prevents the modification of the HID state of the emulated controller by input commands | ||
| 232 | */ | ||
| 233 | void EnableConfiguration(); | ||
| 234 | |||
| 235 | /// Returns the emulated controller into normal mode, allowing the modification of the HID state | ||
| 236 | void DisableConfiguration(); | ||
| 237 | |||
| 238 | /// Enables Home and Screenshot buttons | ||
| 239 | void EnableSystemButtons(); | ||
| 240 | |||
| 241 | /// Disables Home and Screenshot buttons | ||
| 242 | void DisableSystemButtons(); | ||
| 243 | |||
| 244 | /// Sets Home and Screenshot buttons to false | ||
| 245 | void ResetSystemButtons(); | ||
| 246 | |||
| 247 | /// Returns true if the emulated controller is in configuring mode | ||
| 248 | bool IsConfiguring() const; | ||
| 249 | |||
| 250 | /// Reload all input devices | ||
| 251 | void ReloadInput(); | ||
| 252 | |||
| 253 | /// Overrides current mapped devices with the stored configuration and reloads all input devices | ||
| 254 | void ReloadFromSettings(); | ||
| 255 | |||
| 256 | /// Updates current colors with the ones stored in the configuration | ||
| 257 | void ReloadColorsFromSettings(); | ||
| 258 | |||
| 259 | /// Saves the current mapped configuration | ||
| 260 | void SaveCurrentConfig(); | ||
| 261 | |||
| 262 | /// Reverts any mapped changes made that weren't saved | ||
| 263 | void RestoreConfig(); | ||
| 264 | |||
| 265 | /// Returns a vector of mapped devices from the mapped button and stick parameters | ||
| 266 | std::vector<Common::ParamPackage> GetMappedDevices() const; | ||
| 267 | |||
| 268 | // Returns the current mapped button device | ||
| 269 | Common::ParamPackage GetButtonParam(std::size_t index) const; | ||
| 270 | |||
| 271 | // Returns the current mapped stick device | ||
| 272 | Common::ParamPackage GetStickParam(std::size_t index) const; | ||
| 273 | |||
| 274 | // Returns the current mapped motion device | ||
| 275 | Common::ParamPackage GetMotionParam(std::size_t index) const; | ||
| 276 | |||
| 277 | /** | ||
| 278 | * Updates the current mapped button device | ||
| 279 | * @param param ParamPackage with controller data to be mapped | ||
| 280 | */ | ||
| 281 | void SetButtonParam(std::size_t index, Common::ParamPackage param); | ||
| 282 | |||
| 283 | /** | ||
| 284 | * Updates the current mapped stick device | ||
| 285 | * @param param ParamPackage with controller data to be mapped | ||
| 286 | */ | ||
| 287 | void SetStickParam(std::size_t index, Common::ParamPackage param); | ||
| 288 | |||
| 289 | /** | ||
| 290 | * Updates the current mapped motion device | ||
| 291 | * @param param ParamPackage with controller data to be mapped | ||
| 292 | */ | ||
| 293 | void SetMotionParam(std::size_t index, Common::ParamPackage param); | ||
| 294 | |||
| 295 | /// Auto calibrates the current motion devices | ||
| 296 | void StartMotionCalibration(); | ||
| 297 | |||
| 298 | /// Returns the latest button status from the controller with parameters | ||
| 299 | ButtonValues GetButtonsValues() const; | ||
| 300 | |||
| 301 | /// Returns the latest analog stick status from the controller with parameters | ||
| 302 | SticksValues GetSticksValues() const; | ||
| 303 | |||
| 304 | /// Returns the latest trigger status from the controller with parameters | ||
| 305 | TriggerValues GetTriggersValues() const; | ||
| 306 | |||
| 307 | /// Returns the latest motion status from the controller with parameters | ||
| 308 | ControllerMotionValues GetMotionValues() const; | ||
| 309 | |||
| 310 | /// Returns the latest color status from the controller with parameters | ||
| 311 | ColorValues GetColorsValues() const; | ||
| 312 | |||
| 313 | /// Returns the latest battery status from the controller with parameters | ||
| 314 | BatteryValues GetBatteryValues() const; | ||
| 315 | |||
| 316 | /// Returns the latest camera status from the controller with parameters | ||
| 317 | CameraValues GetCameraValues() const; | ||
| 318 | |||
| 319 | /// Returns the latest status of analog input from the ring sensor with parameters | ||
| 320 | RingAnalogValue GetRingSensorValues() const; | ||
| 321 | |||
| 322 | /// Returns the latest status of button input for the hid::HomeButton service | ||
| 323 | HomeButtonState GetHomeButtons() const; | ||
| 324 | |||
| 325 | /// Returns the latest status of button input for the hid::CaptureButton service | ||
| 326 | CaptureButtonState GetCaptureButtons() const; | ||
| 327 | |||
| 328 | /// Returns the latest status of button input for the hid::Npad service | ||
| 329 | NpadButtonState GetNpadButtons() const; | ||
| 330 | |||
| 331 | /// Returns the latest status of button input for the debug pad service | ||
| 332 | DebugPadButton GetDebugPadButtons() const; | ||
| 333 | |||
| 334 | /// Returns the latest status of stick input from the mouse | ||
| 335 | AnalogSticks GetSticks() const; | ||
| 336 | |||
| 337 | /// Returns the latest status of trigger input from the mouse | ||
| 338 | NpadGcTriggerState GetTriggers() const; | ||
| 339 | |||
| 340 | /// Returns the latest status of motion input from the mouse | ||
| 341 | MotionState GetMotions() const; | ||
| 342 | |||
| 343 | /// Returns the latest color value from the controller | ||
| 344 | ControllerColors GetColors() const; | ||
| 345 | |||
| 346 | /// Returns the latest battery status from the controller | ||
| 347 | BatteryLevelState GetBattery() const; | ||
| 348 | |||
| 349 | /// Returns the latest camera status from the controller | ||
| 350 | const CameraState& GetCamera() const; | ||
| 351 | |||
| 352 | /// Returns the latest ringcon force sensor value | ||
| 353 | RingSensorForce GetRingSensorForce() const; | ||
| 354 | |||
| 355 | /// Returns the latest ntag status from the controller | ||
| 356 | const NfcState& GetNfc() const; | ||
| 357 | |||
| 358 | /** | ||
| 359 | * Sends a specific vibration to the output device | ||
| 360 | * @return true if vibration had no errors | ||
| 361 | */ | ||
| 362 | bool SetVibration(std::size_t device_index, VibrationValue vibration); | ||
| 363 | |||
| 364 | /** | ||
| 365 | * Sends a small vibration to the output device | ||
| 366 | * @return true if SetVibration was successful | ||
| 367 | */ | ||
| 368 | bool IsVibrationEnabled(std::size_t device_index); | ||
| 369 | |||
| 370 | /** | ||
| 371 | * Sets the desired data to be polled from a controller | ||
| 372 | * @param device_index index of the controller to set the polling mode | ||
| 373 | * @param polling_mode type of input desired buttons, gyro, nfc, ir, etc. | ||
| 374 | * @return driver result from this command | ||
| 375 | */ | ||
| 376 | Common::Input::DriverResult SetPollingMode(EmulatedDeviceIndex device_index, | ||
| 377 | Common::Input::PollingMode polling_mode); | ||
| 378 | /** | ||
| 379 | * Get the current polling mode from a controller | ||
| 380 | * @param device_index index of the controller to set the polling mode | ||
| 381 | * @return current polling mode | ||
| 382 | */ | ||
| 383 | Common::Input::PollingMode GetPollingMode(EmulatedDeviceIndex device_index) const; | ||
| 384 | |||
| 385 | /** | ||
| 386 | * Sets the desired camera format to be polled from a controller | ||
| 387 | * @param camera_format size of each frame | ||
| 388 | * @return true if SetCameraFormat was successful | ||
| 389 | */ | ||
| 390 | bool SetCameraFormat(Core::IrSensor::ImageTransferProcessorFormat camera_format); | ||
| 391 | |||
| 392 | // Returns the current mapped ring device | ||
| 393 | Common::ParamPackage GetRingParam() const; | ||
| 394 | |||
| 395 | /** | ||
| 396 | * Updates the current mapped ring device | ||
| 397 | * @param param ParamPackage with ring sensor data to be mapped | ||
| 398 | */ | ||
| 399 | void SetRingParam(Common::ParamPackage param); | ||
| 400 | |||
| 401 | /// Returns true if the device has nfc support | ||
| 402 | bool HasNfc() const; | ||
| 403 | |||
| 404 | /// Sets the joycon in nfc mode and increments the handle count | ||
| 405 | bool AddNfcHandle(); | ||
| 406 | |||
| 407 | /// Decrements the handle count if zero sets the joycon in active mode | ||
| 408 | bool RemoveNfcHandle(); | ||
| 409 | |||
| 410 | /// Start searching for nfc tags | ||
| 411 | bool StartNfcPolling(); | ||
| 412 | |||
| 413 | /// Stop searching for nfc tags | ||
| 414 | bool StopNfcPolling(); | ||
| 415 | |||
| 416 | /// Returns true if the nfc tag was readable | ||
| 417 | bool ReadAmiiboData(std::vector<u8>& data); | ||
| 418 | |||
| 419 | /// Returns true if the nfc tag was written | ||
| 420 | bool WriteNfc(const std::vector<u8>& data); | ||
| 421 | |||
| 422 | /// Returns true if the nfc tag was readable | ||
| 423 | bool ReadMifareData(const Common::Input::MifareRequest& request, | ||
| 424 | Common::Input::MifareRequest& out_data); | ||
| 425 | |||
| 426 | /// Returns true if the nfc tag was written | ||
| 427 | bool WriteMifareData(const Common::Input::MifareRequest& request); | ||
| 428 | |||
| 429 | /// Returns the led pattern corresponding to this emulated controller | ||
| 430 | LedPattern GetLedPattern() const; | ||
| 431 | |||
| 432 | /// Asks the output device to change the player led pattern | ||
| 433 | void SetLedPattern(); | ||
| 434 | |||
| 435 | /// Changes sensitivity of the motion sensor | ||
| 436 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode); | ||
| 437 | |||
| 438 | /** | ||
| 439 | * Adds a callback to the list of events | ||
| 440 | * @param update_callback A ConsoleUpdateCallback that will be triggered | ||
| 441 | * @return an unique key corresponding to the callback index in the list | ||
| 442 | */ | ||
| 443 | int SetCallback(ControllerUpdateCallback update_callback); | ||
| 444 | |||
| 445 | /** | ||
| 446 | * Removes a callback from the list stopping any future events to this object | ||
| 447 | * @param key Key corresponding to the callback index in the list | ||
| 448 | */ | ||
| 449 | void DeleteCallback(int key); | ||
| 450 | |||
| 451 | /// Swaps the state of the turbo buttons and updates motion input | ||
| 452 | void StatusUpdate(); | ||
| 453 | |||
| 454 | private: | ||
| 455 | /// creates input devices from params | ||
| 456 | void LoadDevices(); | ||
| 457 | |||
| 458 | /// Set the params for TAS devices | ||
| 459 | void LoadTASParams(); | ||
| 460 | |||
| 461 | /// Set the params for virtual pad devices | ||
| 462 | void LoadVirtualGamepadParams(); | ||
| 463 | |||
| 464 | /** | ||
| 465 | * @param use_temporary_value If true tmp_npad_type will be used | ||
| 466 | * @return true if the controller style is fullkey | ||
| 467 | */ | ||
| 468 | bool IsControllerFullkey(bool use_temporary_value = false) const; | ||
| 469 | |||
| 470 | /** | ||
| 471 | * Checks the current controller type against the supported_style_tag | ||
| 472 | * @param use_temporary_value If true tmp_npad_type will be used | ||
| 473 | * @return true if the controller is supported | ||
| 474 | */ | ||
| 475 | bool IsControllerSupported(bool use_temporary_value = false) const; | ||
| 476 | |||
| 477 | /** | ||
| 478 | * Updates the button status of the controller | ||
| 479 | * @param callback A CallbackStatus containing the button status | ||
| 480 | * @param index Button ID of the to be updated | ||
| 481 | */ | ||
| 482 | void SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 483 | Common::UUID uuid); | ||
| 484 | |||
| 485 | /** | ||
| 486 | * Updates the analog stick status of the controller | ||
| 487 | * @param callback A CallbackStatus containing the analog stick status | ||
| 488 | * @param index stick ID of the to be updated | ||
| 489 | */ | ||
| 490 | void SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 491 | Common::UUID uuid); | ||
| 492 | |||
| 493 | /** | ||
| 494 | * Updates the trigger status of the controller | ||
| 495 | * @param callback A CallbackStatus containing the trigger status | ||
| 496 | * @param index trigger ID of the to be updated | ||
| 497 | */ | ||
| 498 | void SetTrigger(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 499 | Common::UUID uuid); | ||
| 500 | |||
| 501 | /** | ||
| 502 | * Updates the motion status of the controller | ||
| 503 | * @param callback A CallbackStatus containing gyro and accelerometer data | ||
| 504 | * @param index motion ID of the to be updated | ||
| 505 | */ | ||
| 506 | void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 507 | |||
| 508 | /** | ||
| 509 | * Updates the color status of the controller | ||
| 510 | * @param callback A CallbackStatus containing the color status | ||
| 511 | * @param index color ID of the to be updated | ||
| 512 | */ | ||
| 513 | void SetColors(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 514 | |||
| 515 | /** | ||
| 516 | * Updates the battery status of the controller | ||
| 517 | * @param callback A CallbackStatus containing the battery status | ||
| 518 | * @param index battery ID of the to be updated | ||
| 519 | */ | ||
| 520 | void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 521 | |||
| 522 | /** | ||
| 523 | * Updates the camera status of the controller | ||
| 524 | * @param callback A CallbackStatus containing the camera status | ||
| 525 | */ | ||
| 526 | void SetCamera(const Common::Input::CallbackStatus& callback); | ||
| 527 | |||
| 528 | /** | ||
| 529 | * Updates the ring analog sensor status of the ring controller | ||
| 530 | * @param callback A CallbackStatus containing the force status | ||
| 531 | */ | ||
| 532 | void SetRingAnalog(const Common::Input::CallbackStatus& callback); | ||
| 533 | |||
| 534 | /** | ||
| 535 | * Updates the nfc status of the controller | ||
| 536 | * @param callback A CallbackStatus containing the nfc status | ||
| 537 | */ | ||
| 538 | void SetNfc(const Common::Input::CallbackStatus& callback); | ||
| 539 | |||
| 540 | /** | ||
| 541 | * Converts a color format from bgra to rgba | ||
| 542 | * @param color in bgra format | ||
| 543 | * @return NpadColor in rgba format | ||
| 544 | */ | ||
| 545 | NpadColor GetNpadColor(u32 color); | ||
| 546 | |||
| 547 | /** | ||
| 548 | * Triggers a callback that something has changed on the controller status | ||
| 549 | * @param type Input type of the event to trigger | ||
| 550 | * @param is_service_update indicates if this event should only be sent to HID services | ||
| 551 | */ | ||
| 552 | void TriggerOnChange(ControllerTriggerType type, bool is_service_update); | ||
| 553 | |||
| 554 | NpadButton GetTurboButtonMask() const; | ||
| 555 | |||
| 556 | const NpadIdType npad_id_type; | ||
| 557 | NpadStyleIndex npad_type{NpadStyleIndex::None}; | ||
| 558 | NpadStyleIndex original_npad_type{NpadStyleIndex::None}; | ||
| 559 | NpadStyleTag supported_style_tag{NpadStyleSet::All}; | ||
| 560 | bool is_connected{false}; | ||
| 561 | bool is_configuring{false}; | ||
| 562 | bool is_initalized{false}; | ||
| 563 | bool system_buttons_enabled{true}; | ||
| 564 | f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; | ||
| 565 | u32 turbo_button_state{0}; | ||
| 566 | std::size_t nfc_handles{0}; | ||
| 567 | |||
| 568 | // Temporary values to avoid doing changes while the controller is in configuring mode | ||
| 569 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; | ||
| 570 | bool tmp_is_connected{false}; | ||
| 571 | |||
| 572 | ButtonParams button_params; | ||
| 573 | StickParams stick_params; | ||
| 574 | ControllerMotionParams motion_params; | ||
| 575 | TriggerParams trigger_params; | ||
| 576 | BatteryParams battery_params; | ||
| 577 | ColorParams color_params; | ||
| 578 | CameraParams camera_params; | ||
| 579 | RingAnalogParams ring_params; | ||
| 580 | NfcParams nfc_params; | ||
| 581 | OutputParams output_params; | ||
| 582 | |||
| 583 | ButtonDevices button_devices; | ||
| 584 | StickDevices stick_devices; | ||
| 585 | ControllerMotionDevices motion_devices; | ||
| 586 | TriggerDevices trigger_devices; | ||
| 587 | BatteryDevices battery_devices; | ||
| 588 | ColorDevices color_devices; | ||
| 589 | CameraDevices camera_devices; | ||
| 590 | RingAnalogDevices ring_analog_devices; | ||
| 591 | NfcDevices nfc_devices; | ||
| 592 | OutputDevices output_devices; | ||
| 593 | |||
| 594 | // TAS related variables | ||
| 595 | ButtonParams tas_button_params; | ||
| 596 | StickParams tas_stick_params; | ||
| 597 | ButtonDevices tas_button_devices; | ||
| 598 | StickDevices tas_stick_devices; | ||
| 599 | |||
| 600 | // Virtual gamepad related variables | ||
| 601 | ButtonParams virtual_button_params; | ||
| 602 | StickParams virtual_stick_params; | ||
| 603 | ControllerMotionParams virtual_motion_params; | ||
| 604 | ButtonDevices virtual_button_devices; | ||
| 605 | StickDevices virtual_stick_devices; | ||
| 606 | ControllerMotionDevices virtual_motion_devices; | ||
| 607 | |||
| 608 | mutable std::mutex mutex; | ||
| 609 | mutable std::mutex callback_mutex; | ||
| 610 | mutable std::mutex npad_mutex; | ||
| 611 | mutable std::mutex connect_mutex; | ||
| 612 | std::unordered_map<int, ControllerUpdateCallback> callback_list; | ||
| 613 | int last_callback_key = 0; | ||
| 614 | |||
| 615 | // Stores the current status of all controller input | ||
| 616 | ControllerStatus controller; | ||
| 617 | }; | ||
| 618 | |||
| 619 | } // namespace Core::HID | ||
diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp deleted file mode 100644 index 8e165dded..000000000 --- a/src/core/hid/emulated_devices.cpp +++ /dev/null | |||
| @@ -1,483 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <fmt/format.h> | ||
| 6 | |||
| 7 | #include "core/hid/emulated_devices.h" | ||
| 8 | #include "core/hid/input_converter.h" | ||
| 9 | |||
| 10 | namespace Core::HID { | ||
| 11 | |||
| 12 | EmulatedDevices::EmulatedDevices() = default; | ||
| 13 | |||
| 14 | EmulatedDevices::~EmulatedDevices() = default; | ||
| 15 | |||
| 16 | void EmulatedDevices::ReloadFromSettings() { | ||
| 17 | ReloadInput(); | ||
| 18 | } | ||
| 19 | |||
| 20 | void EmulatedDevices::ReloadInput() { | ||
| 21 | // If you load any device here add the equivalent to the UnloadInput() function | ||
| 22 | |||
| 23 | // Native Mouse is mapped on port 1, pad 0 | ||
| 24 | const Common::ParamPackage mouse_params{"engine:mouse,port:1,pad:0"}; | ||
| 25 | |||
| 26 | // Keyboard keys is mapped on port 1, pad 0 for normal keys, pad 1 for moddifier keys | ||
| 27 | const Common::ParamPackage keyboard_params{"engine:keyboard,port:1"}; | ||
| 28 | |||
| 29 | std::size_t key_index = 0; | ||
| 30 | for (auto& mouse_device : mouse_button_devices) { | ||
| 31 | Common::ParamPackage mouse_button_params = mouse_params; | ||
| 32 | mouse_button_params.Set("button", static_cast<int>(key_index)); | ||
| 33 | mouse_device = Common::Input::CreateInputDevice(mouse_button_params); | ||
| 34 | key_index++; | ||
| 35 | } | ||
| 36 | |||
| 37 | Common::ParamPackage mouse_position_params = mouse_params; | ||
| 38 | mouse_position_params.Set("axis_x", 0); | ||
| 39 | mouse_position_params.Set("axis_y", 1); | ||
| 40 | mouse_position_params.Set("deadzone", 0.0f); | ||
| 41 | mouse_position_params.Set("range", 1.0f); | ||
| 42 | mouse_position_params.Set("threshold", 0.0f); | ||
| 43 | mouse_stick_device = Common::Input::CreateInputDevice(mouse_position_params); | ||
| 44 | |||
| 45 | // First two axis are reserved for mouse position | ||
| 46 | key_index = 2; | ||
| 47 | for (auto& mouse_device : mouse_wheel_devices) { | ||
| 48 | Common::ParamPackage mouse_wheel_params = mouse_params; | ||
| 49 | mouse_wheel_params.Set("axis", static_cast<int>(key_index)); | ||
| 50 | mouse_device = Common::Input::CreateInputDevice(mouse_wheel_params); | ||
| 51 | key_index++; | ||
| 52 | } | ||
| 53 | |||
| 54 | key_index = 0; | ||
| 55 | for (auto& keyboard_device : keyboard_devices) { | ||
| 56 | Common::ParamPackage keyboard_key_params = keyboard_params; | ||
| 57 | keyboard_key_params.Set("button", static_cast<int>(key_index)); | ||
| 58 | keyboard_key_params.Set("pad", 0); | ||
| 59 | keyboard_device = Common::Input::CreateInputDevice(keyboard_key_params); | ||
| 60 | key_index++; | ||
| 61 | } | ||
| 62 | |||
| 63 | key_index = 0; | ||
| 64 | for (auto& keyboard_device : keyboard_modifier_devices) { | ||
| 65 | Common::ParamPackage keyboard_moddifier_params = keyboard_params; | ||
| 66 | keyboard_moddifier_params.Set("button", static_cast<int>(key_index)); | ||
| 67 | keyboard_moddifier_params.Set("pad", 1); | ||
| 68 | keyboard_device = Common::Input::CreateInputDevice(keyboard_moddifier_params); | ||
| 69 | key_index++; | ||
| 70 | } | ||
| 71 | |||
| 72 | for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) { | ||
| 73 | if (!mouse_button_devices[index]) { | ||
| 74 | continue; | ||
| 75 | } | ||
| 76 | mouse_button_devices[index]->SetCallback({ | ||
| 77 | .on_change = | ||
| 78 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 79 | SetMouseButton(callback, index); | ||
| 80 | }, | ||
| 81 | }); | ||
| 82 | } | ||
| 83 | |||
| 84 | for (std::size_t index = 0; index < mouse_wheel_devices.size(); ++index) { | ||
| 85 | if (!mouse_wheel_devices[index]) { | ||
| 86 | continue; | ||
| 87 | } | ||
| 88 | mouse_wheel_devices[index]->SetCallback({ | ||
| 89 | .on_change = | ||
| 90 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 91 | SetMouseWheel(callback, index); | ||
| 92 | }, | ||
| 93 | }); | ||
| 94 | } | ||
| 95 | |||
| 96 | if (mouse_stick_device) { | ||
| 97 | mouse_stick_device->SetCallback({ | ||
| 98 | .on_change = | ||
| 99 | [this](const Common::Input::CallbackStatus& callback) { | ||
| 100 | SetMousePosition(callback); | ||
| 101 | }, | ||
| 102 | }); | ||
| 103 | } | ||
| 104 | |||
| 105 | for (std::size_t index = 0; index < keyboard_devices.size(); ++index) { | ||
| 106 | if (!keyboard_devices[index]) { | ||
| 107 | continue; | ||
| 108 | } | ||
| 109 | keyboard_devices[index]->SetCallback({ | ||
| 110 | .on_change = | ||
| 111 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 112 | SetKeyboardButton(callback, index); | ||
| 113 | }, | ||
| 114 | }); | ||
| 115 | } | ||
| 116 | |||
| 117 | for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) { | ||
| 118 | if (!keyboard_modifier_devices[index]) { | ||
| 119 | continue; | ||
| 120 | } | ||
| 121 | keyboard_modifier_devices[index]->SetCallback({ | ||
| 122 | .on_change = | ||
| 123 | [this, index](const Common::Input::CallbackStatus& callback) { | ||
| 124 | SetKeyboardModifier(callback, index); | ||
| 125 | }, | ||
| 126 | }); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | void EmulatedDevices::UnloadInput() { | ||
| 131 | for (auto& button : mouse_button_devices) { | ||
| 132 | button.reset(); | ||
| 133 | } | ||
| 134 | for (auto& analog : mouse_wheel_devices) { | ||
| 135 | analog.reset(); | ||
| 136 | } | ||
| 137 | mouse_stick_device.reset(); | ||
| 138 | for (auto& button : keyboard_devices) { | ||
| 139 | button.reset(); | ||
| 140 | } | ||
| 141 | for (auto& button : keyboard_modifier_devices) { | ||
| 142 | button.reset(); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void EmulatedDevices::EnableConfiguration() { | ||
| 147 | is_configuring = true; | ||
| 148 | SaveCurrentConfig(); | ||
| 149 | } | ||
| 150 | |||
| 151 | void EmulatedDevices::DisableConfiguration() { | ||
| 152 | is_configuring = false; | ||
| 153 | } | ||
| 154 | |||
| 155 | bool EmulatedDevices::IsConfiguring() const { | ||
| 156 | return is_configuring; | ||
| 157 | } | ||
| 158 | |||
| 159 | void EmulatedDevices::SaveCurrentConfig() { | ||
| 160 | if (!is_configuring) { | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | void EmulatedDevices::RestoreConfig() { | ||
| 166 | if (!is_configuring) { | ||
| 167 | return; | ||
| 168 | } | ||
| 169 | ReloadFromSettings(); | ||
| 170 | } | ||
| 171 | |||
| 172 | void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback, | ||
| 173 | std::size_t index) { | ||
| 174 | if (index >= device_status.keyboard_values.size()) { | ||
| 175 | return; | ||
| 176 | } | ||
| 177 | std::unique_lock lock{mutex}; | ||
| 178 | bool value_changed = false; | ||
| 179 | const auto new_status = TransformToButton(callback); | ||
| 180 | auto& current_status = device_status.keyboard_values[index]; | ||
| 181 | current_status.toggle = new_status.toggle; | ||
| 182 | |||
| 183 | // Update button status with current status | ||
| 184 | if (!current_status.toggle) { | ||
| 185 | current_status.locked = false; | ||
| 186 | if (current_status.value != new_status.value) { | ||
| 187 | current_status.value = new_status.value; | ||
| 188 | value_changed = true; | ||
| 189 | } | ||
| 190 | } else { | ||
| 191 | // Toggle button and lock status | ||
| 192 | if (new_status.value && !current_status.locked) { | ||
| 193 | current_status.locked = true; | ||
| 194 | current_status.value = !current_status.value; | ||
| 195 | value_changed = true; | ||
| 196 | } | ||
| 197 | |||
| 198 | // Unlock button, ready for next press | ||
| 199 | if (!new_status.value && current_status.locked) { | ||
| 200 | current_status.locked = false; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | if (!value_changed) { | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | |||
| 208 | if (is_configuring) { | ||
| 209 | lock.unlock(); | ||
| 210 | TriggerOnChange(DeviceTriggerType::Keyboard); | ||
| 211 | return; | ||
| 212 | } | ||
| 213 | |||
| 214 | // Index should be converted from NativeKeyboard to KeyboardKeyIndex | ||
| 215 | UpdateKey(index, current_status.value); | ||
| 216 | |||
| 217 | lock.unlock(); | ||
| 218 | TriggerOnChange(DeviceTriggerType::Keyboard); | ||
| 219 | } | ||
| 220 | |||
| 221 | void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { | ||
| 222 | constexpr std::size_t KEYS_PER_BYTE = 8; | ||
| 223 | auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE]; | ||
| 224 | const u8 mask = static_cast<u8>(1 << (key_index % KEYS_PER_BYTE)); | ||
| 225 | if (status) { | ||
| 226 | entry = entry | mask; | ||
| 227 | } else { | ||
| 228 | entry = static_cast<u8>(entry & ~mask); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& callback, | ||
| 233 | std::size_t index) { | ||
| 234 | if (index >= device_status.keyboard_moddifier_values.size()) { | ||
| 235 | return; | ||
| 236 | } | ||
| 237 | std::unique_lock lock{mutex}; | ||
| 238 | bool value_changed = false; | ||
| 239 | const auto new_status = TransformToButton(callback); | ||
| 240 | auto& current_status = device_status.keyboard_moddifier_values[index]; | ||
| 241 | current_status.toggle = new_status.toggle; | ||
| 242 | |||
| 243 | // Update button status with current | ||
| 244 | if (!current_status.toggle) { | ||
| 245 | current_status.locked = false; | ||
| 246 | if (current_status.value != new_status.value) { | ||
| 247 | current_status.value = new_status.value; | ||
| 248 | value_changed = true; | ||
| 249 | } | ||
| 250 | } else { | ||
| 251 | // Toggle button and lock status | ||
| 252 | if (new_status.value && !current_status.locked) { | ||
| 253 | current_status.locked = true; | ||
| 254 | current_status.value = !current_status.value; | ||
| 255 | value_changed = true; | ||
| 256 | } | ||
| 257 | |||
| 258 | // Unlock button ready for next press | ||
| 259 | if (!new_status.value && current_status.locked) { | ||
| 260 | current_status.locked = false; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | if (!value_changed) { | ||
| 265 | return; | ||
| 266 | } | ||
| 267 | |||
| 268 | if (is_configuring) { | ||
| 269 | lock.unlock(); | ||
| 270 | TriggerOnChange(DeviceTriggerType::KeyboardModdifier); | ||
| 271 | return; | ||
| 272 | } | ||
| 273 | |||
| 274 | switch (index) { | ||
| 275 | case Settings::NativeKeyboard::LeftControl: | ||
| 276 | case Settings::NativeKeyboard::RightControl: | ||
| 277 | device_status.keyboard_moddifier_state.control.Assign(current_status.value); | ||
| 278 | break; | ||
| 279 | case Settings::NativeKeyboard::LeftShift: | ||
| 280 | case Settings::NativeKeyboard::RightShift: | ||
| 281 | device_status.keyboard_moddifier_state.shift.Assign(current_status.value); | ||
| 282 | break; | ||
| 283 | case Settings::NativeKeyboard::LeftAlt: | ||
| 284 | device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value); | ||
| 285 | break; | ||
| 286 | case Settings::NativeKeyboard::RightAlt: | ||
| 287 | device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value); | ||
| 288 | break; | ||
| 289 | case Settings::NativeKeyboard::CapsLock: | ||
| 290 | device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value); | ||
| 291 | break; | ||
| 292 | case Settings::NativeKeyboard::ScrollLock: | ||
| 293 | device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value); | ||
| 294 | break; | ||
| 295 | case Settings::NativeKeyboard::NumLock: | ||
| 296 | device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value); | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | |||
| 300 | lock.unlock(); | ||
| 301 | TriggerOnChange(DeviceTriggerType::KeyboardModdifier); | ||
| 302 | } | ||
| 303 | |||
| 304 | void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callback, | ||
| 305 | std::size_t index) { | ||
| 306 | if (index >= device_status.mouse_button_values.size()) { | ||
| 307 | return; | ||
| 308 | } | ||
| 309 | std::unique_lock lock{mutex}; | ||
| 310 | bool value_changed = false; | ||
| 311 | const auto new_status = TransformToButton(callback); | ||
| 312 | auto& current_status = device_status.mouse_button_values[index]; | ||
| 313 | current_status.toggle = new_status.toggle; | ||
| 314 | |||
| 315 | // Update button status with current | ||
| 316 | if (!current_status.toggle) { | ||
| 317 | current_status.locked = false; | ||
| 318 | if (current_status.value != new_status.value) { | ||
| 319 | current_status.value = new_status.value; | ||
| 320 | value_changed = true; | ||
| 321 | } | ||
| 322 | } else { | ||
| 323 | // Toggle button and lock status | ||
| 324 | if (new_status.value && !current_status.locked) { | ||
| 325 | current_status.locked = true; | ||
| 326 | current_status.value = !current_status.value; | ||
| 327 | value_changed = true; | ||
| 328 | } | ||
| 329 | |||
| 330 | // Unlock button ready for next press | ||
| 331 | if (!new_status.value && current_status.locked) { | ||
| 332 | current_status.locked = false; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | if (!value_changed) { | ||
| 337 | return; | ||
| 338 | } | ||
| 339 | |||
| 340 | if (is_configuring) { | ||
| 341 | lock.unlock(); | ||
| 342 | TriggerOnChange(DeviceTriggerType::Mouse); | ||
| 343 | return; | ||
| 344 | } | ||
| 345 | |||
| 346 | switch (index) { | ||
| 347 | case Settings::NativeMouseButton::Left: | ||
| 348 | device_status.mouse_button_state.left.Assign(current_status.value); | ||
| 349 | break; | ||
| 350 | case Settings::NativeMouseButton::Right: | ||
| 351 | device_status.mouse_button_state.right.Assign(current_status.value); | ||
| 352 | break; | ||
| 353 | case Settings::NativeMouseButton::Middle: | ||
| 354 | device_status.mouse_button_state.middle.Assign(current_status.value); | ||
| 355 | break; | ||
| 356 | case Settings::NativeMouseButton::Forward: | ||
| 357 | device_status.mouse_button_state.forward.Assign(current_status.value); | ||
| 358 | break; | ||
| 359 | case Settings::NativeMouseButton::Back: | ||
| 360 | device_status.mouse_button_state.back.Assign(current_status.value); | ||
| 361 | break; | ||
| 362 | } | ||
| 363 | |||
| 364 | lock.unlock(); | ||
| 365 | TriggerOnChange(DeviceTriggerType::Mouse); | ||
| 366 | } | ||
| 367 | |||
| 368 | void EmulatedDevices::SetMouseWheel(const Common::Input::CallbackStatus& callback, | ||
| 369 | std::size_t index) { | ||
| 370 | if (index >= device_status.mouse_wheel_values.size()) { | ||
| 371 | return; | ||
| 372 | } | ||
| 373 | std::unique_lock lock{mutex}; | ||
| 374 | const auto analog_value = TransformToAnalog(callback); | ||
| 375 | |||
| 376 | device_status.mouse_wheel_values[index] = analog_value; | ||
| 377 | |||
| 378 | if (is_configuring) { | ||
| 379 | device_status.mouse_wheel_state = {}; | ||
| 380 | lock.unlock(); | ||
| 381 | TriggerOnChange(DeviceTriggerType::Mouse); | ||
| 382 | return; | ||
| 383 | } | ||
| 384 | |||
| 385 | switch (index) { | ||
| 386 | case Settings::NativeMouseWheel::X: | ||
| 387 | device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value); | ||
| 388 | break; | ||
| 389 | case Settings::NativeMouseWheel::Y: | ||
| 390 | device_status.mouse_wheel_state.y = static_cast<s32>(analog_value.value); | ||
| 391 | break; | ||
| 392 | } | ||
| 393 | |||
| 394 | lock.unlock(); | ||
| 395 | TriggerOnChange(DeviceTriggerType::Mouse); | ||
| 396 | } | ||
| 397 | |||
| 398 | void EmulatedDevices::SetMousePosition(const Common::Input::CallbackStatus& callback) { | ||
| 399 | std::unique_lock lock{mutex}; | ||
| 400 | const auto touch_value = TransformToTouch(callback); | ||
| 401 | |||
| 402 | device_status.mouse_stick_value = touch_value; | ||
| 403 | |||
| 404 | if (is_configuring) { | ||
| 405 | device_status.mouse_position_state = {}; | ||
| 406 | lock.unlock(); | ||
| 407 | TriggerOnChange(DeviceTriggerType::Mouse); | ||
| 408 | return; | ||
| 409 | } | ||
| 410 | |||
| 411 | device_status.mouse_position_state.x = touch_value.x.value; | ||
| 412 | device_status.mouse_position_state.y = touch_value.y.value; | ||
| 413 | |||
| 414 | lock.unlock(); | ||
| 415 | TriggerOnChange(DeviceTriggerType::Mouse); | ||
| 416 | } | ||
| 417 | |||
| 418 | KeyboardValues EmulatedDevices::GetKeyboardValues() const { | ||
| 419 | std::scoped_lock lock{mutex}; | ||
| 420 | return device_status.keyboard_values; | ||
| 421 | } | ||
| 422 | |||
| 423 | KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const { | ||
| 424 | std::scoped_lock lock{mutex}; | ||
| 425 | return device_status.keyboard_moddifier_values; | ||
| 426 | } | ||
| 427 | |||
| 428 | MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const { | ||
| 429 | std::scoped_lock lock{mutex}; | ||
| 430 | return device_status.mouse_button_values; | ||
| 431 | } | ||
| 432 | |||
| 433 | KeyboardKey EmulatedDevices::GetKeyboard() const { | ||
| 434 | std::scoped_lock lock{mutex}; | ||
| 435 | return device_status.keyboard_state; | ||
| 436 | } | ||
| 437 | |||
| 438 | KeyboardModifier EmulatedDevices::GetKeyboardModifier() const { | ||
| 439 | std::scoped_lock lock{mutex}; | ||
| 440 | return device_status.keyboard_moddifier_state; | ||
| 441 | } | ||
| 442 | |||
| 443 | MouseButton EmulatedDevices::GetMouseButtons() const { | ||
| 444 | std::scoped_lock lock{mutex}; | ||
| 445 | return device_status.mouse_button_state; | ||
| 446 | } | ||
| 447 | |||
| 448 | MousePosition EmulatedDevices::GetMousePosition() const { | ||
| 449 | std::scoped_lock lock{mutex}; | ||
| 450 | return device_status.mouse_position_state; | ||
| 451 | } | ||
| 452 | |||
| 453 | AnalogStickState EmulatedDevices::GetMouseWheel() const { | ||
| 454 | std::scoped_lock lock{mutex}; | ||
| 455 | return device_status.mouse_wheel_state; | ||
| 456 | } | ||
| 457 | |||
| 458 | void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { | ||
| 459 | std::scoped_lock lock{callback_mutex}; | ||
| 460 | for (const auto& poller_pair : callback_list) { | ||
| 461 | const InterfaceUpdateCallback& poller = poller_pair.second; | ||
| 462 | if (poller.on_change) { | ||
| 463 | poller.on_change(type); | ||
| 464 | } | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) { | ||
| 469 | std::scoped_lock lock{callback_mutex}; | ||
| 470 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); | ||
| 471 | return last_callback_key++; | ||
| 472 | } | ||
| 473 | |||
| 474 | void EmulatedDevices::DeleteCallback(int key) { | ||
| 475 | std::scoped_lock lock{callback_mutex}; | ||
| 476 | const auto& iterator = callback_list.find(key); | ||
| 477 | if (iterator == callback_list.end()) { | ||
| 478 | LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); | ||
| 479 | return; | ||
| 480 | } | ||
| 481 | callback_list.erase(iterator); | ||
| 482 | } | ||
| 483 | } // namespace Core::HID | ||
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h deleted file mode 100644 index 5eab693e4..000000000 --- a/src/core/hid/emulated_devices.h +++ /dev/null | |||
| @@ -1,212 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <functional> | ||
| 8 | #include <memory> | ||
| 9 | #include <mutex> | ||
| 10 | #include <unordered_map> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "common/input.h" | ||
| 15 | #include "common/param_package.h" | ||
| 16 | #include "common/settings.h" | ||
| 17 | #include "core/hid/hid_types.h" | ||
| 18 | |||
| 19 | namespace Core::HID { | ||
| 20 | using KeyboardDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, | ||
| 21 | Settings::NativeKeyboard::NumKeyboardKeys>; | ||
| 22 | using KeyboardModifierDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, | ||
| 23 | Settings::NativeKeyboard::NumKeyboardMods>; | ||
| 24 | using MouseButtonDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, | ||
| 25 | Settings::NativeMouseButton::NumMouseButtons>; | ||
| 26 | using MouseWheelDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, | ||
| 27 | Settings::NativeMouseWheel::NumMouseWheels>; | ||
| 28 | using MouseStickDevice = std::unique_ptr<Common::Input::InputDevice>; | ||
| 29 | |||
| 30 | using MouseButtonParams = | ||
| 31 | std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons>; | ||
| 32 | |||
| 33 | using KeyboardValues = | ||
| 34 | std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardKeys>; | ||
| 35 | using KeyboardModifierValues = | ||
| 36 | std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>; | ||
| 37 | using MouseButtonValues = | ||
| 38 | std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>; | ||
| 39 | using MouseWheelValues = | ||
| 40 | std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>; | ||
| 41 | using MouseStickValue = Common::Input::TouchStatus; | ||
| 42 | |||
| 43 | struct MousePosition { | ||
| 44 | f32 x; | ||
| 45 | f32 y; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct DeviceStatus { | ||
| 49 | // Data from input_common | ||
| 50 | KeyboardValues keyboard_values{}; | ||
| 51 | KeyboardModifierValues keyboard_moddifier_values{}; | ||
| 52 | MouseButtonValues mouse_button_values{}; | ||
| 53 | MouseWheelValues mouse_wheel_values{}; | ||
| 54 | MouseStickValue mouse_stick_value{}; | ||
| 55 | |||
| 56 | // Data for HID services | ||
| 57 | KeyboardKey keyboard_state{}; | ||
| 58 | KeyboardModifier keyboard_moddifier_state{}; | ||
| 59 | MouseButton mouse_button_state{}; | ||
| 60 | MousePosition mouse_position_state{}; | ||
| 61 | AnalogStickState mouse_wheel_state{}; | ||
| 62 | }; | ||
| 63 | |||
| 64 | enum class DeviceTriggerType { | ||
| 65 | Keyboard, | ||
| 66 | KeyboardModdifier, | ||
| 67 | Mouse, | ||
| 68 | RingController, | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct InterfaceUpdateCallback { | ||
| 72 | std::function<void(DeviceTriggerType)> on_change; | ||
| 73 | }; | ||
| 74 | |||
| 75 | class EmulatedDevices { | ||
| 76 | public: | ||
| 77 | /** | ||
| 78 | * Contains all input data related to external devices that aren't necessarily a controller | ||
| 79 | * This includes devices such as the keyboard or mouse | ||
| 80 | */ | ||
| 81 | explicit EmulatedDevices(); | ||
| 82 | ~EmulatedDevices(); | ||
| 83 | |||
| 84 | YUZU_NON_COPYABLE(EmulatedDevices); | ||
| 85 | YUZU_NON_MOVEABLE(EmulatedDevices); | ||
| 86 | |||
| 87 | /// Removes all callbacks created from input devices | ||
| 88 | void UnloadInput(); | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Sets the emulated devices into configuring mode | ||
| 92 | * This prevents the modification of the HID state of the emulated devices by input commands | ||
| 93 | */ | ||
| 94 | void EnableConfiguration(); | ||
| 95 | |||
| 96 | /// Returns the emulated devices into normal mode, allowing the modification of the HID state | ||
| 97 | void DisableConfiguration(); | ||
| 98 | |||
| 99 | /// Returns true if the emulated device is in configuring mode | ||
| 100 | bool IsConfiguring() const; | ||
| 101 | |||
| 102 | /// Reload all input devices | ||
| 103 | void ReloadInput(); | ||
| 104 | |||
| 105 | /// Overrides current mapped devices with the stored configuration and reloads all input devices | ||
| 106 | void ReloadFromSettings(); | ||
| 107 | |||
| 108 | /// Saves the current mapped configuration | ||
| 109 | void SaveCurrentConfig(); | ||
| 110 | |||
| 111 | /// Reverts any mapped changes made that weren't saved | ||
| 112 | void RestoreConfig(); | ||
| 113 | |||
| 114 | /// Returns the latest status of button input from the keyboard with parameters | ||
| 115 | KeyboardValues GetKeyboardValues() const; | ||
| 116 | |||
| 117 | /// Returns the latest status of button input from the keyboard modifiers with parameters | ||
| 118 | KeyboardModifierValues GetKeyboardModdifierValues() const; | ||
| 119 | |||
| 120 | /// Returns the latest status of button input from the mouse with parameters | ||
| 121 | MouseButtonValues GetMouseButtonsValues() const; | ||
| 122 | |||
| 123 | /// Returns the latest status of button input from the keyboard | ||
| 124 | KeyboardKey GetKeyboard() const; | ||
| 125 | |||
| 126 | /// Returns the latest status of button input from the keyboard modifiers | ||
| 127 | KeyboardModifier GetKeyboardModifier() const; | ||
| 128 | |||
| 129 | /// Returns the latest status of button input from the mouse | ||
| 130 | MouseButton GetMouseButtons() const; | ||
| 131 | |||
| 132 | /// Returns the latest mouse coordinates | ||
| 133 | MousePosition GetMousePosition() const; | ||
| 134 | |||
| 135 | /// Returns the latest mouse wheel change | ||
| 136 | AnalogStickState GetMouseWheel() const; | ||
| 137 | |||
| 138 | /** | ||
| 139 | * Adds a callback to the list of events | ||
| 140 | * @param update_callback InterfaceUpdateCallback that will be triggered | ||
| 141 | * @return an unique key corresponding to the callback index in the list | ||
| 142 | */ | ||
| 143 | int SetCallback(InterfaceUpdateCallback update_callback); | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Removes a callback from the list stopping any future events to this object | ||
| 147 | * @param key Key corresponding to the callback index in the list | ||
| 148 | */ | ||
| 149 | void DeleteCallback(int key); | ||
| 150 | |||
| 151 | private: | ||
| 152 | /// Helps assigning a value to keyboard_state | ||
| 153 | void UpdateKey(std::size_t key_index, bool status); | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Updates the touch status of the keyboard device | ||
| 157 | * @param callback A CallbackStatus containing the key status | ||
| 158 | * @param index key ID to be updated | ||
| 159 | */ | ||
| 160 | void SetKeyboardButton(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 161 | |||
| 162 | /** | ||
| 163 | * Updates the keyboard status of the keyboard device | ||
| 164 | * @param callback A CallbackStatus containing the modifier key status | ||
| 165 | * @param index modifier key ID to be updated | ||
| 166 | */ | ||
| 167 | void SetKeyboardModifier(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 168 | |||
| 169 | /** | ||
| 170 | * Updates the mouse button status of the mouse device | ||
| 171 | * @param callback A CallbackStatus containing the button status | ||
| 172 | * @param index Button ID to be updated | ||
| 173 | */ | ||
| 174 | void SetMouseButton(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 175 | |||
| 176 | /** | ||
| 177 | * Updates the mouse wheel status of the mouse device | ||
| 178 | * @param callback A CallbackStatus containing the wheel status | ||
| 179 | * @param index wheel ID to be updated | ||
| 180 | */ | ||
| 181 | void SetMouseWheel(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 182 | |||
| 183 | /** | ||
| 184 | * Updates the mouse position status of the mouse device | ||
| 185 | * @param callback A CallbackStatus containing the position status | ||
| 186 | */ | ||
| 187 | void SetMousePosition(const Common::Input::CallbackStatus& callback); | ||
| 188 | |||
| 189 | /** | ||
| 190 | * Triggers a callback that something has changed on the device status | ||
| 191 | * @param type Input type of the event to trigger | ||
| 192 | */ | ||
| 193 | void TriggerOnChange(DeviceTriggerType type); | ||
| 194 | |||
| 195 | bool is_configuring{false}; | ||
| 196 | |||
| 197 | KeyboardDevices keyboard_devices; | ||
| 198 | KeyboardModifierDevices keyboard_modifier_devices; | ||
| 199 | MouseButtonDevices mouse_button_devices; | ||
| 200 | MouseWheelDevices mouse_wheel_devices; | ||
| 201 | MouseStickDevice mouse_stick_device; | ||
| 202 | |||
| 203 | mutable std::mutex mutex; | ||
| 204 | mutable std::mutex callback_mutex; | ||
| 205 | std::unordered_map<int, InterfaceUpdateCallback> callback_list; | ||
| 206 | int last_callback_key = 0; | ||
| 207 | |||
| 208 | // Stores the current status of all external device input | ||
| 209 | DeviceStatus device_status; | ||
| 210 | }; | ||
| 211 | |||
| 212 | } // namespace Core::HID | ||
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp deleted file mode 100644 index 2cf25a870..000000000 --- a/src/core/hid/hid_core.cpp +++ /dev/null | |||
| @@ -1,222 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/assert.h" | ||
| 5 | #include "core/hid/emulated_console.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/emulated_devices.h" | ||
| 8 | #include "core/hid/hid_core.h" | ||
| 9 | #include "core/hle/service/hid/hid_util.h" | ||
| 10 | |||
| 11 | namespace Core::HID { | ||
| 12 | |||
| 13 | HIDCore::HIDCore() | ||
| 14 | : player_1{std::make_unique<EmulatedController>(NpadIdType::Player1)}, | ||
| 15 | player_2{std::make_unique<EmulatedController>(NpadIdType::Player2)}, | ||
| 16 | player_3{std::make_unique<EmulatedController>(NpadIdType::Player3)}, | ||
| 17 | player_4{std::make_unique<EmulatedController>(NpadIdType::Player4)}, | ||
| 18 | player_5{std::make_unique<EmulatedController>(NpadIdType::Player5)}, | ||
| 19 | player_6{std::make_unique<EmulatedController>(NpadIdType::Player6)}, | ||
| 20 | player_7{std::make_unique<EmulatedController>(NpadIdType::Player7)}, | ||
| 21 | player_8{std::make_unique<EmulatedController>(NpadIdType::Player8)}, | ||
| 22 | other{std::make_unique<EmulatedController>(NpadIdType::Other)}, | ||
| 23 | handheld{std::make_unique<EmulatedController>(NpadIdType::Handheld)}, | ||
| 24 | console{std::make_unique<EmulatedConsole>()}, devices{std::make_unique<EmulatedDevices>()} {} | ||
| 25 | |||
| 26 | HIDCore::~HIDCore() = default; | ||
| 27 | |||
| 28 | EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) { | ||
| 29 | switch (npad_id_type) { | ||
| 30 | case NpadIdType::Player1: | ||
| 31 | return player_1.get(); | ||
| 32 | case NpadIdType::Player2: | ||
| 33 | return player_2.get(); | ||
| 34 | case NpadIdType::Player3: | ||
| 35 | return player_3.get(); | ||
| 36 | case NpadIdType::Player4: | ||
| 37 | return player_4.get(); | ||
| 38 | case NpadIdType::Player5: | ||
| 39 | return player_5.get(); | ||
| 40 | case NpadIdType::Player6: | ||
| 41 | return player_6.get(); | ||
| 42 | case NpadIdType::Player7: | ||
| 43 | return player_7.get(); | ||
| 44 | case NpadIdType::Player8: | ||
| 45 | return player_8.get(); | ||
| 46 | case NpadIdType::Other: | ||
| 47 | return other.get(); | ||
| 48 | case NpadIdType::Handheld: | ||
| 49 | return handheld.get(); | ||
| 50 | case NpadIdType::Invalid: | ||
| 51 | default: | ||
| 52 | ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type); | ||
| 53 | return nullptr; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | const EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) const { | ||
| 58 | switch (npad_id_type) { | ||
| 59 | case NpadIdType::Player1: | ||
| 60 | return player_1.get(); | ||
| 61 | case NpadIdType::Player2: | ||
| 62 | return player_2.get(); | ||
| 63 | case NpadIdType::Player3: | ||
| 64 | return player_3.get(); | ||
| 65 | case NpadIdType::Player4: | ||
| 66 | return player_4.get(); | ||
| 67 | case NpadIdType::Player5: | ||
| 68 | return player_5.get(); | ||
| 69 | case NpadIdType::Player6: | ||
| 70 | return player_6.get(); | ||
| 71 | case NpadIdType::Player7: | ||
| 72 | return player_7.get(); | ||
| 73 | case NpadIdType::Player8: | ||
| 74 | return player_8.get(); | ||
| 75 | case NpadIdType::Other: | ||
| 76 | return other.get(); | ||
| 77 | case NpadIdType::Handheld: | ||
| 78 | return handheld.get(); | ||
| 79 | case NpadIdType::Invalid: | ||
| 80 | default: | ||
| 81 | ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type); | ||
| 82 | return nullptr; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | EmulatedConsole* HIDCore::GetEmulatedConsole() { | ||
| 86 | return console.get(); | ||
| 87 | } | ||
| 88 | |||
| 89 | const EmulatedConsole* HIDCore::GetEmulatedConsole() const { | ||
| 90 | return console.get(); | ||
| 91 | } | ||
| 92 | |||
| 93 | EmulatedDevices* HIDCore::GetEmulatedDevices() { | ||
| 94 | return devices.get(); | ||
| 95 | } | ||
| 96 | |||
| 97 | const EmulatedDevices* HIDCore::GetEmulatedDevices() const { | ||
| 98 | return devices.get(); | ||
| 99 | } | ||
| 100 | |||
| 101 | EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) { | ||
| 102 | return GetEmulatedController(Service::HID::IndexToNpadIdType(index)); | ||
| 103 | } | ||
| 104 | |||
| 105 | const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const { | ||
| 106 | return GetEmulatedController(Service::HID::IndexToNpadIdType(index)); | ||
| 107 | } | ||
| 108 | |||
| 109 | void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) { | ||
| 110 | supported_style_tag.raw = style_tag.raw; | ||
| 111 | player_1->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 112 | player_2->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 113 | player_3->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 114 | player_4->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 115 | player_5->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 116 | player_6->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 117 | player_7->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 118 | player_8->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 119 | other->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 120 | handheld->SetSupportedNpadStyleTag(supported_style_tag); | ||
| 121 | } | ||
| 122 | |||
| 123 | NpadStyleTag HIDCore::GetSupportedStyleTag() const { | ||
| 124 | return supported_style_tag; | ||
| 125 | } | ||
| 126 | |||
| 127 | s8 HIDCore::GetPlayerCount() const { | ||
| 128 | s8 active_players = 0; | ||
| 129 | for (std::size_t player_index = 0; player_index < available_controllers - 2; ++player_index) { | ||
| 130 | const auto* const controller = GetEmulatedControllerByIndex(player_index); | ||
| 131 | if (controller->IsConnected()) { | ||
| 132 | active_players++; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | return active_players; | ||
| 136 | } | ||
| 137 | |||
| 138 | NpadIdType HIDCore::GetFirstNpadId() const { | ||
| 139 | for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) { | ||
| 140 | const auto* const controller = GetEmulatedControllerByIndex(player_index); | ||
| 141 | if (controller->IsConnected()) { | ||
| 142 | return controller->GetNpadIdType(); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | return NpadIdType::Player1; | ||
| 146 | } | ||
| 147 | |||
| 148 | NpadIdType HIDCore::GetFirstDisconnectedNpadId() const { | ||
| 149 | for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) { | ||
| 150 | const auto* const controller = GetEmulatedControllerByIndex(player_index); | ||
| 151 | if (!controller->IsConnected()) { | ||
| 152 | return controller->GetNpadIdType(); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | return NpadIdType::Player1; | ||
| 156 | } | ||
| 157 | |||
| 158 | void HIDCore::SetLastActiveController(NpadIdType npad_id) { | ||
| 159 | last_active_controller = npad_id; | ||
| 160 | } | ||
| 161 | |||
| 162 | NpadIdType HIDCore::GetLastActiveController() const { | ||
| 163 | return last_active_controller; | ||
| 164 | } | ||
| 165 | |||
| 166 | void HIDCore::EnableAllControllerConfiguration() { | ||
| 167 | player_1->EnableConfiguration(); | ||
| 168 | player_2->EnableConfiguration(); | ||
| 169 | player_3->EnableConfiguration(); | ||
| 170 | player_4->EnableConfiguration(); | ||
| 171 | player_5->EnableConfiguration(); | ||
| 172 | player_6->EnableConfiguration(); | ||
| 173 | player_7->EnableConfiguration(); | ||
| 174 | player_8->EnableConfiguration(); | ||
| 175 | other->EnableConfiguration(); | ||
| 176 | handheld->EnableConfiguration(); | ||
| 177 | } | ||
| 178 | |||
| 179 | void HIDCore::DisableAllControllerConfiguration() { | ||
| 180 | player_1->DisableConfiguration(); | ||
| 181 | player_2->DisableConfiguration(); | ||
| 182 | player_3->DisableConfiguration(); | ||
| 183 | player_4->DisableConfiguration(); | ||
| 184 | player_5->DisableConfiguration(); | ||
| 185 | player_6->DisableConfiguration(); | ||
| 186 | player_7->DisableConfiguration(); | ||
| 187 | player_8->DisableConfiguration(); | ||
| 188 | other->DisableConfiguration(); | ||
| 189 | handheld->DisableConfiguration(); | ||
| 190 | } | ||
| 191 | |||
| 192 | void HIDCore::ReloadInputDevices() { | ||
| 193 | player_1->ReloadFromSettings(); | ||
| 194 | player_2->ReloadFromSettings(); | ||
| 195 | player_3->ReloadFromSettings(); | ||
| 196 | player_4->ReloadFromSettings(); | ||
| 197 | player_5->ReloadFromSettings(); | ||
| 198 | player_6->ReloadFromSettings(); | ||
| 199 | player_7->ReloadFromSettings(); | ||
| 200 | player_8->ReloadFromSettings(); | ||
| 201 | other->ReloadFromSettings(); | ||
| 202 | handheld->ReloadFromSettings(); | ||
| 203 | console->ReloadFromSettings(); | ||
| 204 | devices->ReloadFromSettings(); | ||
| 205 | } | ||
| 206 | |||
| 207 | void HIDCore::UnloadInputDevices() { | ||
| 208 | player_1->UnloadInput(); | ||
| 209 | player_2->UnloadInput(); | ||
| 210 | player_3->UnloadInput(); | ||
| 211 | player_4->UnloadInput(); | ||
| 212 | player_5->UnloadInput(); | ||
| 213 | player_6->UnloadInput(); | ||
| 214 | player_7->UnloadInput(); | ||
| 215 | player_8->UnloadInput(); | ||
| 216 | other->UnloadInput(); | ||
| 217 | handheld->UnloadInput(); | ||
| 218 | console->UnloadInput(); | ||
| 219 | devices->UnloadInput(); | ||
| 220 | } | ||
| 221 | |||
| 222 | } // namespace Core::HID | ||
diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h deleted file mode 100644 index 80abab18b..000000000 --- a/src/core/hid/hid_core.h +++ /dev/null | |||
| @@ -1,89 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include "common/common_funcs.h" | ||
| 9 | #include "core/hid/hid_types.h" | ||
| 10 | |||
| 11 | namespace Core::HID { | ||
| 12 | class EmulatedConsole; | ||
| 13 | class EmulatedController; | ||
| 14 | class EmulatedDevices; | ||
| 15 | } // namespace Core::HID | ||
| 16 | |||
| 17 | namespace Core::HID { | ||
| 18 | |||
| 19 | class HIDCore { | ||
| 20 | public: | ||
| 21 | explicit HIDCore(); | ||
| 22 | ~HIDCore(); | ||
| 23 | |||
| 24 | YUZU_NON_COPYABLE(HIDCore); | ||
| 25 | YUZU_NON_MOVEABLE(HIDCore); | ||
| 26 | |||
| 27 | EmulatedController* GetEmulatedController(NpadIdType npad_id_type); | ||
| 28 | const EmulatedController* GetEmulatedController(NpadIdType npad_id_type) const; | ||
| 29 | |||
| 30 | EmulatedController* GetEmulatedControllerByIndex(std::size_t index); | ||
| 31 | const EmulatedController* GetEmulatedControllerByIndex(std::size_t index) const; | ||
| 32 | |||
| 33 | EmulatedConsole* GetEmulatedConsole(); | ||
| 34 | const EmulatedConsole* GetEmulatedConsole() const; | ||
| 35 | |||
| 36 | EmulatedDevices* GetEmulatedDevices(); | ||
| 37 | const EmulatedDevices* GetEmulatedDevices() const; | ||
| 38 | |||
| 39 | void SetSupportedStyleTag(NpadStyleTag style_tag); | ||
| 40 | NpadStyleTag GetSupportedStyleTag() const; | ||
| 41 | |||
| 42 | /// Counts the connected players from P1-P8 | ||
| 43 | s8 GetPlayerCount() const; | ||
| 44 | |||
| 45 | /// Returns the first connected npad id | ||
| 46 | NpadIdType GetFirstNpadId() const; | ||
| 47 | |||
| 48 | /// Returns the first disconnected npad id | ||
| 49 | NpadIdType GetFirstDisconnectedNpadId() const; | ||
| 50 | |||
| 51 | /// Sets the npad id of the last active controller | ||
| 52 | void SetLastActiveController(NpadIdType npad_id); | ||
| 53 | |||
| 54 | /// Returns the npad id of the last controller that pushed a button | ||
| 55 | NpadIdType GetLastActiveController() const; | ||
| 56 | |||
| 57 | /// Sets all emulated controllers into configuring mode. | ||
| 58 | void EnableAllControllerConfiguration(); | ||
| 59 | |||
| 60 | /// Sets all emulated controllers into normal mode. | ||
| 61 | void DisableAllControllerConfiguration(); | ||
| 62 | |||
| 63 | /// Reloads all input devices from settings | ||
| 64 | void ReloadInputDevices(); | ||
| 65 | |||
| 66 | /// Removes all callbacks from input common | ||
| 67 | void UnloadInputDevices(); | ||
| 68 | |||
| 69 | /// Number of emulated controllers | ||
| 70 | static constexpr std::size_t available_controllers{10}; | ||
| 71 | |||
| 72 | private: | ||
| 73 | std::unique_ptr<EmulatedController> player_1; | ||
| 74 | std::unique_ptr<EmulatedController> player_2; | ||
| 75 | std::unique_ptr<EmulatedController> player_3; | ||
| 76 | std::unique_ptr<EmulatedController> player_4; | ||
| 77 | std::unique_ptr<EmulatedController> player_5; | ||
| 78 | std::unique_ptr<EmulatedController> player_6; | ||
| 79 | std::unique_ptr<EmulatedController> player_7; | ||
| 80 | std::unique_ptr<EmulatedController> player_8; | ||
| 81 | std::unique_ptr<EmulatedController> other; | ||
| 82 | std::unique_ptr<EmulatedController> handheld; | ||
| 83 | std::unique_ptr<EmulatedConsole> console; | ||
| 84 | std::unique_ptr<EmulatedDevices> devices; | ||
| 85 | NpadStyleTag supported_style_tag{NpadStyleSet::All}; | ||
| 86 | NpadIdType last_active_controller{NpadIdType::Handheld}; | ||
| 87 | }; | ||
| 88 | |||
| 89 | } // namespace Core::HID | ||
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h deleted file mode 100644 index a81ed6af0..000000000 --- a/src/core/hid/hid_types.h +++ /dev/null | |||
| @@ -1,736 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_funcs.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "common/point.h" | ||
| 10 | #include "common/uuid.h" | ||
| 11 | #include "common/vector_math.h" | ||
| 12 | |||
| 13 | namespace Core::HID { | ||
| 14 | |||
| 15 | enum class DeviceIndex : u8 { | ||
| 16 | Left = 0, | ||
| 17 | Right = 1, | ||
| 18 | None = 2, | ||
| 19 | MaxDeviceIndex = 3, | ||
| 20 | }; | ||
| 21 | |||
| 22 | // This is nn::hid::NpadButton | ||
| 23 | enum class NpadButton : u64 { | ||
| 24 | None = 0, | ||
| 25 | A = 1U << 0, | ||
| 26 | B = 1U << 1, | ||
| 27 | X = 1U << 2, | ||
| 28 | Y = 1U << 3, | ||
| 29 | StickL = 1U << 4, | ||
| 30 | StickR = 1U << 5, | ||
| 31 | L = 1U << 6, | ||
| 32 | R = 1U << 7, | ||
| 33 | ZL = 1U << 8, | ||
| 34 | ZR = 1U << 9, | ||
| 35 | Plus = 1U << 10, | ||
| 36 | Minus = 1U << 11, | ||
| 37 | |||
| 38 | Left = 1U << 12, | ||
| 39 | Up = 1U << 13, | ||
| 40 | Right = 1U << 14, | ||
| 41 | Down = 1U << 15, | ||
| 42 | |||
| 43 | StickLLeft = 1U << 16, | ||
| 44 | StickLUp = 1U << 17, | ||
| 45 | StickLRight = 1U << 18, | ||
| 46 | StickLDown = 1U << 19, | ||
| 47 | |||
| 48 | StickRLeft = 1U << 20, | ||
| 49 | StickRUp = 1U << 21, | ||
| 50 | StickRRight = 1U << 22, | ||
| 51 | StickRDown = 1U << 23, | ||
| 52 | |||
| 53 | LeftSL = 1U << 24, | ||
| 54 | LeftSR = 1U << 25, | ||
| 55 | |||
| 56 | RightSL = 1U << 26, | ||
| 57 | RightSR = 1U << 27, | ||
| 58 | |||
| 59 | Palma = 1U << 28, | ||
| 60 | Verification = 1U << 29, | ||
| 61 | HandheldLeftB = 1U << 30, | ||
| 62 | LagonCLeft = 1U << 31, | ||
| 63 | LagonCUp = 1ULL << 32, | ||
| 64 | LagonCRight = 1ULL << 33, | ||
| 65 | LagonCDown = 1ULL << 34, | ||
| 66 | |||
| 67 | All = 0xFFFFFFFFFFFFFFFFULL, | ||
| 68 | }; | ||
| 69 | DECLARE_ENUM_FLAG_OPERATORS(NpadButton); | ||
| 70 | |||
| 71 | enum class KeyboardKeyIndex : u32 { | ||
| 72 | A = 4, | ||
| 73 | B = 5, | ||
| 74 | C = 6, | ||
| 75 | D = 7, | ||
| 76 | E = 8, | ||
| 77 | F = 9, | ||
| 78 | G = 10, | ||
| 79 | H = 11, | ||
| 80 | I = 12, | ||
| 81 | J = 13, | ||
| 82 | K = 14, | ||
| 83 | L = 15, | ||
| 84 | M = 16, | ||
| 85 | N = 17, | ||
| 86 | O = 18, | ||
| 87 | P = 19, | ||
| 88 | Q = 20, | ||
| 89 | R = 21, | ||
| 90 | S = 22, | ||
| 91 | T = 23, | ||
| 92 | U = 24, | ||
| 93 | V = 25, | ||
| 94 | W = 26, | ||
| 95 | X = 27, | ||
| 96 | Y = 28, | ||
| 97 | Z = 29, | ||
| 98 | D1 = 30, | ||
| 99 | D2 = 31, | ||
| 100 | D3 = 32, | ||
| 101 | D4 = 33, | ||
| 102 | D5 = 34, | ||
| 103 | D6 = 35, | ||
| 104 | D7 = 36, | ||
| 105 | D8 = 37, | ||
| 106 | D9 = 38, | ||
| 107 | D0 = 39, | ||
| 108 | Return = 40, | ||
| 109 | Escape = 41, | ||
| 110 | Backspace = 42, | ||
| 111 | Tab = 43, | ||
| 112 | Space = 44, | ||
| 113 | Minus = 45, | ||
| 114 | Plus = 46, | ||
| 115 | OpenBracket = 47, | ||
| 116 | CloseBracket = 48, | ||
| 117 | Pipe = 49, | ||
| 118 | Tilde = 50, | ||
| 119 | Semicolon = 51, | ||
| 120 | Quote = 52, | ||
| 121 | Backquote = 53, | ||
| 122 | Comma = 54, | ||
| 123 | Period = 55, | ||
| 124 | Slash = 56, | ||
| 125 | CapsLock = 57, | ||
| 126 | F1 = 58, | ||
| 127 | F2 = 59, | ||
| 128 | F3 = 60, | ||
| 129 | F4 = 61, | ||
| 130 | F5 = 62, | ||
| 131 | F6 = 63, | ||
| 132 | F7 = 64, | ||
| 133 | F8 = 65, | ||
| 134 | F9 = 66, | ||
| 135 | F10 = 67, | ||
| 136 | F11 = 68, | ||
| 137 | F12 = 69, | ||
| 138 | PrintScreen = 70, | ||
| 139 | ScrollLock = 71, | ||
| 140 | Pause = 72, | ||
| 141 | Insert = 73, | ||
| 142 | Home = 74, | ||
| 143 | PageUp = 75, | ||
| 144 | Delete = 76, | ||
| 145 | End = 77, | ||
| 146 | PageDown = 78, | ||
| 147 | RightArrow = 79, | ||
| 148 | LeftArrow = 80, | ||
| 149 | DownArrow = 81, | ||
| 150 | UpArrow = 82, | ||
| 151 | NumLock = 83, | ||
| 152 | NumPadDivide = 84, | ||
| 153 | NumPadMultiply = 85, | ||
| 154 | NumPadSubtract = 86, | ||
| 155 | NumPadAdd = 87, | ||
| 156 | NumPadEnter = 88, | ||
| 157 | NumPad1 = 89, | ||
| 158 | NumPad2 = 90, | ||
| 159 | NumPad3 = 91, | ||
| 160 | NumPad4 = 92, | ||
| 161 | NumPad5 = 93, | ||
| 162 | NumPad6 = 94, | ||
| 163 | NumPad7 = 95, | ||
| 164 | NumPad8 = 96, | ||
| 165 | NumPad9 = 97, | ||
| 166 | NumPad0 = 98, | ||
| 167 | NumPadDot = 99, | ||
| 168 | Backslash = 100, | ||
| 169 | Application = 101, | ||
| 170 | Power = 102, | ||
| 171 | NumPadEquals = 103, | ||
| 172 | F13 = 104, | ||
| 173 | F14 = 105, | ||
| 174 | F15 = 106, | ||
| 175 | F16 = 107, | ||
| 176 | F17 = 108, | ||
| 177 | F18 = 109, | ||
| 178 | F19 = 110, | ||
| 179 | F20 = 111, | ||
| 180 | F21 = 112, | ||
| 181 | F22 = 113, | ||
| 182 | F23 = 114, | ||
| 183 | F24 = 115, | ||
| 184 | NumPadComma = 133, | ||
| 185 | Ro = 135, | ||
| 186 | KatakanaHiragana = 136, | ||
| 187 | Yen = 137, | ||
| 188 | Henkan = 138, | ||
| 189 | Muhenkan = 139, | ||
| 190 | NumPadCommaPc98 = 140, | ||
| 191 | HangulEnglish = 144, | ||
| 192 | Hanja = 145, | ||
| 193 | Katakana = 146, | ||
| 194 | Hiragana = 147, | ||
| 195 | ZenkakuHankaku = 148, | ||
| 196 | LeftControl = 224, | ||
| 197 | LeftShift = 225, | ||
| 198 | LeftAlt = 226, | ||
| 199 | LeftGui = 227, | ||
| 200 | RightControl = 228, | ||
| 201 | RightShift = 229, | ||
| 202 | RightAlt = 230, | ||
| 203 | RightGui = 231, | ||
| 204 | }; | ||
| 205 | |||
| 206 | // This is nn::hid::NpadIdType | ||
| 207 | enum class NpadIdType : u32 { | ||
| 208 | Player1 = 0x0, | ||
| 209 | Player2 = 0x1, | ||
| 210 | Player3 = 0x2, | ||
| 211 | Player4 = 0x3, | ||
| 212 | Player5 = 0x4, | ||
| 213 | Player6 = 0x5, | ||
| 214 | Player7 = 0x6, | ||
| 215 | Player8 = 0x7, | ||
| 216 | Other = 0x10, | ||
| 217 | Handheld = 0x20, | ||
| 218 | |||
| 219 | Invalid = 0xFFFFFFFF, | ||
| 220 | }; | ||
| 221 | |||
| 222 | enum class NpadInterfaceType : u8 { | ||
| 223 | Bluetooth = 1, | ||
| 224 | Rail = 2, | ||
| 225 | Usb = 3, | ||
| 226 | Embedded = 4, | ||
| 227 | }; | ||
| 228 | |||
| 229 | // This is nn::hid::NpadStyleIndex | ||
| 230 | enum class NpadStyleIndex : u8 { | ||
| 231 | None = 0, | ||
| 232 | ProController = 3, | ||
| 233 | Handheld = 4, | ||
| 234 | HandheldNES = 4, | ||
| 235 | JoyconDual = 5, | ||
| 236 | JoyconLeft = 6, | ||
| 237 | JoyconRight = 7, | ||
| 238 | GameCube = 8, | ||
| 239 | Pokeball = 9, | ||
| 240 | NES = 10, | ||
| 241 | SNES = 12, | ||
| 242 | N64 = 13, | ||
| 243 | SegaGenesis = 14, | ||
| 244 | SystemExt = 32, | ||
| 245 | System = 33, | ||
| 246 | MaxNpadType = 34, | ||
| 247 | }; | ||
| 248 | |||
| 249 | // This is nn::hid::NpadStyleSet | ||
| 250 | enum class NpadStyleSet : u32 { | ||
| 251 | None = 0, | ||
| 252 | Fullkey = 1U << 0, | ||
| 253 | Handheld = 1U << 1, | ||
| 254 | JoyDual = 1U << 2, | ||
| 255 | JoyLeft = 1U << 3, | ||
| 256 | JoyRight = 1U << 4, | ||
| 257 | Gc = 1U << 5, | ||
| 258 | Palma = 1U << 6, | ||
| 259 | Lark = 1U << 7, | ||
| 260 | HandheldLark = 1U << 8, | ||
| 261 | Lucia = 1U << 9, | ||
| 262 | Lagoon = 1U << 10, | ||
| 263 | Lager = 1U << 11, | ||
| 264 | SystemExt = 1U << 29, | ||
| 265 | System = 1U << 30, | ||
| 266 | |||
| 267 | All = 0xFFFFFFFFU, | ||
| 268 | }; | ||
| 269 | static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); | ||
| 270 | DECLARE_ENUM_FLAG_OPERATORS(NpadStyleSet) | ||
| 271 | |||
| 272 | // This is nn::hid::VibrationDevicePosition | ||
| 273 | enum class VibrationDevicePosition : u32 { | ||
| 274 | None = 0, | ||
| 275 | Left = 1, | ||
| 276 | Right = 2, | ||
| 277 | }; | ||
| 278 | |||
| 279 | // This is nn::hid::VibrationDeviceType | ||
| 280 | enum class VibrationDeviceType : u32 { | ||
| 281 | Unknown = 0, | ||
| 282 | LinearResonantActuator = 1, | ||
| 283 | GcErm = 2, | ||
| 284 | N64 = 3, | ||
| 285 | }; | ||
| 286 | |||
| 287 | // This is nn::hid::VibrationGcErmCommand | ||
| 288 | enum class VibrationGcErmCommand : u64 { | ||
| 289 | Stop = 0, | ||
| 290 | Start = 1, | ||
| 291 | StopHard = 2, | ||
| 292 | }; | ||
| 293 | |||
| 294 | // This is nn::hid::GyroscopeZeroDriftMode | ||
| 295 | enum class GyroscopeZeroDriftMode : u32 { | ||
| 296 | Loose = 0, | ||
| 297 | Standard = 1, | ||
| 298 | Tight = 2, | ||
| 299 | }; | ||
| 300 | |||
| 301 | // This is nn::settings::system::TouchScreenMode | ||
| 302 | enum class TouchScreenMode : u32 { | ||
| 303 | Stylus = 0, | ||
| 304 | Standard = 1, | ||
| 305 | }; | ||
| 306 | |||
| 307 | // This is nn::hid::TouchScreenModeForNx | ||
| 308 | enum class TouchScreenModeForNx : u8 { | ||
| 309 | UseSystemSetting, | ||
| 310 | Finger, | ||
| 311 | Heat2, | ||
| 312 | }; | ||
| 313 | |||
| 314 | // This is nn::hid::system::NpadBatteryLevel | ||
| 315 | enum class NpadBatteryLevel : u32 { | ||
| 316 | Empty, | ||
| 317 | Critical, | ||
| 318 | Low, | ||
| 319 | High, | ||
| 320 | Full, | ||
| 321 | }; | ||
| 322 | |||
| 323 | // This is nn::hid::NpadStyleTag | ||
| 324 | struct NpadStyleTag { | ||
| 325 | union { | ||
| 326 | NpadStyleSet raw{}; | ||
| 327 | |||
| 328 | BitField<0, 1, u32> fullkey; | ||
| 329 | BitField<1, 1, u32> handheld; | ||
| 330 | BitField<2, 1, u32> joycon_dual; | ||
| 331 | BitField<3, 1, u32> joycon_left; | ||
| 332 | BitField<4, 1, u32> joycon_right; | ||
| 333 | BitField<5, 1, u32> gamecube; | ||
| 334 | BitField<6, 1, u32> palma; | ||
| 335 | BitField<7, 1, u32> lark; | ||
| 336 | BitField<8, 1, u32> handheld_lark; | ||
| 337 | BitField<9, 1, u32> lucia; | ||
| 338 | BitField<10, 1, u32> lagoon; | ||
| 339 | BitField<11, 1, u32> lager; | ||
| 340 | BitField<29, 1, u32> system_ext; | ||
| 341 | BitField<30, 1, u32> system; | ||
| 342 | }; | ||
| 343 | }; | ||
| 344 | static_assert(sizeof(NpadStyleTag) == 4, "NpadStyleTag is an invalid size"); | ||
| 345 | |||
| 346 | // This is nn::hid::TouchAttribute | ||
| 347 | struct TouchAttribute { | ||
| 348 | union { | ||
| 349 | u32 raw{}; | ||
| 350 | BitField<0, 1, u32> start_touch; | ||
| 351 | BitField<1, 1, u32> end_touch; | ||
| 352 | }; | ||
| 353 | }; | ||
| 354 | static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"); | ||
| 355 | |||
| 356 | // This is nn::hid::TouchState | ||
| 357 | struct TouchState { | ||
| 358 | u64 delta_time{}; | ||
| 359 | TouchAttribute attribute{}; | ||
| 360 | u32 finger{}; | ||
| 361 | Common::Point<u32> position{}; | ||
| 362 | u32 diameter_x{}; | ||
| 363 | u32 diameter_y{}; | ||
| 364 | u32 rotation_angle{}; | ||
| 365 | }; | ||
| 366 | static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); | ||
| 367 | |||
| 368 | struct TouchFinger { | ||
| 369 | u64 last_touch{}; | ||
| 370 | Common::Point<float> position{}; | ||
| 371 | u32 id{}; | ||
| 372 | TouchAttribute attribute{}; | ||
| 373 | bool pressed{}; | ||
| 374 | }; | ||
| 375 | |||
| 376 | // This is nn::hid::TouchScreenConfigurationForNx | ||
| 377 | struct TouchScreenConfigurationForNx { | ||
| 378 | TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting}; | ||
| 379 | INSERT_PADDING_BYTES(0xF); | ||
| 380 | }; | ||
| 381 | static_assert(sizeof(TouchScreenConfigurationForNx) == 0x10, | ||
| 382 | "TouchScreenConfigurationForNx is an invalid size"); | ||
| 383 | |||
| 384 | struct NpadColor { | ||
| 385 | u8 r{}; | ||
| 386 | u8 g{}; | ||
| 387 | u8 b{}; | ||
| 388 | u8 a{}; | ||
| 389 | }; | ||
| 390 | static_assert(sizeof(NpadColor) == 4, "NpadColor is an invalid size"); | ||
| 391 | |||
| 392 | // This is nn::hid::NpadControllerColor | ||
| 393 | struct NpadControllerColor { | ||
| 394 | NpadColor body{}; | ||
| 395 | NpadColor button{}; | ||
| 396 | }; | ||
| 397 | static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); | ||
| 398 | |||
| 399 | // This is nn::hid::AnalogStickState | ||
| 400 | struct AnalogStickState { | ||
| 401 | s32 x{}; | ||
| 402 | s32 y{}; | ||
| 403 | }; | ||
| 404 | static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size"); | ||
| 405 | |||
| 406 | // This is nn::hid::server::NpadGcTriggerState | ||
| 407 | struct NpadGcTriggerState { | ||
| 408 | s64 sampling_number{}; | ||
| 409 | s32 left{}; | ||
| 410 | s32 right{}; | ||
| 411 | }; | ||
| 412 | static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); | ||
| 413 | |||
| 414 | // This is nn::hid::system::NpadPowerInfo | ||
| 415 | struct NpadPowerInfo { | ||
| 416 | bool is_powered{}; | ||
| 417 | bool is_charging{}; | ||
| 418 | INSERT_PADDING_BYTES(0x6); | ||
| 419 | NpadBatteryLevel battery_level{NpadBatteryLevel::Full}; | ||
| 420 | }; | ||
| 421 | static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); | ||
| 422 | |||
| 423 | struct LedPattern { | ||
| 424 | explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { | ||
| 425 | position1.Assign(light1); | ||
| 426 | position2.Assign(light2); | ||
| 427 | position3.Assign(light3); | ||
| 428 | position4.Assign(light4); | ||
| 429 | } | ||
| 430 | union { | ||
| 431 | u64 raw{}; | ||
| 432 | BitField<0, 1, u64> position1; | ||
| 433 | BitField<1, 1, u64> position2; | ||
| 434 | BitField<2, 1, u64> position3; | ||
| 435 | BitField<3, 1, u64> position4; | ||
| 436 | }; | ||
| 437 | }; | ||
| 438 | |||
| 439 | struct HomeButtonState { | ||
| 440 | union { | ||
| 441 | u64 raw{}; | ||
| 442 | |||
| 443 | // Buttons | ||
| 444 | BitField<0, 1, u64> home; | ||
| 445 | }; | ||
| 446 | }; | ||
| 447 | static_assert(sizeof(HomeButtonState) == 0x8, "HomeButtonState has incorrect size."); | ||
| 448 | |||
| 449 | struct CaptureButtonState { | ||
| 450 | union { | ||
| 451 | u64 raw{}; | ||
| 452 | |||
| 453 | // Buttons | ||
| 454 | BitField<0, 1, u64> capture; | ||
| 455 | }; | ||
| 456 | }; | ||
| 457 | static_assert(sizeof(CaptureButtonState) == 0x8, "CaptureButtonState has incorrect size."); | ||
| 458 | |||
| 459 | struct NpadButtonState { | ||
| 460 | union { | ||
| 461 | NpadButton raw{}; | ||
| 462 | |||
| 463 | // Buttons | ||
| 464 | BitField<0, 1, u64> a; | ||
| 465 | BitField<1, 1, u64> b; | ||
| 466 | BitField<2, 1, u64> x; | ||
| 467 | BitField<3, 1, u64> y; | ||
| 468 | BitField<4, 1, u64> stick_l; | ||
| 469 | BitField<5, 1, u64> stick_r; | ||
| 470 | BitField<6, 1, u64> l; | ||
| 471 | BitField<7, 1, u64> r; | ||
| 472 | BitField<8, 1, u64> zl; | ||
| 473 | BitField<9, 1, u64> zr; | ||
| 474 | BitField<10, 1, u64> plus; | ||
| 475 | BitField<11, 1, u64> minus; | ||
| 476 | |||
| 477 | // D-Pad | ||
| 478 | BitField<12, 1, u64> left; | ||
| 479 | BitField<13, 1, u64> up; | ||
| 480 | BitField<14, 1, u64> right; | ||
| 481 | BitField<15, 1, u64> down; | ||
| 482 | |||
| 483 | // Left JoyStick | ||
| 484 | BitField<16, 1, u64> stick_l_left; | ||
| 485 | BitField<17, 1, u64> stick_l_up; | ||
| 486 | BitField<18, 1, u64> stick_l_right; | ||
| 487 | BitField<19, 1, u64> stick_l_down; | ||
| 488 | |||
| 489 | // Right JoyStick | ||
| 490 | BitField<20, 1, u64> stick_r_left; | ||
| 491 | BitField<21, 1, u64> stick_r_up; | ||
| 492 | BitField<22, 1, u64> stick_r_right; | ||
| 493 | BitField<23, 1, u64> stick_r_down; | ||
| 494 | |||
| 495 | BitField<24, 1, u64> left_sl; | ||
| 496 | BitField<25, 1, u64> left_sr; | ||
| 497 | |||
| 498 | BitField<26, 1, u64> right_sl; | ||
| 499 | BitField<27, 1, u64> right_sr; | ||
| 500 | |||
| 501 | BitField<28, 1, u64> palma; | ||
| 502 | BitField<29, 1, u64> verification; | ||
| 503 | BitField<30, 1, u64> handheld_left_b; | ||
| 504 | BitField<31, 1, u64> lagon_c_left; | ||
| 505 | BitField<32, 1, u64> lagon_c_up; | ||
| 506 | BitField<33, 1, u64> lagon_c_right; | ||
| 507 | BitField<34, 1, u64> lagon_c_down; | ||
| 508 | }; | ||
| 509 | }; | ||
| 510 | static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect size."); | ||
| 511 | |||
| 512 | // This is nn::hid::DebugPadButton | ||
| 513 | struct DebugPadButton { | ||
| 514 | union { | ||
| 515 | u32 raw{}; | ||
| 516 | BitField<0, 1, u32> a; | ||
| 517 | BitField<1, 1, u32> b; | ||
| 518 | BitField<2, 1, u32> x; | ||
| 519 | BitField<3, 1, u32> y; | ||
| 520 | BitField<4, 1, u32> l; | ||
| 521 | BitField<5, 1, u32> r; | ||
| 522 | BitField<6, 1, u32> zl; | ||
| 523 | BitField<7, 1, u32> zr; | ||
| 524 | BitField<8, 1, u32> plus; | ||
| 525 | BitField<9, 1, u32> minus; | ||
| 526 | BitField<10, 1, u32> d_left; | ||
| 527 | BitField<11, 1, u32> d_up; | ||
| 528 | BitField<12, 1, u32> d_right; | ||
| 529 | BitField<13, 1, u32> d_down; | ||
| 530 | }; | ||
| 531 | }; | ||
| 532 | static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); | ||
| 533 | |||
| 534 | // This is nn::hid::ConsoleSixAxisSensorHandle | ||
| 535 | struct ConsoleSixAxisSensorHandle { | ||
| 536 | u8 unknown_1{}; | ||
| 537 | u8 unknown_2{}; | ||
| 538 | INSERT_PADDING_BYTES_NOINIT(2); | ||
| 539 | }; | ||
| 540 | static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4, | ||
| 541 | "ConsoleSixAxisSensorHandle is an invalid size"); | ||
| 542 | |||
| 543 | // This is nn::hid::SixAxisSensorHandle | ||
| 544 | struct SixAxisSensorHandle { | ||
| 545 | NpadStyleIndex npad_type{NpadStyleIndex::None}; | ||
| 546 | u8 npad_id{}; | ||
| 547 | DeviceIndex device_index{DeviceIndex::None}; | ||
| 548 | INSERT_PADDING_BYTES_NOINIT(1); | ||
| 549 | }; | ||
| 550 | static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size"); | ||
| 551 | |||
| 552 | // These parameters seem related to how much gyro/accelerometer is used | ||
| 553 | struct SixAxisSensorFusionParameters { | ||
| 554 | f32 parameter1{0.03f}; // Range 0.0 to 1.0, default 0.03 | ||
| 555 | f32 parameter2{0.4f}; // Default 0.4 | ||
| 556 | }; | ||
| 557 | static_assert(sizeof(SixAxisSensorFusionParameters) == 8, | ||
| 558 | "SixAxisSensorFusionParameters is an invalid size"); | ||
| 559 | |||
| 560 | // This is nn::hid::server::SixAxisSensorProperties | ||
| 561 | struct SixAxisSensorProperties { | ||
| 562 | union { | ||
| 563 | u8 raw{}; | ||
| 564 | BitField<0, 1, u8> is_newly_assigned; | ||
| 565 | BitField<1, 1, u8> is_firmware_update_available; | ||
| 566 | }; | ||
| 567 | }; | ||
| 568 | static_assert(sizeof(SixAxisSensorProperties) == 1, "SixAxisSensorProperties is an invalid size"); | ||
| 569 | |||
| 570 | // This is nn::hid::SixAxisSensorCalibrationParameter | ||
| 571 | struct SixAxisSensorCalibrationParameter { | ||
| 572 | std::array<u8, 0x744> unknown_data{}; | ||
| 573 | }; | ||
| 574 | static_assert(sizeof(SixAxisSensorCalibrationParameter) == 0x744, | ||
| 575 | "SixAxisSensorCalibrationParameter is an invalid size"); | ||
| 576 | |||
| 577 | // This is nn::hid::SixAxisSensorIcInformation | ||
| 578 | struct SixAxisSensorIcInformation { | ||
| 579 | f32 angular_rate{2000.0f}; // dps | ||
| 580 | std::array<f32, 6> unknown_gyro_data1{ | ||
| 581 | -10.0f, -10.0f, -10.0f, 10.0f, 10.0f, 10.0f, | ||
| 582 | }; // dps | ||
| 583 | std::array<f32, 9> unknown_gyro_data2{ | ||
| 584 | 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, | ||
| 585 | }; | ||
| 586 | std::array<f32, 9> unknown_gyro_data3{ | ||
| 587 | 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, | ||
| 588 | }; | ||
| 589 | f32 acceleration_range{8.0f}; // g force | ||
| 590 | std::array<f32, 6> unknown_accel_data1{ | ||
| 591 | -0.0612f, -0.0612f, -0.0612f, 0.0612f, 0.0612f, 0.0612f, | ||
| 592 | }; // g force | ||
| 593 | std::array<f32, 9> unknown_accel_data2{ | ||
| 594 | 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, | ||
| 595 | }; | ||
| 596 | std::array<f32, 9> unknown_accel_data3{ | ||
| 597 | 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, | ||
| 598 | }; | ||
| 599 | }; | ||
| 600 | static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8, | ||
| 601 | "SixAxisSensorIcInformation is an invalid size"); | ||
| 602 | |||
| 603 | // This is nn::hid::SixAxisSensorAttribute | ||
| 604 | struct SixAxisSensorAttribute { | ||
| 605 | union { | ||
| 606 | u32 raw{}; | ||
| 607 | BitField<0, 1, u32> is_connected; | ||
| 608 | BitField<1, 1, u32> is_interpolated; | ||
| 609 | }; | ||
| 610 | }; | ||
| 611 | static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size"); | ||
| 612 | |||
| 613 | // This is nn::hid::SixAxisSensorState | ||
| 614 | struct SixAxisSensorState { | ||
| 615 | s64 delta_time{}; | ||
| 616 | s64 sampling_number{}; | ||
| 617 | Common::Vec3f accel{}; | ||
| 618 | Common::Vec3f gyro{}; | ||
| 619 | Common::Vec3f rotation{}; | ||
| 620 | std::array<Common::Vec3f, 3> orientation{}; | ||
| 621 | SixAxisSensorAttribute attribute{}; | ||
| 622 | INSERT_PADDING_BYTES(4); // Reserved | ||
| 623 | }; | ||
| 624 | static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size"); | ||
| 625 | |||
| 626 | // This is nn::hid::VibrationDeviceHandle | ||
| 627 | struct VibrationDeviceHandle { | ||
| 628 | NpadStyleIndex npad_type{NpadStyleIndex::None}; | ||
| 629 | u8 npad_id{}; | ||
| 630 | DeviceIndex device_index{DeviceIndex::None}; | ||
| 631 | INSERT_PADDING_BYTES_NOINIT(1); | ||
| 632 | }; | ||
| 633 | static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size"); | ||
| 634 | |||
| 635 | // This is nn::hid::VibrationValue | ||
| 636 | struct VibrationValue { | ||
| 637 | f32 low_amplitude{}; | ||
| 638 | f32 low_frequency{}; | ||
| 639 | f32 high_amplitude{}; | ||
| 640 | f32 high_frequency{}; | ||
| 641 | }; | ||
| 642 | static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); | ||
| 643 | |||
| 644 | constexpr VibrationValue DEFAULT_VIBRATION_VALUE{ | ||
| 645 | .low_amplitude = 0.0f, | ||
| 646 | .low_frequency = 160.0f, | ||
| 647 | .high_amplitude = 0.0f, | ||
| 648 | .high_frequency = 320.0f, | ||
| 649 | }; | ||
| 650 | |||
| 651 | // This is nn::hid::VibrationDeviceInfo | ||
| 652 | struct VibrationDeviceInfo { | ||
| 653 | VibrationDeviceType type{}; | ||
| 654 | VibrationDevicePosition position{}; | ||
| 655 | }; | ||
| 656 | static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); | ||
| 657 | |||
| 658 | // This is nn::hid::KeyboardModifier | ||
| 659 | struct KeyboardModifier { | ||
| 660 | union { | ||
| 661 | u32 raw{}; | ||
| 662 | BitField<0, 1, u32> control; | ||
| 663 | BitField<1, 1, u32> shift; | ||
| 664 | BitField<2, 1, u32> left_alt; | ||
| 665 | BitField<3, 1, u32> right_alt; | ||
| 666 | BitField<4, 1, u32> gui; | ||
| 667 | BitField<8, 1, u32> caps_lock; | ||
| 668 | BitField<9, 1, u32> scroll_lock; | ||
| 669 | BitField<10, 1, u32> num_lock; | ||
| 670 | BitField<11, 1, u32> katakana; | ||
| 671 | BitField<12, 1, u32> hiragana; | ||
| 672 | }; | ||
| 673 | }; | ||
| 674 | |||
| 675 | static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size"); | ||
| 676 | |||
| 677 | // This is nn::hid::KeyboardAttribute | ||
| 678 | struct KeyboardAttribute { | ||
| 679 | union { | ||
| 680 | u32 raw{}; | ||
| 681 | BitField<0, 1, u32> is_connected; | ||
| 682 | }; | ||
| 683 | }; | ||
| 684 | static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid size"); | ||
| 685 | |||
| 686 | // This is nn::hid::KeyboardKey | ||
| 687 | struct KeyboardKey { | ||
| 688 | // This should be a 256 bit flag | ||
| 689 | std::array<u8, 32> key{}; | ||
| 690 | }; | ||
| 691 | static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size"); | ||
| 692 | |||
| 693 | // This is nn::hid::MouseButton | ||
| 694 | struct MouseButton { | ||
| 695 | union { | ||
| 696 | u32_le raw{}; | ||
| 697 | BitField<0, 1, u32> left; | ||
| 698 | BitField<1, 1, u32> right; | ||
| 699 | BitField<2, 1, u32> middle; | ||
| 700 | BitField<3, 1, u32> forward; | ||
| 701 | BitField<4, 1, u32> back; | ||
| 702 | }; | ||
| 703 | }; | ||
| 704 | static_assert(sizeof(MouseButton) == 0x4, "MouseButton is an invalid size"); | ||
| 705 | |||
| 706 | // This is nn::hid::MouseAttribute | ||
| 707 | struct MouseAttribute { | ||
| 708 | union { | ||
| 709 | u32 raw{}; | ||
| 710 | BitField<0, 1, u32> transferable; | ||
| 711 | BitField<1, 1, u32> is_connected; | ||
| 712 | }; | ||
| 713 | }; | ||
| 714 | static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size"); | ||
| 715 | |||
| 716 | // This is nn::hid::detail::MouseState | ||
| 717 | struct MouseState { | ||
| 718 | s64 sampling_number{}; | ||
| 719 | s32 x{}; | ||
| 720 | s32 y{}; | ||
| 721 | s32 delta_x{}; | ||
| 722 | s32 delta_y{}; | ||
| 723 | // Axis Order in HW is switched for the wheel | ||
| 724 | s32 delta_wheel_y{}; | ||
| 725 | s32 delta_wheel_x{}; | ||
| 726 | MouseButton button{}; | ||
| 727 | MouseAttribute attribute{}; | ||
| 728 | }; | ||
| 729 | static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); | ||
| 730 | |||
| 731 | struct UniquePadId { | ||
| 732 | u64 id; | ||
| 733 | }; | ||
| 734 | static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size"); | ||
| 735 | |||
| 736 | } // namespace Core::HID | ||
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp deleted file mode 100644 index a05716fd8..000000000 --- a/src/core/hid/input_converter.cpp +++ /dev/null | |||
| @@ -1,436 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <random> | ||
| 6 | |||
| 7 | #include "common/input.h" | ||
| 8 | #include "core/hid/input_converter.h" | ||
| 9 | |||
| 10 | namespace Core::HID { | ||
| 11 | |||
| 12 | Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback) { | ||
| 13 | Common::Input::BatteryStatus battery{Common::Input::BatteryStatus::None}; | ||
| 14 | switch (callback.type) { | ||
| 15 | case Common::Input::InputType::Analog: | ||
| 16 | case Common::Input::InputType::Trigger: { | ||
| 17 | const auto value = TransformToTrigger(callback).analog.value; | ||
| 18 | battery = Common::Input::BatteryLevel::Empty; | ||
| 19 | if (value > 0.2f) { | ||
| 20 | battery = Common::Input::BatteryLevel::Critical; | ||
| 21 | } | ||
| 22 | if (value > 0.4f) { | ||
| 23 | battery = Common::Input::BatteryLevel::Low; | ||
| 24 | } | ||
| 25 | if (value > 0.6f) { | ||
| 26 | battery = Common::Input::BatteryLevel::Medium; | ||
| 27 | } | ||
| 28 | if (value > 0.8f) { | ||
| 29 | battery = Common::Input::BatteryLevel::Full; | ||
| 30 | } | ||
| 31 | if (value >= 0.95f) { | ||
| 32 | battery = Common::Input::BatteryLevel::Charging; | ||
| 33 | } | ||
| 34 | break; | ||
| 35 | } | ||
| 36 | case Common::Input::InputType::Button: | ||
| 37 | battery = callback.button_status.value ? Common::Input::BatteryLevel::Charging | ||
| 38 | : Common::Input::BatteryLevel::Critical; | ||
| 39 | break; | ||
| 40 | case Common::Input::InputType::Battery: | ||
| 41 | battery = callback.battery_status; | ||
| 42 | break; | ||
| 43 | default: | ||
| 44 | LOG_ERROR(Input, "Conversion from type {} to battery not implemented", callback.type); | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | |||
| 48 | return battery; | ||
| 49 | } | ||
| 50 | |||
| 51 | Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback) { | ||
| 52 | Common::Input::ButtonStatus status{}; | ||
| 53 | switch (callback.type) { | ||
| 54 | case Common::Input::InputType::Analog: | ||
| 55 | status.value = TransformToTrigger(callback).pressed.value; | ||
| 56 | status.toggle = callback.analog_status.properties.toggle; | ||
| 57 | status.inverted = callback.analog_status.properties.inverted_button; | ||
| 58 | break; | ||
| 59 | case Common::Input::InputType::Trigger: | ||
| 60 | status.value = TransformToTrigger(callback).pressed.value; | ||
| 61 | break; | ||
| 62 | case Common::Input::InputType::Button: | ||
| 63 | status = callback.button_status; | ||
| 64 | break; | ||
| 65 | case Common::Input::InputType::Motion: | ||
| 66 | status.value = std::abs(callback.motion_status.gyro.x.raw_value) > 1.0f; | ||
| 67 | break; | ||
| 68 | default: | ||
| 69 | LOG_ERROR(Input, "Conversion from type {} to button not implemented", callback.type); | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | |||
| 73 | if (status.inverted) { | ||
| 74 | status.value = !status.value; | ||
| 75 | } | ||
| 76 | |||
| 77 | return status; | ||
| 78 | } | ||
| 79 | |||
| 80 | Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback) { | ||
| 81 | Common::Input::MotionStatus status{}; | ||
| 82 | switch (callback.type) { | ||
| 83 | case Common::Input::InputType::Button: { | ||
| 84 | Common::Input::AnalogProperties properties{ | ||
| 85 | .deadzone = 0.0f, | ||
| 86 | .range = 1.0f, | ||
| 87 | .offset = 0.0f, | ||
| 88 | }; | ||
| 89 | status.delta_timestamp = 1000; | ||
| 90 | status.force_update = true; | ||
| 91 | status.accel.x = { | ||
| 92 | .value = 0.0f, | ||
| 93 | .raw_value = 0.0f, | ||
| 94 | .properties = properties, | ||
| 95 | }; | ||
| 96 | status.accel.y = { | ||
| 97 | .value = 0.0f, | ||
| 98 | .raw_value = 0.0f, | ||
| 99 | .properties = properties, | ||
| 100 | }; | ||
| 101 | status.accel.z = { | ||
| 102 | .value = 0.0f, | ||
| 103 | .raw_value = -1.0f, | ||
| 104 | .properties = properties, | ||
| 105 | }; | ||
| 106 | status.gyro.x = { | ||
| 107 | .value = 0.0f, | ||
| 108 | .raw_value = 0.0f, | ||
| 109 | .properties = properties, | ||
| 110 | }; | ||
| 111 | status.gyro.y = { | ||
| 112 | .value = 0.0f, | ||
| 113 | .raw_value = 0.0f, | ||
| 114 | .properties = properties, | ||
| 115 | }; | ||
| 116 | status.gyro.z = { | ||
| 117 | .value = 0.0f, | ||
| 118 | .raw_value = 0.0f, | ||
| 119 | .properties = properties, | ||
| 120 | }; | ||
| 121 | if (TransformToButton(callback).value) { | ||
| 122 | std::random_device device; | ||
| 123 | std::mt19937 gen(device()); | ||
| 124 | std::uniform_int_distribution<s16> distribution(-5000, 5000); | ||
| 125 | status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | ||
| 126 | status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | ||
| 127 | status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | ||
| 128 | status.gyro.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | ||
| 129 | status.gyro.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | ||
| 130 | status.gyro.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | ||
| 131 | } | ||
| 132 | break; | ||
| 133 | } | ||
| 134 | case Common::Input::InputType::Motion: | ||
| 135 | status = callback.motion_status; | ||
| 136 | break; | ||
| 137 | default: | ||
| 138 | LOG_ERROR(Input, "Conversion from type {} to motion not implemented", callback.type); | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | SanitizeAnalog(status.accel.x, false); | ||
| 142 | SanitizeAnalog(status.accel.y, false); | ||
| 143 | SanitizeAnalog(status.accel.z, false); | ||
| 144 | SanitizeAnalog(status.gyro.x, false); | ||
| 145 | SanitizeAnalog(status.gyro.y, false); | ||
| 146 | SanitizeAnalog(status.gyro.z, false); | ||
| 147 | |||
| 148 | return status; | ||
| 149 | } | ||
| 150 | |||
| 151 | Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback) { | ||
| 152 | Common::Input::StickStatus status{}; | ||
| 153 | |||
| 154 | switch (callback.type) { | ||
| 155 | case Common::Input::InputType::Stick: | ||
| 156 | status = callback.stick_status; | ||
| 157 | break; | ||
| 158 | default: | ||
| 159 | LOG_ERROR(Input, "Conversion from type {} to stick not implemented", callback.type); | ||
| 160 | break; | ||
| 161 | } | ||
| 162 | |||
| 163 | SanitizeStick(status.x, status.y, true); | ||
| 164 | const auto& properties_x = status.x.properties; | ||
| 165 | const auto& properties_y = status.y.properties; | ||
| 166 | const float x = status.x.value; | ||
| 167 | const float y = status.y.value; | ||
| 168 | |||
| 169 | // Set directional buttons | ||
| 170 | status.right = x > properties_x.threshold; | ||
| 171 | status.left = x < -properties_x.threshold; | ||
| 172 | status.up = y > properties_y.threshold; | ||
| 173 | status.down = y < -properties_y.threshold; | ||
| 174 | |||
| 175 | return status; | ||
| 176 | } | ||
| 177 | |||
| 178 | Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback) { | ||
| 179 | Common::Input::TouchStatus status{}; | ||
| 180 | |||
| 181 | switch (callback.type) { | ||
| 182 | case Common::Input::InputType::Touch: | ||
| 183 | status = callback.touch_status; | ||
| 184 | break; | ||
| 185 | case Common::Input::InputType::Stick: | ||
| 186 | status.x = callback.stick_status.x; | ||
| 187 | status.y = callback.stick_status.y; | ||
| 188 | break; | ||
| 189 | default: | ||
| 190 | LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type); | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | |||
| 194 | SanitizeAnalog(status.x, true); | ||
| 195 | SanitizeAnalog(status.y, true); | ||
| 196 | float& x = status.x.value; | ||
| 197 | float& y = status.y.value; | ||
| 198 | |||
| 199 | // Adjust if value is inverted | ||
| 200 | x = status.x.properties.inverted ? 1.0f + x : x; | ||
| 201 | y = status.y.properties.inverted ? 1.0f + y : y; | ||
| 202 | |||
| 203 | // clamp value | ||
| 204 | x = std::clamp(x, 0.0f, 1.0f); | ||
| 205 | y = std::clamp(y, 0.0f, 1.0f); | ||
| 206 | |||
| 207 | if (status.pressed.inverted) { | ||
| 208 | status.pressed.value = !status.pressed.value; | ||
| 209 | } | ||
| 210 | |||
| 211 | return status; | ||
| 212 | } | ||
| 213 | |||
| 214 | Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback) { | ||
| 215 | Common::Input::TriggerStatus status{}; | ||
| 216 | float& raw_value = status.analog.raw_value; | ||
| 217 | bool calculate_button_value = true; | ||
| 218 | |||
| 219 | switch (callback.type) { | ||
| 220 | case Common::Input::InputType::Analog: | ||
| 221 | status.analog.properties = callback.analog_status.properties; | ||
| 222 | raw_value = callback.analog_status.raw_value; | ||
| 223 | break; | ||
| 224 | case Common::Input::InputType::Button: | ||
| 225 | status.analog.properties.range = 1.0f; | ||
| 226 | status.analog.properties.inverted = callback.button_status.inverted; | ||
| 227 | raw_value = callback.button_status.value ? 1.0f : 0.0f; | ||
| 228 | break; | ||
| 229 | case Common::Input::InputType::Trigger: | ||
| 230 | status = callback.trigger_status; | ||
| 231 | calculate_button_value = false; | ||
| 232 | break; | ||
| 233 | case Common::Input::InputType::Motion: | ||
| 234 | status.analog.properties.range = 1.0f; | ||
| 235 | raw_value = callback.motion_status.accel.x.raw_value; | ||
| 236 | break; | ||
| 237 | default: | ||
| 238 | LOG_ERROR(Input, "Conversion from type {} to trigger not implemented", callback.type); | ||
| 239 | break; | ||
| 240 | } | ||
| 241 | |||
| 242 | SanitizeAnalog(status.analog, true); | ||
| 243 | const auto& properties = status.analog.properties; | ||
| 244 | float& value = status.analog.value; | ||
| 245 | |||
| 246 | // Set button status | ||
| 247 | if (calculate_button_value) { | ||
| 248 | status.pressed.value = value > properties.threshold; | ||
| 249 | } | ||
| 250 | |||
| 251 | // Adjust if value is inverted | ||
| 252 | value = properties.inverted ? 1.0f + value : value; | ||
| 253 | |||
| 254 | // clamp value | ||
| 255 | value = std::clamp(value, 0.0f, 1.0f); | ||
| 256 | |||
| 257 | return status; | ||
| 258 | } | ||
| 259 | |||
| 260 | Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback) { | ||
| 261 | Common::Input::AnalogStatus status{}; | ||
| 262 | |||
| 263 | switch (callback.type) { | ||
| 264 | case Common::Input::InputType::Analog: | ||
| 265 | status.properties = callback.analog_status.properties; | ||
| 266 | status.raw_value = callback.analog_status.raw_value; | ||
| 267 | break; | ||
| 268 | default: | ||
| 269 | LOG_ERROR(Input, "Conversion from type {} to analog not implemented", callback.type); | ||
| 270 | break; | ||
| 271 | } | ||
| 272 | |||
| 273 | SanitizeAnalog(status, false); | ||
| 274 | |||
| 275 | // Adjust if value is inverted | ||
| 276 | status.value = status.properties.inverted ? -status.value : status.value; | ||
| 277 | |||
| 278 | return status; | ||
| 279 | } | ||
| 280 | |||
| 281 | Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatus& callback) { | ||
| 282 | Common::Input::CameraStatus camera{}; | ||
| 283 | switch (callback.type) { | ||
| 284 | case Common::Input::InputType::IrSensor: | ||
| 285 | camera = { | ||
| 286 | .format = callback.camera_status, | ||
| 287 | .data = callback.raw_data, | ||
| 288 | }; | ||
| 289 | break; | ||
| 290 | default: | ||
| 291 | LOG_ERROR(Input, "Conversion from type {} to camera not implemented", callback.type); | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | |||
| 295 | return camera; | ||
| 296 | } | ||
| 297 | |||
| 298 | Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& callback) { | ||
| 299 | Common::Input::NfcStatus nfc{}; | ||
| 300 | switch (callback.type) { | ||
| 301 | case Common::Input::InputType::Nfc: | ||
| 302 | return callback.nfc_status; | ||
| 303 | default: | ||
| 304 | LOG_ERROR(Input, "Conversion from type {} to NFC not implemented", callback.type); | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | |||
| 308 | return nfc; | ||
| 309 | } | ||
| 310 | |||
| 311 | Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback) { | ||
| 312 | switch (callback.type) { | ||
| 313 | case Common::Input::InputType::Color: | ||
| 314 | return callback.color_status; | ||
| 315 | break; | ||
| 316 | default: | ||
| 317 | LOG_ERROR(Input, "Conversion from type {} to color not implemented", callback.type); | ||
| 318 | return {}; | ||
| 319 | break; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { | ||
| 324 | const auto& properties = analog.properties; | ||
| 325 | float& raw_value = analog.raw_value; | ||
| 326 | float& value = analog.value; | ||
| 327 | |||
| 328 | if (!std::isnormal(raw_value)) { | ||
| 329 | raw_value = 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | // Apply center offset | ||
| 333 | raw_value -= properties.offset; | ||
| 334 | |||
| 335 | // Set initial values to be formatted | ||
| 336 | value = raw_value; | ||
| 337 | |||
| 338 | // Calculate vector size | ||
| 339 | const float r = std::abs(value); | ||
| 340 | |||
| 341 | // Return zero if value is smaller than the deadzone | ||
| 342 | if (r <= properties.deadzone || properties.deadzone == 1.0f) { | ||
| 343 | analog.value = 0; | ||
| 344 | return; | ||
| 345 | } | ||
| 346 | |||
| 347 | // Adjust range of value | ||
| 348 | const float deadzone_factor = | ||
| 349 | 1.0f / r * (r - properties.deadzone) / (1.0f - properties.deadzone); | ||
| 350 | value = value * deadzone_factor / properties.range; | ||
| 351 | |||
| 352 | // Invert direction if needed | ||
| 353 | if (properties.inverted) { | ||
| 354 | value = -value; | ||
| 355 | } | ||
| 356 | |||
| 357 | // Clamp value | ||
| 358 | if (clamp_value) { | ||
| 359 | value = std::clamp(value, -1.0f, 1.0f); | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, | ||
| 364 | bool clamp_value) { | ||
| 365 | const auto& properties_x = analog_x.properties; | ||
| 366 | const auto& properties_y = analog_y.properties; | ||
| 367 | float& raw_x = analog_x.raw_value; | ||
| 368 | float& raw_y = analog_y.raw_value; | ||
| 369 | float& x = analog_x.value; | ||
| 370 | float& y = analog_y.value; | ||
| 371 | |||
| 372 | if (!std::isnormal(raw_x)) { | ||
| 373 | raw_x = 0; | ||
| 374 | } | ||
| 375 | if (!std::isnormal(raw_y)) { | ||
| 376 | raw_y = 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | // Apply center offset | ||
| 380 | raw_x += properties_x.offset; | ||
| 381 | raw_y += properties_y.offset; | ||
| 382 | |||
| 383 | // Apply X scale correction from offset | ||
| 384 | if (std::abs(properties_x.offset) < 0.75f) { | ||
| 385 | if (raw_x > 0) { | ||
| 386 | raw_x /= 1 + properties_x.offset; | ||
| 387 | } else { | ||
| 388 | raw_x /= 1 - properties_x.offset; | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | // Apply Y scale correction from offset | ||
| 393 | if (std::abs(properties_y.offset) < 0.75f) { | ||
| 394 | if (raw_y > 0) { | ||
| 395 | raw_y /= 1 + properties_y.offset; | ||
| 396 | } else { | ||
| 397 | raw_y /= 1 - properties_y.offset; | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | // Invert direction if needed | ||
| 402 | raw_x = properties_x.inverted ? -raw_x : raw_x; | ||
| 403 | raw_y = properties_y.inverted ? -raw_y : raw_y; | ||
| 404 | |||
| 405 | // Set initial values to be formatted | ||
| 406 | x = raw_x; | ||
| 407 | y = raw_y; | ||
| 408 | |||
| 409 | // Calculate vector size | ||
| 410 | float r = x * x + y * y; | ||
| 411 | r = std::sqrt(r); | ||
| 412 | |||
| 413 | // TODO(German77): Use deadzone and range of both axis | ||
| 414 | |||
| 415 | // Return zero if values are smaller than the deadzone | ||
| 416 | if (r <= properties_x.deadzone || properties_x.deadzone >= 1.0f) { | ||
| 417 | x = 0; | ||
| 418 | y = 0; | ||
| 419 | return; | ||
| 420 | } | ||
| 421 | |||
| 422 | // Adjust range of joystick | ||
| 423 | const float deadzone_factor = | ||
| 424 | 1.0f / r * (r - properties_x.deadzone) / (1.0f - properties_x.deadzone); | ||
| 425 | x = x * deadzone_factor / properties_x.range; | ||
| 426 | y = y * deadzone_factor / properties_x.range; | ||
| 427 | r = r * deadzone_factor / properties_x.range; | ||
| 428 | |||
| 429 | // Normalize joystick | ||
| 430 | if (clamp_value && r > 1.0f) { | ||
| 431 | x /= r; | ||
| 432 | y /= r; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | } // namespace Core::HID | ||
diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h deleted file mode 100644 index c51c03e57..000000000 --- a/src/core/hid/input_converter.h +++ /dev/null | |||
| @@ -1,119 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | namespace Common::Input { | ||
| 7 | struct CallbackStatus; | ||
| 8 | enum class BatteryLevel : u32; | ||
| 9 | using BatteryStatus = BatteryLevel; | ||
| 10 | struct AnalogStatus; | ||
| 11 | struct ButtonStatus; | ||
| 12 | struct MotionStatus; | ||
| 13 | struct StickStatus; | ||
| 14 | struct TouchStatus; | ||
| 15 | struct TriggerStatus; | ||
| 16 | }; // namespace Common::Input | ||
| 17 | |||
| 18 | namespace Core::HID { | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Converts raw input data into a valid battery status. | ||
| 22 | * | ||
| 23 | * @param callback Supported callbacks: Analog, Battery, Trigger. | ||
| 24 | * @return A valid BatteryStatus object. | ||
| 25 | */ | ||
| 26 | Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback); | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Converts raw input data into a valid button status. Applies invert properties to the output. | ||
| 30 | * | ||
| 31 | * @param callback Supported callbacks: Analog, Button, Trigger. | ||
| 32 | * @return A valid TouchStatus object. | ||
| 33 | */ | ||
| 34 | Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback); | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Converts raw input data into a valid motion status. | ||
| 38 | * | ||
| 39 | * @param callback Supported callbacks: Motion. | ||
| 40 | * @return A valid TouchStatus object. | ||
| 41 | */ | ||
| 42 | Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback); | ||
| 43 | |||
| 44 | /** | ||
| 45 | * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert | ||
| 46 | * properties to the output. | ||
| 47 | * | ||
| 48 | * @param callback Supported callbacks: Stick. | ||
| 49 | * @return A valid StickStatus object. | ||
| 50 | */ | ||
| 51 | Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback); | ||
| 52 | |||
| 53 | /** | ||
| 54 | * Converts raw input data into a valid touch status. | ||
| 55 | * | ||
| 56 | * @param callback Supported callbacks: Touch. | ||
| 57 | * @return A valid TouchStatus object. | ||
| 58 | */ | ||
| 59 | Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback); | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and | ||
| 63 | * invert properties to the output. Button status uses the threshold property if necessary. | ||
| 64 | * | ||
| 65 | * @param callback Supported callbacks: Analog, Button, Trigger. | ||
| 66 | * @return A valid TriggerStatus object. | ||
| 67 | */ | ||
| 68 | Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Converts raw input data into a valid analog status. Applies offset, deadzone, range and | ||
| 72 | * invert properties to the output. | ||
| 73 | * | ||
| 74 | * @param callback Supported callbacks: Analog. | ||
| 75 | * @return A valid AnalogStatus object. | ||
| 76 | */ | ||
| 77 | Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); | ||
| 78 | |||
| 79 | /** | ||
| 80 | * Converts raw input data into a valid camera status. | ||
| 81 | * | ||
| 82 | * @param callback Supported callbacks: Camera. | ||
| 83 | * @return A valid CameraObject object. | ||
| 84 | */ | ||
| 85 | Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatus& callback); | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Converts raw input data into a valid nfc status. | ||
| 89 | * | ||
| 90 | * @param callback Supported callbacks: Nfc. | ||
| 91 | * @return A valid data tag vector. | ||
| 92 | */ | ||
| 93 | Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& callback); | ||
| 94 | |||
| 95 | /** | ||
| 96 | * Converts raw input data into a valid color status. | ||
| 97 | * | ||
| 98 | * @param callback Supported callbacks: Color. | ||
| 99 | * @return A valid Color object. | ||
| 100 | */ | ||
| 101 | Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback); | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Converts raw analog data into a valid analog value | ||
| 105 | * @param analog An analog object containing raw data and properties | ||
| 106 | * @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f. | ||
| 107 | */ | ||
| 108 | void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value); | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Converts raw stick data into a valid stick value | ||
| 112 | * @param analog_x raw analog data and properties for the x-axis | ||
| 113 | * @param analog_y raw analog data and properties for the y-axis | ||
| 114 | * @param clamp_value bool that determines if the value needs to be clamped into the unit circle. | ||
| 115 | */ | ||
| 116 | void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, | ||
| 117 | bool clamp_value); | ||
| 118 | |||
| 119 | } // namespace Core::HID | ||
diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp deleted file mode 100644 index 072f38a68..000000000 --- a/src/core/hid/input_interpreter.cpp +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hid/hid_types.h" | ||
| 6 | #include "core/hid/input_interpreter.h" | ||
| 7 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 8 | #include "core/hle/service/hid/hid_server.h" | ||
| 9 | #include "core/hle/service/hid/resource_manager.h" | ||
| 10 | #include "core/hle/service/sm/sm.h" | ||
| 11 | |||
| 12 | InputInterpreter::InputInterpreter(Core::System& system) | ||
| 13 | : npad{system.ServiceManager() | ||
| 14 | .GetService<Service::HID::IHidServer>("hid") | ||
| 15 | ->GetResourceManager() | ||
| 16 | ->GetNpad()} { | ||
| 17 | ResetButtonStates(); | ||
| 18 | } | ||
| 19 | |||
| 20 | InputInterpreter::~InputInterpreter() = default; | ||
| 21 | |||
| 22 | void InputInterpreter::PollInput() { | ||
| 23 | if (npad == nullptr) { | ||
| 24 | return; | ||
| 25 | } | ||
| 26 | const auto button_state = npad->GetAndResetPressState(); | ||
| 27 | |||
| 28 | previous_index = current_index; | ||
| 29 | current_index = (current_index + 1) % button_states.size(); | ||
| 30 | |||
| 31 | button_states[current_index] = button_state; | ||
| 32 | } | ||
| 33 | |||
| 34 | void InputInterpreter::ResetButtonStates() { | ||
| 35 | previous_index = 0; | ||
| 36 | current_index = 0; | ||
| 37 | |||
| 38 | button_states[0] = Core::HID::NpadButton::All; | ||
| 39 | |||
| 40 | for (std::size_t i = 1; i < button_states.size(); ++i) { | ||
| 41 | button_states[i] = Core::HID::NpadButton::None; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const { | ||
| 46 | return True(button_states[current_index] & button); | ||
| 47 | } | ||
| 48 | |||
| 49 | bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const { | ||
| 50 | const bool current_press = True(button_states[current_index] & button); | ||
| 51 | const bool previous_press = True(button_states[previous_index] & button); | ||
| 52 | |||
| 53 | return current_press && !previous_press; | ||
| 54 | } | ||
| 55 | |||
| 56 | bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const { | ||
| 57 | Core::HID::NpadButton held_buttons{button_states[0]}; | ||
| 58 | |||
| 59 | for (std::size_t i = 1; i < button_states.size(); ++i) { | ||
| 60 | held_buttons &= button_states[i]; | ||
| 61 | } | ||
| 62 | |||
| 63 | return True(held_buttons & button); | ||
| 64 | } | ||
diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h deleted file mode 100644 index 3569aac93..000000000 --- a/src/core/hid/input_interpreter.h +++ /dev/null | |||
| @@ -1,111 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | |||
| 10 | namespace Core { | ||
| 11 | class System; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Core::HID { | ||
| 15 | enum class NpadButton : u64; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Service::HID { | ||
| 19 | class NPad; | ||
| 20 | } | ||
| 21 | |||
| 22 | /** | ||
| 23 | * The InputInterpreter class interfaces with HID to retrieve button press states. | ||
| 24 | * Input is intended to be polled every 50ms so that a button is considered to be | ||
| 25 | * held down after 400ms has elapsed since the initial button press and subsequent | ||
| 26 | * repeated presses occur every 50ms. | ||
| 27 | */ | ||
| 28 | class InputInterpreter { | ||
| 29 | public: | ||
| 30 | explicit InputInterpreter(Core::System& system); | ||
| 31 | virtual ~InputInterpreter(); | ||
| 32 | |||
| 33 | /// Gets a button state from HID and inserts it into the array of button states. | ||
| 34 | void PollInput(); | ||
| 35 | |||
| 36 | /// Resets all the button states to their defaults. | ||
| 37 | void ResetButtonStates(); | ||
| 38 | |||
| 39 | /** | ||
| 40 | * Checks whether the button is pressed. | ||
| 41 | * | ||
| 42 | * @param button The button to check. | ||
| 43 | * | ||
| 44 | * @returns True when the button is pressed. | ||
| 45 | */ | ||
| 46 | [[nodiscard]] bool IsButtonPressed(Core::HID::NpadButton button) const; | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Checks whether any of the buttons in the parameter list is pressed. | ||
| 50 | * | ||
| 51 | * @tparam HIDButton The buttons to check. | ||
| 52 | * | ||
| 53 | * @returns True when at least one of the buttons is pressed. | ||
| 54 | */ | ||
| 55 | template <Core::HID::NpadButton... T> | ||
| 56 | [[nodiscard]] bool IsAnyButtonPressed() { | ||
| 57 | return (IsButtonPressed(T) || ...); | ||
| 58 | } | ||
| 59 | |||
| 60 | /** | ||
| 61 | * The specified button is considered to be pressed once | ||
| 62 | * if it is currently pressed and not pressed previously. | ||
| 63 | * | ||
| 64 | * @param button The button to check. | ||
| 65 | * | ||
| 66 | * @returns True when the button is pressed once. | ||
| 67 | */ | ||
| 68 | [[nodiscard]] bool IsButtonPressedOnce(Core::HID::NpadButton button) const; | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Checks whether any of the buttons in the parameter list is pressed once. | ||
| 72 | * | ||
| 73 | * @tparam T The buttons to check. | ||
| 74 | * | ||
| 75 | * @returns True when at least one of the buttons is pressed once. | ||
| 76 | */ | ||
| 77 | template <Core::HID::NpadButton... T> | ||
| 78 | [[nodiscard]] bool IsAnyButtonPressedOnce() const { | ||
| 79 | return (IsButtonPressedOnce(T) || ...); | ||
| 80 | } | ||
| 81 | |||
| 82 | /** | ||
| 83 | * The specified button is considered to be held down if it is pressed in all 9 button states. | ||
| 84 | * | ||
| 85 | * @param button The button to check. | ||
| 86 | * | ||
| 87 | * @returns True when the button is held down. | ||
| 88 | */ | ||
| 89 | [[nodiscard]] bool IsButtonHeld(Core::HID::NpadButton button) const; | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Checks whether any of the buttons in the parameter list is held down. | ||
| 93 | * | ||
| 94 | * @tparam T The buttons to check. | ||
| 95 | * | ||
| 96 | * @returns True when at least one of the buttons is held down. | ||
| 97 | */ | ||
| 98 | template <Core::HID::NpadButton... T> | ||
| 99 | [[nodiscard]] bool IsAnyButtonHeld() const { | ||
| 100 | return (IsButtonHeld(T) || ...); | ||
| 101 | } | ||
| 102 | |||
| 103 | private: | ||
| 104 | std::shared_ptr<Service::HID::NPad> npad; | ||
| 105 | |||
| 106 | /// Stores 9 consecutive button states polled from HID. | ||
| 107 | std::array<Core::HID::NpadButton, 9> button_states{}; | ||
| 108 | |||
| 109 | std::size_t previous_index{}; | ||
| 110 | std::size_t current_index{}; | ||
| 111 | }; | ||
diff --git a/src/core/hid/irs_types.h b/src/core/hid/irs_types.h deleted file mode 100644 index 0d1bfe53f..000000000 --- a/src/core/hid/irs_types.h +++ /dev/null | |||
| @@ -1,301 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_funcs.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | |||
| 10 | namespace Core::IrSensor { | ||
| 11 | |||
| 12 | // This is nn::irsensor::CameraAmbientNoiseLevel | ||
| 13 | enum class CameraAmbientNoiseLevel : u32 { | ||
| 14 | Low, | ||
| 15 | Medium, | ||
| 16 | High, | ||
| 17 | Unknown3, // This level can't be reached | ||
| 18 | }; | ||
| 19 | |||
| 20 | // This is nn::irsensor::CameraLightTarget | ||
| 21 | enum class CameraLightTarget : u32 { | ||
| 22 | AllLeds, | ||
| 23 | BrightLeds, | ||
| 24 | DimLeds, | ||
| 25 | None, | ||
| 26 | }; | ||
| 27 | |||
| 28 | // This is nn::irsensor::PackedCameraLightTarget | ||
| 29 | enum class PackedCameraLightTarget : u8 { | ||
| 30 | AllLeds, | ||
| 31 | BrightLeds, | ||
| 32 | DimLeds, | ||
| 33 | None, | ||
| 34 | }; | ||
| 35 | |||
| 36 | // This is nn::irsensor::AdaptiveClusteringMode | ||
| 37 | enum class AdaptiveClusteringMode : u32 { | ||
| 38 | StaticFov, | ||
| 39 | DynamicFov, | ||
| 40 | }; | ||
| 41 | |||
| 42 | // This is nn::irsensor::AdaptiveClusteringTargetDistance | ||
| 43 | enum class AdaptiveClusteringTargetDistance : u32 { | ||
| 44 | Near, | ||
| 45 | Middle, | ||
| 46 | Far, | ||
| 47 | }; | ||
| 48 | |||
| 49 | // This is nn::irsensor::ImageTransferProcessorFormat | ||
| 50 | enum class ImageTransferProcessorFormat : u32 { | ||
| 51 | Size320x240, | ||
| 52 | Size160x120, | ||
| 53 | Size80x60, | ||
| 54 | Size40x30, | ||
| 55 | Size20x15, | ||
| 56 | }; | ||
| 57 | |||
| 58 | // This is nn::irsensor::PackedImageTransferProcessorFormat | ||
| 59 | enum class PackedImageTransferProcessorFormat : u8 { | ||
| 60 | Size320x240, | ||
| 61 | Size160x120, | ||
| 62 | Size80x60, | ||
| 63 | Size40x30, | ||
| 64 | Size20x15, | ||
| 65 | }; | ||
| 66 | |||
| 67 | // This is nn::irsensor::IrCameraStatus | ||
| 68 | enum class IrCameraStatus : u32 { | ||
| 69 | Available, | ||
| 70 | Unsupported, | ||
| 71 | Unconnected, | ||
| 72 | }; | ||
| 73 | |||
| 74 | // This is nn::irsensor::IrCameraInternalStatus | ||
| 75 | enum class IrCameraInternalStatus : u32 { | ||
| 76 | Stopped, | ||
| 77 | FirmwareUpdateNeeded, | ||
| 78 | Unknown2, | ||
| 79 | Unknown3, | ||
| 80 | Unknown4, | ||
| 81 | FirmwareVersionRequested, | ||
| 82 | FirmwareVersionIsInvalid, | ||
| 83 | Ready, | ||
| 84 | Setting, | ||
| 85 | }; | ||
| 86 | |||
| 87 | // This is nn::irsensor::detail::StatusManager::IrSensorMode | ||
| 88 | enum class IrSensorMode : u64 { | ||
| 89 | None, | ||
| 90 | MomentProcessor, | ||
| 91 | ClusteringProcessor, | ||
| 92 | ImageTransferProcessor, | ||
| 93 | PointingProcessorMarker, | ||
| 94 | TeraPluginProcessor, | ||
| 95 | IrLedProcessor, | ||
| 96 | }; | ||
| 97 | |||
| 98 | // This is nn::irsensor::ImageProcessorStatus | ||
| 99 | enum ImageProcessorStatus : u32 { | ||
| 100 | Stopped, | ||
| 101 | Running, | ||
| 102 | }; | ||
| 103 | |||
| 104 | // This is nn::irsensor::HandAnalysisMode | ||
| 105 | enum class HandAnalysisMode : u32 { | ||
| 106 | None, | ||
| 107 | Silhouette, | ||
| 108 | Image, | ||
| 109 | SilhoueteAndImage, | ||
| 110 | SilhuetteOnly, | ||
| 111 | }; | ||
| 112 | |||
| 113 | // This is nn::irsensor::IrSensorFunctionLevel | ||
| 114 | enum class IrSensorFunctionLevel : u8 { | ||
| 115 | unknown0, | ||
| 116 | unknown1, | ||
| 117 | unknown2, | ||
| 118 | unknown3, | ||
| 119 | unknown4, | ||
| 120 | }; | ||
| 121 | |||
| 122 | // This is nn::irsensor::MomentProcessorPreprocess | ||
| 123 | enum class MomentProcessorPreprocess : u32 { | ||
| 124 | Unknown0, | ||
| 125 | Unknown1, | ||
| 126 | }; | ||
| 127 | |||
| 128 | // This is nn::irsensor::PackedMomentProcessorPreprocess | ||
| 129 | enum class PackedMomentProcessorPreprocess : u8 { | ||
| 130 | Unknown0, | ||
| 131 | Unknown1, | ||
| 132 | }; | ||
| 133 | |||
| 134 | // This is nn::irsensor::PointingStatus | ||
| 135 | enum class PointingStatus : u32 { | ||
| 136 | Unknown0, | ||
| 137 | Unknown1, | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct IrsRect { | ||
| 141 | s16 x; | ||
| 142 | s16 y; | ||
| 143 | s16 width; | ||
| 144 | s16 height; | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct IrsCentroid { | ||
| 148 | f32 x; | ||
| 149 | f32 y; | ||
| 150 | }; | ||
| 151 | |||
| 152 | struct CameraConfig { | ||
| 153 | u64 exposure_time; | ||
| 154 | CameraLightTarget light_target; | ||
| 155 | u32 gain; | ||
| 156 | bool is_negative_used; | ||
| 157 | INSERT_PADDING_BYTES(7); | ||
| 158 | }; | ||
| 159 | static_assert(sizeof(CameraConfig) == 0x18, "CameraConfig is an invalid size"); | ||
| 160 | |||
| 161 | struct PackedCameraConfig { | ||
| 162 | u64 exposure_time; | ||
| 163 | PackedCameraLightTarget light_target; | ||
| 164 | u8 gain; | ||
| 165 | bool is_negative_used; | ||
| 166 | INSERT_PADDING_BYTES(5); | ||
| 167 | }; | ||
| 168 | static_assert(sizeof(PackedCameraConfig) == 0x10, "PackedCameraConfig is an invalid size"); | ||
| 169 | |||
| 170 | // This is nn::irsensor::IrCameraHandle | ||
| 171 | struct IrCameraHandle { | ||
| 172 | u8 npad_id{}; | ||
| 173 | Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; | ||
| 174 | INSERT_PADDING_BYTES(2); | ||
| 175 | }; | ||
| 176 | static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size"); | ||
| 177 | |||
| 178 | // This is nn::irsensor::PackedMcuVersion | ||
| 179 | struct PackedMcuVersion { | ||
| 180 | u16 major; | ||
| 181 | u16 minor; | ||
| 182 | }; | ||
| 183 | static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size"); | ||
| 184 | |||
| 185 | // This is nn::irsensor::PackedMomentProcessorConfig | ||
| 186 | struct PackedMomentProcessorConfig { | ||
| 187 | PackedCameraConfig camera_config; | ||
| 188 | IrsRect window_of_interest; | ||
| 189 | PackedMcuVersion required_mcu_version; | ||
| 190 | PackedMomentProcessorPreprocess preprocess; | ||
| 191 | u8 preprocess_intensity_threshold; | ||
| 192 | INSERT_PADDING_BYTES(2); | ||
| 193 | }; | ||
| 194 | static_assert(sizeof(PackedMomentProcessorConfig) == 0x20, | ||
| 195 | "PackedMomentProcessorConfig is an invalid size"); | ||
| 196 | |||
| 197 | // This is nn::irsensor::PackedClusteringProcessorConfig | ||
| 198 | struct PackedClusteringProcessorConfig { | ||
| 199 | PackedCameraConfig camera_config; | ||
| 200 | IrsRect window_of_interest; | ||
| 201 | PackedMcuVersion required_mcu_version; | ||
| 202 | u32 pixel_count_min; | ||
| 203 | u32 pixel_count_max; | ||
| 204 | u8 object_intensity_min; | ||
| 205 | bool is_external_light_filter_enabled; | ||
| 206 | INSERT_PADDING_BYTES(2); | ||
| 207 | }; | ||
| 208 | static_assert(sizeof(PackedClusteringProcessorConfig) == 0x28, | ||
| 209 | "PackedClusteringProcessorConfig is an invalid size"); | ||
| 210 | |||
| 211 | // This is nn::irsensor::PackedImageTransferProcessorConfig | ||
| 212 | struct PackedImageTransferProcessorConfig { | ||
| 213 | PackedCameraConfig camera_config; | ||
| 214 | PackedMcuVersion required_mcu_version; | ||
| 215 | PackedImageTransferProcessorFormat format; | ||
| 216 | INSERT_PADDING_BYTES(3); | ||
| 217 | }; | ||
| 218 | static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18, | ||
| 219 | "PackedImageTransferProcessorConfig is an invalid size"); | ||
| 220 | |||
| 221 | // This is nn::irsensor::PackedTeraPluginProcessorConfig | ||
| 222 | struct PackedTeraPluginProcessorConfig { | ||
| 223 | PackedMcuVersion required_mcu_version; | ||
| 224 | u8 mode; | ||
| 225 | u8 unknown_1; | ||
| 226 | u8 unknown_2; | ||
| 227 | u8 unknown_3; | ||
| 228 | }; | ||
| 229 | static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8, | ||
| 230 | "PackedTeraPluginProcessorConfig is an invalid size"); | ||
| 231 | |||
| 232 | // This is nn::irsensor::PackedPointingProcessorConfig | ||
| 233 | struct PackedPointingProcessorConfig { | ||
| 234 | IrsRect window_of_interest; | ||
| 235 | PackedMcuVersion required_mcu_version; | ||
| 236 | }; | ||
| 237 | static_assert(sizeof(PackedPointingProcessorConfig) == 0xC, | ||
| 238 | "PackedPointingProcessorConfig is an invalid size"); | ||
| 239 | |||
| 240 | // This is nn::irsensor::PackedFunctionLevel | ||
| 241 | struct PackedFunctionLevel { | ||
| 242 | IrSensorFunctionLevel function_level; | ||
| 243 | INSERT_PADDING_BYTES(3); | ||
| 244 | }; | ||
| 245 | static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size"); | ||
| 246 | |||
| 247 | // This is nn::irsensor::PackedImageTransferProcessorExConfig | ||
| 248 | struct PackedImageTransferProcessorExConfig { | ||
| 249 | PackedCameraConfig camera_config; | ||
| 250 | PackedMcuVersion required_mcu_version; | ||
| 251 | PackedImageTransferProcessorFormat origin_format; | ||
| 252 | PackedImageTransferProcessorFormat trimming_format; | ||
| 253 | u16 trimming_start_x; | ||
| 254 | u16 trimming_start_y; | ||
| 255 | bool is_external_light_filter_enabled; | ||
| 256 | INSERT_PADDING_BYTES(5); | ||
| 257 | }; | ||
| 258 | static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20, | ||
| 259 | "PackedImageTransferProcessorExConfig is an invalid size"); | ||
| 260 | |||
| 261 | // This is nn::irsensor::PackedIrLedProcessorConfig | ||
| 262 | struct PackedIrLedProcessorConfig { | ||
| 263 | PackedMcuVersion required_mcu_version; | ||
| 264 | u8 light_target; | ||
| 265 | INSERT_PADDING_BYTES(3); | ||
| 266 | }; | ||
| 267 | static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8, | ||
| 268 | "PackedIrLedProcessorConfig is an invalid size"); | ||
| 269 | |||
| 270 | // This is nn::irsensor::HandAnalysisConfig | ||
| 271 | struct HandAnalysisConfig { | ||
| 272 | HandAnalysisMode mode; | ||
| 273 | }; | ||
| 274 | static_assert(sizeof(HandAnalysisConfig) == 0x4, "HandAnalysisConfig is an invalid size"); | ||
| 275 | |||
| 276 | // This is nn::irsensor::detail::ProcessorState contents are different for each processor | ||
| 277 | struct ProcessorState { | ||
| 278 | std::array<u8, 0xE20> processor_raw_data{}; | ||
| 279 | }; | ||
| 280 | static_assert(sizeof(ProcessorState) == 0xE20, "ProcessorState is an invalid size"); | ||
| 281 | |||
| 282 | // This is nn::irsensor::detail::DeviceFormat | ||
| 283 | struct DeviceFormat { | ||
| 284 | Core::IrSensor::IrCameraStatus camera_status{Core::IrSensor::IrCameraStatus::Unconnected}; | ||
| 285 | Core::IrSensor::IrCameraInternalStatus camera_internal_status{ | ||
| 286 | Core::IrSensor::IrCameraInternalStatus::Ready}; | ||
| 287 | Core::IrSensor::IrSensorMode mode{Core::IrSensor::IrSensorMode::None}; | ||
| 288 | ProcessorState state{}; | ||
| 289 | }; | ||
| 290 | static_assert(sizeof(DeviceFormat) == 0xE30, "DeviceFormat is an invalid size"); | ||
| 291 | |||
| 292 | // This is nn::irsensor::ImageTransferProcessorState | ||
| 293 | struct ImageTransferProcessorState { | ||
| 294 | u64 sampling_number; | ||
| 295 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 296 | INSERT_PADDING_BYTES(4); | ||
| 297 | }; | ||
| 298 | static_assert(sizeof(ImageTransferProcessorState) == 0x10, | ||
| 299 | "ImageTransferProcessorState is an invalid size"); | ||
| 300 | |||
| 301 | } // namespace Core::IrSensor | ||
diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp deleted file mode 100644 index f56f2ae1d..000000000 --- a/src/core/hid/motion_input.cpp +++ /dev/null | |||
| @@ -1,357 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <cmath> | ||
| 5 | |||
| 6 | #include "common/math_util.h" | ||
| 7 | #include "core/hid/motion_input.h" | ||
| 8 | |||
| 9 | namespace Core::HID { | ||
| 10 | |||
| 11 | MotionInput::MotionInput() { | ||
| 12 | // Initialize PID constants with default values | ||
| 13 | SetPID(0.3f, 0.005f, 0.0f); | ||
| 14 | SetGyroThreshold(ThresholdStandard); | ||
| 15 | ResetQuaternion(); | ||
| 16 | ResetRotations(); | ||
| 17 | } | ||
| 18 | |||
| 19 | void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) { | ||
| 20 | kp = new_kp; | ||
| 21 | ki = new_ki; | ||
| 22 | kd = new_kd; | ||
| 23 | } | ||
| 24 | |||
| 25 | void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) { | ||
| 26 | accel = acceleration; | ||
| 27 | |||
| 28 | accel.x = std::clamp(accel.x, -AccelMaxValue, AccelMaxValue); | ||
| 29 | accel.y = std::clamp(accel.y, -AccelMaxValue, AccelMaxValue); | ||
| 30 | accel.z = std::clamp(accel.z, -AccelMaxValue, AccelMaxValue); | ||
| 31 | } | ||
| 32 | |||
| 33 | void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { | ||
| 34 | gyro = gyroscope - gyro_bias; | ||
| 35 | |||
| 36 | gyro.x = std::clamp(gyro.x, -GyroMaxValue, GyroMaxValue); | ||
| 37 | gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue); | ||
| 38 | gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue); | ||
| 39 | |||
| 40 | // Auto adjust gyro_bias to minimize drift | ||
| 41 | if (!IsMoving(IsAtRestRelaxed)) { | ||
| 42 | gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f); | ||
| 43 | } | ||
| 44 | |||
| 45 | // Adjust drift when calibration mode is enabled | ||
| 46 | if (calibration_mode) { | ||
| 47 | gyro_bias = (gyro_bias * 0.99f) + (gyroscope * 0.01f); | ||
| 48 | StopCalibration(); | ||
| 49 | } | ||
| 50 | |||
| 51 | if (gyro.Length() < gyro_threshold * user_gyro_threshold) { | ||
| 52 | gyro = {}; | ||
| 53 | } else { | ||
| 54 | only_accelerometer = false; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) { | ||
| 59 | quat = quaternion; | ||
| 60 | } | ||
| 61 | |||
| 62 | void MotionInput::SetEulerAngles(const Common::Vec3f& euler_angles) { | ||
| 63 | const float cr = std::cos(euler_angles.x * 0.5f); | ||
| 64 | const float sr = std::sin(euler_angles.x * 0.5f); | ||
| 65 | const float cp = std::cos(euler_angles.y * 0.5f); | ||
| 66 | const float sp = std::sin(euler_angles.y * 0.5f); | ||
| 67 | const float cy = std::cos(euler_angles.z * 0.5f); | ||
| 68 | const float sy = std::sin(euler_angles.z * 0.5f); | ||
| 69 | |||
| 70 | quat.w = cr * cp * cy + sr * sp * sy; | ||
| 71 | quat.xyz.x = sr * cp * cy - cr * sp * sy; | ||
| 72 | quat.xyz.y = cr * sp * cy + sr * cp * sy; | ||
| 73 | quat.xyz.z = cr * cp * sy - sr * sp * cy; | ||
| 74 | } | ||
| 75 | |||
| 76 | void MotionInput::SetGyroBias(const Common::Vec3f& bias) { | ||
| 77 | gyro_bias = bias; | ||
| 78 | } | ||
| 79 | |||
| 80 | void MotionInput::SetGyroThreshold(f32 threshold) { | ||
| 81 | gyro_threshold = threshold; | ||
| 82 | } | ||
| 83 | |||
| 84 | void MotionInput::SetUserGyroThreshold(f32 threshold) { | ||
| 85 | user_gyro_threshold = threshold / ThresholdStandard; | ||
| 86 | } | ||
| 87 | |||
| 88 | void MotionInput::EnableReset(bool reset) { | ||
| 89 | reset_enabled = reset; | ||
| 90 | } | ||
| 91 | |||
| 92 | void MotionInput::ResetRotations() { | ||
| 93 | rotations = {}; | ||
| 94 | } | ||
| 95 | |||
| 96 | void MotionInput::ResetQuaternion() { | ||
| 97 | quat = {{0.0f, 0.0f, -1.0f}, 0.0f}; | ||
| 98 | } | ||
| 99 | |||
| 100 | bool MotionInput::IsMoving(f32 sensitivity) const { | ||
| 101 | return gyro.Length() >= sensitivity || accel.Length() <= 0.9f || accel.Length() >= 1.1f; | ||
| 102 | } | ||
| 103 | |||
| 104 | bool MotionInput::IsCalibrated(f32 sensitivity) const { | ||
| 105 | return real_error.Length() < sensitivity; | ||
| 106 | } | ||
| 107 | |||
| 108 | void MotionInput::UpdateRotation(u64 elapsed_time) { | ||
| 109 | const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f; | ||
| 110 | if (sample_period > 0.1f) { | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | rotations += gyro * sample_period; | ||
| 114 | } | ||
| 115 | |||
| 116 | void MotionInput::Calibrate() { | ||
| 117 | calibration_mode = true; | ||
| 118 | calibration_counter = 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | void MotionInput::StopCalibration() { | ||
| 122 | if (calibration_counter++ > CalibrationSamples) { | ||
| 123 | calibration_mode = false; | ||
| 124 | ResetQuaternion(); | ||
| 125 | ResetRotations(); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | // Based on Madgwick's implementation of Mayhony's AHRS algorithm. | ||
| 130 | // https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs | ||
| 131 | void MotionInput::UpdateOrientation(u64 elapsed_time) { | ||
| 132 | if (!IsCalibrated(0.1f)) { | ||
| 133 | ResetOrientation(); | ||
| 134 | } | ||
| 135 | // Short name local variable for readability | ||
| 136 | f32 q1 = quat.w; | ||
| 137 | f32 q2 = quat.xyz[0]; | ||
| 138 | f32 q3 = quat.xyz[1]; | ||
| 139 | f32 q4 = quat.xyz[2]; | ||
| 140 | const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f; | ||
| 141 | |||
| 142 | // Ignore invalid elapsed time | ||
| 143 | if (sample_period > 0.1f) { | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | |||
| 147 | const auto normal_accel = accel.Normalized(); | ||
| 148 | auto rad_gyro = gyro * Common::PI * 2; | ||
| 149 | const f32 swap = rad_gyro.x; | ||
| 150 | rad_gyro.x = rad_gyro.y; | ||
| 151 | rad_gyro.y = -swap; | ||
| 152 | rad_gyro.z = -rad_gyro.z; | ||
| 153 | |||
| 154 | // Clear gyro values if there is no gyro present | ||
| 155 | if (only_accelerometer) { | ||
| 156 | rad_gyro.x = 0; | ||
| 157 | rad_gyro.y = 0; | ||
| 158 | rad_gyro.z = 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | // Ignore drift correction if acceleration is not reliable | ||
| 162 | if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) { | ||
| 163 | const f32 ax = -normal_accel.x; | ||
| 164 | const f32 ay = normal_accel.y; | ||
| 165 | const f32 az = -normal_accel.z; | ||
| 166 | |||
| 167 | // Estimated direction of gravity | ||
| 168 | const f32 vx = 2.0f * (q2 * q4 - q1 * q3); | ||
| 169 | const f32 vy = 2.0f * (q1 * q2 + q3 * q4); | ||
| 170 | const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; | ||
| 171 | |||
| 172 | // Error is cross product between estimated direction and measured direction of gravity | ||
| 173 | const Common::Vec3f new_real_error = { | ||
| 174 | az * vx - ax * vz, | ||
| 175 | ay * vz - az * vy, | ||
| 176 | ax * vy - ay * vx, | ||
| 177 | }; | ||
| 178 | |||
| 179 | derivative_error = new_real_error - real_error; | ||
| 180 | real_error = new_real_error; | ||
| 181 | |||
| 182 | // Prevent integral windup | ||
| 183 | if (ki != 0.0f && !IsCalibrated(0.05f)) { | ||
| 184 | integral_error += real_error; | ||
| 185 | } else { | ||
| 186 | integral_error = {}; | ||
| 187 | } | ||
| 188 | |||
| 189 | // Apply feedback terms | ||
| 190 | if (!only_accelerometer) { | ||
| 191 | rad_gyro += kp * real_error; | ||
| 192 | rad_gyro += ki * integral_error; | ||
| 193 | rad_gyro += kd * derivative_error; | ||
| 194 | } else { | ||
| 195 | // Give more weight to accelerometer values to compensate for the lack of gyro | ||
| 196 | rad_gyro += 35.0f * kp * real_error; | ||
| 197 | rad_gyro += 10.0f * ki * integral_error; | ||
| 198 | rad_gyro += 10.0f * kd * derivative_error; | ||
| 199 | |||
| 200 | // Emulate gyro values for games that need them | ||
| 201 | gyro.x = -rad_gyro.y; | ||
| 202 | gyro.y = rad_gyro.x; | ||
| 203 | gyro.z = -rad_gyro.z; | ||
| 204 | UpdateRotation(elapsed_time); | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | const f32 gx = rad_gyro.y; | ||
| 209 | const f32 gy = rad_gyro.x; | ||
| 210 | const f32 gz = rad_gyro.z; | ||
| 211 | |||
| 212 | // Integrate rate of change of quaternion | ||
| 213 | const f32 pa = q2; | ||
| 214 | const f32 pb = q3; | ||
| 215 | const f32 pc = q4; | ||
| 216 | q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period); | ||
| 217 | q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period); | ||
| 218 | q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); | ||
| 219 | q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); | ||
| 220 | |||
| 221 | quat.w = q1; | ||
| 222 | quat.xyz[0] = q2; | ||
| 223 | quat.xyz[1] = q3; | ||
| 224 | quat.xyz[2] = q4; | ||
| 225 | quat = quat.Normalized(); | ||
| 226 | } | ||
| 227 | |||
| 228 | std::array<Common::Vec3f, 3> MotionInput::GetOrientation() const { | ||
| 229 | const Common::Quaternion<float> quad{ | ||
| 230 | .xyz = {-quat.xyz[1], -quat.xyz[0], -quat.w}, | ||
| 231 | .w = -quat.xyz[2], | ||
| 232 | }; | ||
| 233 | const std::array<float, 16> matrix4x4 = quad.ToMatrix(); | ||
| 234 | |||
| 235 | return {Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]), | ||
| 236 | Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]), | ||
| 237 | Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])}; | ||
| 238 | } | ||
| 239 | |||
| 240 | Common::Vec3f MotionInput::GetAcceleration() const { | ||
| 241 | return accel; | ||
| 242 | } | ||
| 243 | |||
| 244 | Common::Vec3f MotionInput::GetGyroscope() const { | ||
| 245 | return gyro; | ||
| 246 | } | ||
| 247 | |||
| 248 | Common::Vec3f MotionInput::GetGyroBias() const { | ||
| 249 | return gyro_bias; | ||
| 250 | } | ||
| 251 | |||
| 252 | Common::Quaternion<f32> MotionInput::GetQuaternion() const { | ||
| 253 | return quat; | ||
| 254 | } | ||
| 255 | |||
| 256 | Common::Vec3f MotionInput::GetRotations() const { | ||
| 257 | return rotations; | ||
| 258 | } | ||
| 259 | |||
| 260 | Common::Vec3f MotionInput::GetEulerAngles() const { | ||
| 261 | // roll (x-axis rotation) | ||
| 262 | const float sinr_cosp = 2 * (quat.w * quat.xyz.x + quat.xyz.y * quat.xyz.z); | ||
| 263 | const float cosr_cosp = 1 - 2 * (quat.xyz.x * quat.xyz.x + quat.xyz.y * quat.xyz.y); | ||
| 264 | |||
| 265 | // pitch (y-axis rotation) | ||
| 266 | const float sinp = std::sqrt(1 + 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); | ||
| 267 | const float cosp = std::sqrt(1 - 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); | ||
| 268 | |||
| 269 | // yaw (z-axis rotation) | ||
| 270 | const float siny_cosp = 2 * (quat.w * quat.xyz.z + quat.xyz.x * quat.xyz.y); | ||
| 271 | const float cosy_cosp = 1 - 2 * (quat.xyz.y * quat.xyz.y + quat.xyz.z * quat.xyz.z); | ||
| 272 | |||
| 273 | return { | ||
| 274 | std::atan2(sinr_cosp, cosr_cosp), | ||
| 275 | 2 * std::atan2(sinp, cosp) - Common::PI / 2, | ||
| 276 | std::atan2(siny_cosp, cosy_cosp), | ||
| 277 | }; | ||
| 278 | } | ||
| 279 | |||
| 280 | void MotionInput::ResetOrientation() { | ||
| 281 | if (!reset_enabled || only_accelerometer) { | ||
| 282 | return; | ||
| 283 | } | ||
| 284 | if (!IsMoving(IsAtRestRelaxed) && accel.z <= -0.9f) { | ||
| 285 | ++reset_counter; | ||
| 286 | if (reset_counter > 900) { | ||
| 287 | quat.w = 0; | ||
| 288 | quat.xyz[0] = 0; | ||
| 289 | quat.xyz[1] = 0; | ||
| 290 | quat.xyz[2] = -1; | ||
| 291 | SetOrientationFromAccelerometer(); | ||
| 292 | integral_error = {}; | ||
| 293 | reset_counter = 0; | ||
| 294 | } | ||
| 295 | } else { | ||
| 296 | reset_counter = 0; | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | void MotionInput::SetOrientationFromAccelerometer() { | ||
| 301 | int iterations = 0; | ||
| 302 | const f32 sample_period = 0.015f; | ||
| 303 | |||
| 304 | const auto normal_accel = accel.Normalized(); | ||
| 305 | |||
| 306 | while (!IsCalibrated(0.01f) && ++iterations < 100) { | ||
| 307 | // Short name local variable for readability | ||
| 308 | f32 q1 = quat.w; | ||
| 309 | f32 q2 = quat.xyz[0]; | ||
| 310 | f32 q3 = quat.xyz[1]; | ||
| 311 | f32 q4 = quat.xyz[2]; | ||
| 312 | |||
| 313 | Common::Vec3f rad_gyro; | ||
| 314 | const f32 ax = -normal_accel.x; | ||
| 315 | const f32 ay = normal_accel.y; | ||
| 316 | const f32 az = -normal_accel.z; | ||
| 317 | |||
| 318 | // Estimated direction of gravity | ||
| 319 | const f32 vx = 2.0f * (q2 * q4 - q1 * q3); | ||
| 320 | const f32 vy = 2.0f * (q1 * q2 + q3 * q4); | ||
| 321 | const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; | ||
| 322 | |||
| 323 | // Error is cross product between estimated direction and measured direction of gravity | ||
| 324 | const Common::Vec3f new_real_error = { | ||
| 325 | az * vx - ax * vz, | ||
| 326 | ay * vz - az * vy, | ||
| 327 | ax * vy - ay * vx, | ||
| 328 | }; | ||
| 329 | |||
| 330 | derivative_error = new_real_error - real_error; | ||
| 331 | real_error = new_real_error; | ||
| 332 | |||
| 333 | rad_gyro += 10.0f * kp * real_error; | ||
| 334 | rad_gyro += 5.0f * ki * integral_error; | ||
| 335 | rad_gyro += 10.0f * kd * derivative_error; | ||
| 336 | |||
| 337 | const f32 gx = rad_gyro.y; | ||
| 338 | const f32 gy = rad_gyro.x; | ||
| 339 | const f32 gz = rad_gyro.z; | ||
| 340 | |||
| 341 | // Integrate rate of change of quaternion | ||
| 342 | const f32 pa = q2; | ||
| 343 | const f32 pb = q3; | ||
| 344 | const f32 pc = q4; | ||
| 345 | q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period); | ||
| 346 | q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period); | ||
| 347 | q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); | ||
| 348 | q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); | ||
| 349 | |||
| 350 | quat.w = q1; | ||
| 351 | quat.xyz[0] = q2; | ||
| 352 | quat.xyz[1] = q3; | ||
| 353 | quat.xyz[2] = q4; | ||
| 354 | quat = quat.Normalized(); | ||
| 355 | } | ||
| 356 | } | ||
| 357 | } // namespace Core::HID | ||
diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h deleted file mode 100644 index 11678983d..000000000 --- a/src/core/hid/motion_input.h +++ /dev/null | |||
| @@ -1,119 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "common/quaternion.h" | ||
| 8 | #include "common/vector_math.h" | ||
| 9 | |||
| 10 | namespace Core::HID { | ||
| 11 | |||
| 12 | class MotionInput { | ||
| 13 | public: | ||
| 14 | static constexpr float ThresholdLoose = 0.01f; | ||
| 15 | static constexpr float ThresholdStandard = 0.007f; | ||
| 16 | static constexpr float ThresholdThight = 0.002f; | ||
| 17 | |||
| 18 | static constexpr float IsAtRestRelaxed = 0.05f; | ||
| 19 | static constexpr float IsAtRestLoose = 0.02f; | ||
| 20 | static constexpr float IsAtRestStandard = 0.01f; | ||
| 21 | static constexpr float IsAtRestThight = 0.005f; | ||
| 22 | |||
| 23 | static constexpr float GyroMaxValue = 5.0f; | ||
| 24 | static constexpr float AccelMaxValue = 7.0f; | ||
| 25 | |||
| 26 | static constexpr std::size_t CalibrationSamples = 300; | ||
| 27 | |||
| 28 | explicit MotionInput(); | ||
| 29 | |||
| 30 | MotionInput(const MotionInput&) = default; | ||
| 31 | MotionInput& operator=(const MotionInput&) = default; | ||
| 32 | |||
| 33 | MotionInput(MotionInput&&) = default; | ||
| 34 | MotionInput& operator=(MotionInput&&) = default; | ||
| 35 | |||
| 36 | void SetPID(f32 new_kp, f32 new_ki, f32 new_kd); | ||
| 37 | void SetAcceleration(const Common::Vec3f& acceleration); | ||
| 38 | void SetGyroscope(const Common::Vec3f& gyroscope); | ||
| 39 | void SetQuaternion(const Common::Quaternion<f32>& quaternion); | ||
| 40 | void SetEulerAngles(const Common::Vec3f& euler_angles); | ||
| 41 | void SetGyroBias(const Common::Vec3f& bias); | ||
| 42 | void SetGyroThreshold(f32 threshold); | ||
| 43 | |||
| 44 | /// Applies a modifier on top of the normal gyro threshold | ||
| 45 | void SetUserGyroThreshold(f32 threshold); | ||
| 46 | |||
| 47 | void EnableReset(bool reset); | ||
| 48 | void ResetRotations(); | ||
| 49 | void ResetQuaternion(); | ||
| 50 | |||
| 51 | void UpdateRotation(u64 elapsed_time); | ||
| 52 | void UpdateOrientation(u64 elapsed_time); | ||
| 53 | |||
| 54 | void Calibrate(); | ||
| 55 | |||
| 56 | [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; | ||
| 57 | [[nodiscard]] Common::Vec3f GetAcceleration() const; | ||
| 58 | [[nodiscard]] Common::Vec3f GetGyroscope() const; | ||
| 59 | [[nodiscard]] Common::Vec3f GetGyroBias() const; | ||
| 60 | [[nodiscard]] Common::Vec3f GetRotations() const; | ||
| 61 | [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; | ||
| 62 | [[nodiscard]] Common::Vec3f GetEulerAngles() const; | ||
| 63 | |||
| 64 | [[nodiscard]] bool IsMoving(f32 sensitivity) const; | ||
| 65 | [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; | ||
| 66 | |||
| 67 | private: | ||
| 68 | void StopCalibration(); | ||
| 69 | void ResetOrientation(); | ||
| 70 | void SetOrientationFromAccelerometer(); | ||
| 71 | |||
| 72 | // PID constants | ||
| 73 | f32 kp; | ||
| 74 | f32 ki; | ||
| 75 | f32 kd; | ||
| 76 | |||
| 77 | // PID errors | ||
| 78 | Common::Vec3f real_error; | ||
| 79 | Common::Vec3f integral_error; | ||
| 80 | Common::Vec3f derivative_error; | ||
| 81 | |||
| 82 | // Quaternion containing the device orientation | ||
| 83 | Common::Quaternion<f32> quat; | ||
| 84 | |||
| 85 | // Number of full rotations in each axis | ||
| 86 | Common::Vec3f rotations; | ||
| 87 | |||
| 88 | // Acceleration vector measurement in G force | ||
| 89 | Common::Vec3f accel; | ||
| 90 | |||
| 91 | // Gyroscope vector measurement in radians/s. | ||
| 92 | Common::Vec3f gyro; | ||
| 93 | |||
| 94 | // Vector to be subtracted from gyro measurements | ||
| 95 | Common::Vec3f gyro_bias; | ||
| 96 | |||
| 97 | // Minimum gyro amplitude to detect if the device is moving | ||
| 98 | f32 gyro_threshold = 0.0f; | ||
| 99 | |||
| 100 | // Multiplies gyro_threshold by this value | ||
| 101 | f32 user_gyro_threshold = 0.0f; | ||
| 102 | |||
| 103 | // Number of invalid sequential data | ||
| 104 | u32 reset_counter = 0; | ||
| 105 | |||
| 106 | // If the provided data is invalid the device will be autocalibrated | ||
| 107 | bool reset_enabled = true; | ||
| 108 | |||
| 109 | // Use accelerometer values to calculate position | ||
| 110 | bool only_accelerometer = true; | ||
| 111 | |||
| 112 | // When enabled it will aggressively adjust for gyro drift | ||
| 113 | bool calibration_mode = false; | ||
| 114 | |||
| 115 | // Used to auto disable calibration mode | ||
| 116 | std::size_t calibration_counter = 0; | ||
| 117 | }; | ||
| 118 | |||
| 119 | } // namespace Core::HID | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 97eb56ff0..9e05bdafa 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/registered_cache.h" | 14 | #include "core/file_sys/registered_cache.h" |
| 15 | #include "core/file_sys/savedata_factory.h" | 15 | #include "core/file_sys/savedata_factory.h" |
| 16 | #include "core/hid/hid_types.h" | ||
| 17 | #include "core/hle/kernel/k_event.h" | 16 | #include "core/hle/kernel/k_event.h" |
| 18 | #include "core/hle/kernel/k_transfer_memory.h" | 17 | #include "core/hle/kernel/k_transfer_memory.h" |
| 19 | #include "core/hle/result.h" | 18 | #include "core/hle/result.h" |
| @@ -37,7 +36,6 @@ | |||
| 37 | #include "core/hle/service/caps/caps_su.h" | 36 | #include "core/hle/service/caps/caps_su.h" |
| 38 | #include "core/hle/service/caps/caps_types.h" | 37 | #include "core/hle/service/caps/caps_types.h" |
| 39 | #include "core/hle/service/filesystem/filesystem.h" | 38 | #include "core/hle/service/filesystem/filesystem.h" |
| 40 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 41 | #include "core/hle/service/ipc_helpers.h" | 39 | #include "core/hle/service/ipc_helpers.h" |
| 42 | #include "core/hle/service/ns/ns.h" | 40 | #include "core/hle/service/ns/ns.h" |
| 43 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | 41 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" |
| @@ -48,6 +46,8 @@ | |||
| 48 | #include "core/hle/service/vi/vi.h" | 46 | #include "core/hle/service/vi/vi.h" |
| 49 | #include "core/hle/service/vi/vi_results.h" | 47 | #include "core/hle/service/vi/vi_results.h" |
| 50 | #include "core/memory.h" | 48 | #include "core/memory.h" |
| 49 | #include "hid_core/hid_types.h" | ||
| 50 | #include "hid_core/resources/npad/npad.h" | ||
| 51 | 51 | ||
| 52 | namespace Service::AM { | 52 | namespace Service::AM { |
| 53 | 53 | ||
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp index 3906c0fa4..c2ff444a6 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.cpp +++ b/src/core/hle/service/am/applets/applet_cabinet.cpp | |||
| @@ -5,13 +5,13 @@ | |||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/frontend/applets/cabinet.h" | 7 | #include "core/frontend/applets/cabinet.h" |
| 8 | #include "core/hid/hid_core.h" | ||
| 9 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| 10 | #include "core/hle/kernel/k_readable_event.h" | 9 | #include "core/hle/kernel/k_readable_event.h" |
| 11 | #include "core/hle/service/am/am.h" | 10 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/applet_cabinet.h" | 11 | #include "core/hle/service/am/applets/applet_cabinet.h" |
| 13 | #include "core/hle/service/mii/mii_manager.h" | 12 | #include "core/hle/service/mii/mii_manager.h" |
| 14 | #include "core/hle/service/nfc/common/device.h" | 13 | #include "core/hle/service/nfc/common/device.h" |
| 14 | #include "hid_core/hid_core.h" | ||
| 15 | 15 | ||
| 16 | namespace Service::AM::Applets { | 16 | namespace Service::AM::Applets { |
| 17 | 17 | ||
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp index 9840d2547..0e4d9cc39 100644 --- a/src/core/hle/service/am/applets/applet_controller.cpp +++ b/src/core/hle/service/am/applets/applet_controller.cpp | |||
| @@ -9,13 +9,13 @@ | |||
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/frontend/applets/controller.h" | 11 | #include "core/frontend/applets/controller.h" |
| 12 | #include "core/hid/emulated_controller.h" | ||
| 13 | #include "core/hid/hid_core.h" | ||
| 14 | #include "core/hid/hid_types.h" | ||
| 15 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 16 | #include "core/hle/service/am/am.h" | 13 | #include "core/hle/service/am/am.h" |
| 17 | #include "core/hle/service/am/applets/applet_controller.h" | 14 | #include "core/hle/service/am/applets/applet_controller.h" |
| 18 | #include "core/hle/service/hid/controllers/npad.h" | 15 | #include "hid_core/frontend/emulated_controller.h" |
| 16 | #include "hid_core/hid_core.h" | ||
| 17 | #include "hid_core/hid_types.h" | ||
| 18 | #include "hid_core/resources/npad/npad.h" | ||
| 19 | 19 | ||
| 20 | namespace Service::AM::Applets { | 20 | namespace Service::AM::Applets { |
| 21 | 21 | ||
diff --git a/src/core/hle/service/hid/controllers/applet_resource.cpp b/src/core/hle/service/hid/controllers/applet_resource.cpp deleted file mode 100644 index b4ff663c2..000000000 --- a/src/core/hle/service/hid/controllers/applet_resource.cpp +++ /dev/null | |||
| @@ -1,329 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 6 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | #include "core/hle/service/hid/errors.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | AppletResource::AppletResource(Core::System& system_) : system{system_} {} | ||
| 13 | |||
| 14 | AppletResource::~AppletResource() = default; | ||
| 15 | |||
| 16 | Result AppletResource::CreateAppletResource(u64 aruid) { | ||
| 17 | const u64 index = GetIndexFromAruid(aruid); | ||
| 18 | |||
| 19 | if (index >= AruidIndexMax) { | ||
| 20 | return ResultAruidNotRegistered; | ||
| 21 | } | ||
| 22 | |||
| 23 | if (data[index].flag.is_assigned) { | ||
| 24 | return ResultAruidAlreadyRegistered; | ||
| 25 | } | ||
| 26 | |||
| 27 | auto& shared_memory = shared_memory_holder[index]; | ||
| 28 | if (!shared_memory.IsMapped()) { | ||
| 29 | const Result result = shared_memory.Initialize(system); | ||
| 30 | if (result.IsError()) { | ||
| 31 | return result; | ||
| 32 | } | ||
| 33 | if (shared_memory.GetAddress() == nullptr) { | ||
| 34 | shared_memory.Finalize(); | ||
| 35 | return ResultSharedMemoryNotInitialized; | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | auto* shared_memory_format = shared_memory.GetAddress(); | ||
| 40 | if (shared_memory_format != nullptr) { | ||
| 41 | shared_memory_format->Initialize(); | ||
| 42 | } | ||
| 43 | |||
| 44 | data[index].shared_memory_format = shared_memory_format; | ||
| 45 | data[index].flag.is_assigned.Assign(true); | ||
| 46 | // TODO: InitializeSixAxisControllerConfig(false); | ||
| 47 | active_aruid = aruid; | ||
| 48 | return ResultSuccess; | ||
| 49 | } | ||
| 50 | |||
| 51 | Result AppletResource::RegisterAppletResourceUserId(u64 aruid, bool enable_input) { | ||
| 52 | const u64 index = GetIndexFromAruid(aruid); | ||
| 53 | |||
| 54 | if (index < AruidIndexMax) { | ||
| 55 | return ResultAruidAlreadyRegistered; | ||
| 56 | } | ||
| 57 | |||
| 58 | std::size_t data_index = AruidIndexMax; | ||
| 59 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 60 | if (!data[i].flag.is_initialized) { | ||
| 61 | data_index = i; | ||
| 62 | break; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | if (data_index == AruidIndexMax) { | ||
| 67 | return ResultAruidNoAvailableEntries; | ||
| 68 | } | ||
| 69 | |||
| 70 | AruidData& aruid_data = data[data_index]; | ||
| 71 | |||
| 72 | aruid_data.aruid = aruid; | ||
| 73 | aruid_data.flag.is_initialized.Assign(true); | ||
| 74 | if (enable_input) { | ||
| 75 | aruid_data.flag.enable_pad_input.Assign(true); | ||
| 76 | aruid_data.flag.enable_six_axis_sensor.Assign(true); | ||
| 77 | aruid_data.flag.bit_18.Assign(true); | ||
| 78 | aruid_data.flag.enable_touchscreen.Assign(true); | ||
| 79 | } | ||
| 80 | |||
| 81 | data_index = AruidIndexMax; | ||
| 82 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 83 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 84 | if (registration_list.aruid[i] != aruid) { | ||
| 85 | continue; | ||
| 86 | } | ||
| 87 | data_index = i; | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | if (registration_list.flag[i] == RegistrationStatus::None) { | ||
| 91 | data_index = i; | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | if (data_index == AruidIndexMax) { | ||
| 97 | return ResultSuccess; | ||
| 98 | } | ||
| 99 | |||
| 100 | registration_list.flag[data_index] = RegistrationStatus::Initialized; | ||
| 101 | registration_list.aruid[data_index] = aruid; | ||
| 102 | |||
| 103 | return ResultSuccess; | ||
| 104 | } | ||
| 105 | |||
| 106 | void AppletResource::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 107 | u64 index = GetIndexFromAruid(aruid); | ||
| 108 | |||
| 109 | if (index < AruidIndexMax) { | ||
| 110 | if (data[index].flag.is_assigned) { | ||
| 111 | data[index].shared_memory_format = nullptr; | ||
| 112 | data[index].flag.is_assigned.Assign(false); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | index = GetIndexFromAruid(aruid); | ||
| 117 | if (index < AruidIndexMax) { | ||
| 118 | DestroySevenSixAxisTransferMemory(); | ||
| 119 | data[index].flag.raw = 0; | ||
| 120 | data[index].aruid = 0; | ||
| 121 | |||
| 122 | index = GetIndexFromAruid(aruid); | ||
| 123 | if (index < AruidIndexMax) { | ||
| 124 | registration_list.flag[index] = RegistrationStatus::PendingDelete; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | void AppletResource::FreeAppletResourceId(u64 aruid) { | ||
| 130 | u64 index = GetIndexFromAruid(aruid); | ||
| 131 | if (index >= AruidIndexMax) { | ||
| 132 | return; | ||
| 133 | } | ||
| 134 | |||
| 135 | auto& aruid_data = data[index]; | ||
| 136 | if (aruid_data.flag.is_assigned) { | ||
| 137 | aruid_data.shared_memory_format = nullptr; | ||
| 138 | aruid_data.flag.is_assigned.Assign(false); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | u64 AppletResource::GetActiveAruid() { | ||
| 143 | return active_aruid; | ||
| 144 | } | ||
| 145 | |||
| 146 | Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) { | ||
| 147 | u64 index = GetIndexFromAruid(aruid); | ||
| 148 | if (index >= AruidIndexMax) { | ||
| 149 | return ResultAruidNotRegistered; | ||
| 150 | } | ||
| 151 | |||
| 152 | *out_handle = shared_memory_holder[index].GetHandle(); | ||
| 153 | return ResultSuccess; | ||
| 154 | } | ||
| 155 | |||
| 156 | Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, | ||
| 157 | u64 aruid) { | ||
| 158 | u64 index = GetIndexFromAruid(aruid); | ||
| 159 | if (index >= AruidIndexMax) { | ||
| 160 | return ResultAruidNotRegistered; | ||
| 161 | } | ||
| 162 | |||
| 163 | *out_shared_memory_format = data[index].shared_memory_format; | ||
| 164 | return ResultSuccess; | ||
| 165 | } | ||
| 166 | |||
| 167 | AruidData* AppletResource::GetAruidData(u64 aruid) { | ||
| 168 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 169 | if (aruid_index == AruidIndexMax) { | ||
| 170 | return nullptr; | ||
| 171 | } | ||
| 172 | return &data[aruid_index]; | ||
| 173 | } | ||
| 174 | |||
| 175 | AruidData* AppletResource::GetAruidDataByIndex(std::size_t aruid_index) { | ||
| 176 | return &data[aruid_index]; | ||
| 177 | } | ||
| 178 | |||
| 179 | bool AppletResource::IsVibrationAruidActive(u64 aruid) const { | ||
| 180 | return aruid == 0 || aruid == active_vibration_aruid; | ||
| 181 | } | ||
| 182 | |||
| 183 | u64 AppletResource::GetIndexFromAruid(u64 aruid) { | ||
| 184 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 185 | if (registration_list.flag[i] == RegistrationStatus::Initialized && | ||
| 186 | registration_list.aruid[i] == aruid) { | ||
| 187 | return i; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | return AruidIndexMax; | ||
| 191 | } | ||
| 192 | |||
| 193 | Result AppletResource::DestroySevenSixAxisTransferMemory() { | ||
| 194 | // TODO | ||
| 195 | return ResultSuccess; | ||
| 196 | } | ||
| 197 | |||
| 198 | void AppletResource::EnableInput(u64 aruid, bool is_enabled) { | ||
| 199 | const u64 index = GetIndexFromAruid(aruid); | ||
| 200 | if (index >= AruidIndexMax) { | ||
| 201 | return; | ||
| 202 | } | ||
| 203 | |||
| 204 | data[index].flag.enable_pad_input.Assign(is_enabled); | ||
| 205 | data[index].flag.enable_touchscreen.Assign(is_enabled); | ||
| 206 | } | ||
| 207 | |||
| 208 | void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { | ||
| 209 | const u64 index = GetIndexFromAruid(aruid); | ||
| 210 | if (index >= AruidIndexMax) { | ||
| 211 | return; | ||
| 212 | } | ||
| 213 | |||
| 214 | data[index].flag.enable_six_axis_sensor.Assign(is_enabled); | ||
| 215 | } | ||
| 216 | |||
| 217 | void AppletResource::EnablePadInput(u64 aruid, bool is_enabled) { | ||
| 218 | const u64 index = GetIndexFromAruid(aruid); | ||
| 219 | if (index >= AruidIndexMax) { | ||
| 220 | return; | ||
| 221 | } | ||
| 222 | |||
| 223 | data[index].flag.enable_pad_input.Assign(is_enabled); | ||
| 224 | } | ||
| 225 | |||
| 226 | void AppletResource::EnableTouchScreen(u64 aruid, bool is_enabled) { | ||
| 227 | const u64 index = GetIndexFromAruid(aruid); | ||
| 228 | if (index >= AruidIndexMax) { | ||
| 229 | return; | ||
| 230 | } | ||
| 231 | |||
| 232 | data[index].flag.enable_touchscreen.Assign(is_enabled); | ||
| 233 | } | ||
| 234 | |||
| 235 | void AppletResource::SetIsPalmaConnectable(u64 aruid, bool is_connectable) { | ||
| 236 | const u64 index = GetIndexFromAruid(aruid); | ||
| 237 | if (index >= AruidIndexMax) { | ||
| 238 | return; | ||
| 239 | } | ||
| 240 | |||
| 241 | data[index].flag.is_palma_connectable.Assign(is_connectable); | ||
| 242 | } | ||
| 243 | |||
| 244 | void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) { | ||
| 245 | const u64 index = GetIndexFromAruid(aruid); | ||
| 246 | if (index >= AruidIndexMax) { | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | |||
| 250 | data[index].flag.enable_palma_boost_mode.Assign(is_enabled); | ||
| 251 | } | ||
| 252 | |||
| 253 | Result AppletResource::RegisterCoreAppletResource() { | ||
| 254 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 255 | return ResultAppletResourceOverflow; | ||
| 256 | } | ||
| 257 | if (ref_counter == 0) { | ||
| 258 | const u64 index = GetIndexFromAruid(0); | ||
| 259 | if (index < AruidIndexMax) { | ||
| 260 | return ResultAruidAlreadyRegistered; | ||
| 261 | } | ||
| 262 | |||
| 263 | std::size_t data_index = AruidIndexMax; | ||
| 264 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 265 | if (!data[i].flag.is_initialized) { | ||
| 266 | data_index = i; | ||
| 267 | break; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | if (data_index == AruidIndexMax) { | ||
| 272 | return ResultAruidNoAvailableEntries; | ||
| 273 | } | ||
| 274 | |||
| 275 | AruidData& aruid_data = data[data_index]; | ||
| 276 | |||
| 277 | aruid_data.aruid = 0; | ||
| 278 | aruid_data.flag.is_initialized.Assign(true); | ||
| 279 | aruid_data.flag.enable_pad_input.Assign(true); | ||
| 280 | aruid_data.flag.enable_six_axis_sensor.Assign(true); | ||
| 281 | aruid_data.flag.bit_18.Assign(true); | ||
| 282 | aruid_data.flag.enable_touchscreen.Assign(true); | ||
| 283 | |||
| 284 | data_index = AruidIndexMax; | ||
| 285 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 286 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 287 | if (registration_list.aruid[i] != 0) { | ||
| 288 | continue; | ||
| 289 | } | ||
| 290 | data_index = i; | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | if (registration_list.flag[i] == RegistrationStatus::None) { | ||
| 294 | data_index = i; | ||
| 295 | break; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | Result result = ResultSuccess; | ||
| 300 | |||
| 301 | if (data_index == AruidIndexMax) { | ||
| 302 | result = CreateAppletResource(0); | ||
| 303 | } else { | ||
| 304 | registration_list.flag[data_index] = RegistrationStatus::Initialized; | ||
| 305 | registration_list.aruid[data_index] = 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | if (result.IsError()) { | ||
| 309 | UnregisterAppletResourceUserId(0); | ||
| 310 | return result; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | ref_counter++; | ||
| 314 | return ResultSuccess; | ||
| 315 | } | ||
| 316 | |||
| 317 | Result AppletResource::UnregisterCoreAppletResource() { | ||
| 318 | if (ref_counter == 0) { | ||
| 319 | return ResultAppletResourceNotInitialized; | ||
| 320 | } | ||
| 321 | |||
| 322 | if (--ref_counter == 0) { | ||
| 323 | UnregisterAppletResourceUserId(0); | ||
| 324 | } | ||
| 325 | |||
| 326 | return ResultSuccess; | ||
| 327 | } | ||
| 328 | |||
| 329 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/applet_resource.h b/src/core/hle/service/hid/controllers/applet_resource.h deleted file mode 100644 index 0862fdc2f..000000000 --- a/src/core/hle/service/hid/controllers/applet_resource.h +++ /dev/null | |||
| @@ -1,123 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | #include "core/hle/service/hid/controllers/shared_memory_holder.h" | ||
| 13 | |||
| 14 | namespace Core { | ||
| 15 | class System; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Kernel { | ||
| 19 | class KSharedMemory; | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace Service::HID { | ||
| 23 | struct SharedMemoryFormat; | ||
| 24 | class AppletResource; | ||
| 25 | class NPadResource; | ||
| 26 | |||
| 27 | static constexpr std::size_t AruidIndexMax = 0x20; | ||
| 28 | static constexpr u64 SystemAruid = 0; | ||
| 29 | |||
| 30 | enum class RegistrationStatus : u32 { | ||
| 31 | None, | ||
| 32 | Initialized, | ||
| 33 | PendingDelete, | ||
| 34 | }; | ||
| 35 | |||
| 36 | struct DataStatusFlag { | ||
| 37 | union { | ||
| 38 | u32 raw{}; | ||
| 39 | |||
| 40 | BitField<0, 1, u32> is_initialized; | ||
| 41 | BitField<1, 1, u32> is_assigned; | ||
| 42 | BitField<16, 1, u32> enable_pad_input; | ||
| 43 | BitField<17, 1, u32> enable_six_axis_sensor; | ||
| 44 | BitField<18, 1, u32> bit_18; | ||
| 45 | BitField<19, 1, u32> is_palma_connectable; | ||
| 46 | BitField<20, 1, u32> enable_palma_boost_mode; | ||
| 47 | BitField<21, 1, u32> enable_touchscreen; | ||
| 48 | }; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct AruidRegisterList { | ||
| 52 | std::array<RegistrationStatus, AruidIndexMax> flag{}; | ||
| 53 | std::array<u64, AruidIndexMax> aruid{}; | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(AruidRegisterList) == 0x180, "AruidRegisterList is an invalid size"); | ||
| 56 | |||
| 57 | struct AruidData { | ||
| 58 | DataStatusFlag flag{}; | ||
| 59 | u64 aruid{}; | ||
| 60 | SharedMemoryFormat* shared_memory_format{nullptr}; | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct HandheldConfig { | ||
| 64 | bool is_handheld_hid_enabled; | ||
| 65 | bool is_force_handheld; | ||
| 66 | bool is_joycon_rail_enabled; | ||
| 67 | bool is_force_handheld_style_vibration; | ||
| 68 | }; | ||
| 69 | static_assert(sizeof(HandheldConfig) == 0x4, "HandheldConfig is an invalid size"); | ||
| 70 | |||
| 71 | struct AppletResourceHolder { | ||
| 72 | std::shared_ptr<AppletResource> applet_resource{nullptr}; | ||
| 73 | std::recursive_mutex* shared_mutex{nullptr}; | ||
| 74 | NPadResource* shared_npad_resource{nullptr}; | ||
| 75 | std::shared_ptr<HandheldConfig> handheld_config{nullptr}; | ||
| 76 | long* handle_1; | ||
| 77 | }; | ||
| 78 | |||
| 79 | class AppletResource { | ||
| 80 | public: | ||
| 81 | explicit AppletResource(Core::System& system_); | ||
| 82 | ~AppletResource(); | ||
| 83 | |||
| 84 | Result CreateAppletResource(u64 aruid); | ||
| 85 | |||
| 86 | Result RegisterAppletResourceUserId(u64 aruid, bool enable_input); | ||
| 87 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 88 | |||
| 89 | void FreeAppletResourceId(u64 aruid); | ||
| 90 | |||
| 91 | u64 GetActiveAruid(); | ||
| 92 | Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); | ||
| 93 | Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid); | ||
| 94 | AruidData* GetAruidData(u64 aruid); | ||
| 95 | AruidData* GetAruidDataByIndex(std::size_t aruid_index); | ||
| 96 | |||
| 97 | bool IsVibrationAruidActive(u64 aruid) const; | ||
| 98 | |||
| 99 | u64 GetIndexFromAruid(u64 aruid); | ||
| 100 | |||
| 101 | Result DestroySevenSixAxisTransferMemory(); | ||
| 102 | |||
| 103 | void EnableInput(u64 aruid, bool is_enabled); | ||
| 104 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); | ||
| 105 | void EnablePadInput(u64 aruid, bool is_enabled); | ||
| 106 | void EnableTouchScreen(u64 aruid, bool is_enabled); | ||
| 107 | void SetIsPalmaConnectable(u64 aruid, bool is_connectable); | ||
| 108 | void EnablePalmaBoostMode(u64 aruid, bool is_enabled); | ||
| 109 | |||
| 110 | Result RegisterCoreAppletResource(); | ||
| 111 | Result UnregisterCoreAppletResource(); | ||
| 112 | |||
| 113 | private: | ||
| 114 | u64 active_aruid{}; | ||
| 115 | AruidRegisterList registration_list{}; | ||
| 116 | std::array<AruidData, AruidIndexMax> data{}; | ||
| 117 | std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{}; | ||
| 118 | s32 ref_counter{}; | ||
| 119 | u64 active_vibration_aruid; | ||
| 120 | |||
| 121 | Core::System& system; | ||
| 122 | }; | ||
| 123 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/capture_button.cpp b/src/core/hle/service/hid/controllers/capture_button.cpp deleted file mode 100644 index 7847c080e..000000000 --- a/src/core/hle/service/hid/controllers/capture_button.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/capture_button.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | CaptureButton::CaptureButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | CaptureButton::~CaptureButton() = default; | ||
| 14 | |||
| 15 | void CaptureButton::OnInit() {} | ||
| 16 | |||
| 17 | void CaptureButton::OnRelease() {} | ||
| 18 | |||
| 19 | void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->capture_button.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/capture_button.h b/src/core/hle/service/hid/controllers/capture_button.h deleted file mode 100644 index dcc4715c5..000000000 --- a/src/core/hle/service/hid/controllers/capture_button.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class CaptureButton final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit CaptureButton(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~CaptureButton() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.cpp b/src/core/hle/service/hid/controllers/console_six_axis.cpp deleted file mode 100644 index 4b574c2e5..000000000 --- a/src/core/hle/service/hid/controllers/console_six_axis.cpp +++ /dev/null | |||
| @@ -1,45 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hid/emulated_console.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hle/service/hid/controllers/console_six_axis.h" | ||
| 8 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 13 | console = hid_core.GetEmulatedConsole(); | ||
| 14 | } | ||
| 15 | |||
| 16 | ConsoleSixAxis::~ConsoleSixAxis() = default; | ||
| 17 | |||
| 18 | void ConsoleSixAxis::OnInit() {} | ||
| 19 | |||
| 20 | void ConsoleSixAxis::OnRelease() {} | ||
| 21 | |||
| 22 | void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 23 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 24 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 25 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 26 | |||
| 27 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | ConsoleSixAxisSensorSharedMemoryFormat& shared_memory = data->shared_memory_format->console; | ||
| 32 | |||
| 33 | if (!IsControllerActivated()) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | |||
| 37 | const auto motion_status = console->GetMotion(); | ||
| 38 | |||
| 39 | shared_memory.sampling_number++; | ||
| 40 | shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; | ||
| 41 | shared_memory.verticalization_error = motion_status.verticalization_error; | ||
| 42 | shared_memory.gyro_bias = motion_status.gyro_bias; | ||
| 43 | } | ||
| 44 | |||
| 45 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.h b/src/core/hle/service/hid/controllers/console_six_axis.h deleted file mode 100644 index e3351f83c..000000000 --- a/src/core/hle/service/hid/controllers/console_six_axis.h +++ /dev/null | |||
| @@ -1,30 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Core::HID { | ||
| 9 | class EmulatedConsole; | ||
| 10 | } // namespace Core::HID | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | class ConsoleSixAxis final : public ControllerBase { | ||
| 14 | public: | ||
| 15 | explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_); | ||
| 16 | ~ConsoleSixAxis() override; | ||
| 17 | |||
| 18 | // Called when the controller is initialized | ||
| 19 | void OnInit() override; | ||
| 20 | |||
| 21 | // When the controller is released | ||
| 22 | void OnRelease() override; | ||
| 23 | |||
| 24 | // When the controller is requesting an update for the shared memory | ||
| 25 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 26 | |||
| 27 | private: | ||
| 28 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 29 | }; | ||
| 30 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp deleted file mode 100644 index afca7154c..000000000 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | |||
| 8 | ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} | ||
| 9 | ControllerBase::~ControllerBase() = default; | ||
| 10 | |||
| 11 | Result ControllerBase::Activate() { | ||
| 12 | if (is_activated) { | ||
| 13 | return ResultSuccess; | ||
| 14 | } | ||
| 15 | is_activated = true; | ||
| 16 | OnInit(); | ||
| 17 | return ResultSuccess; | ||
| 18 | } | ||
| 19 | |||
| 20 | Result ControllerBase::Activate(u64 aruid) { | ||
| 21 | return Activate(); | ||
| 22 | } | ||
| 23 | |||
| 24 | void ControllerBase::DeactivateController() { | ||
| 25 | if (is_activated) { | ||
| 26 | OnRelease(); | ||
| 27 | } | ||
| 28 | is_activated = false; | ||
| 29 | } | ||
| 30 | |||
| 31 | bool ControllerBase::IsControllerActivated() const { | ||
| 32 | return is_activated; | ||
| 33 | } | ||
| 34 | |||
| 35 | void ControllerBase::SetAppletResource(std::shared_ptr<AppletResource> resource, | ||
| 36 | std::recursive_mutex* resource_mutex) { | ||
| 37 | applet_resource = resource; | ||
| 38 | shared_mutex = resource_mutex; | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h deleted file mode 100644 index b34b85ece..000000000 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ /dev/null | |||
| @@ -1,55 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 11 | |||
| 12 | namespace Core::Timing { | ||
| 13 | class CoreTiming; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Core::HID { | ||
| 17 | class HIDCore; | ||
| 18 | } // namespace Core::HID | ||
| 19 | |||
| 20 | namespace Service::HID { | ||
| 21 | class ControllerBase { | ||
| 22 | public: | ||
| 23 | explicit ControllerBase(Core::HID::HIDCore& hid_core_); | ||
| 24 | virtual ~ControllerBase(); | ||
| 25 | |||
| 26 | // Called when the controller is initialized | ||
| 27 | virtual void OnInit() = 0; | ||
| 28 | |||
| 29 | // When the controller is released | ||
| 30 | virtual void OnRelease() = 0; | ||
| 31 | |||
| 32 | // When the controller is requesting an update for the shared memory | ||
| 33 | virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing) = 0; | ||
| 34 | |||
| 35 | // When the controller is requesting a motion update for the shared memory | ||
| 36 | virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {} | ||
| 37 | |||
| 38 | Result Activate(); | ||
| 39 | Result Activate(u64 aruid); | ||
| 40 | |||
| 41 | void DeactivateController(); | ||
| 42 | |||
| 43 | bool IsControllerActivated() const; | ||
| 44 | |||
| 45 | void SetAppletResource(std::shared_ptr<AppletResource> resource, | ||
| 46 | std::recursive_mutex* resource_mutex); | ||
| 47 | |||
| 48 | protected: | ||
| 49 | bool is_activated{false}; | ||
| 50 | std::shared_ptr<AppletResource> applet_resource{nullptr}; | ||
| 51 | std::recursive_mutex* shared_mutex{nullptr}; | ||
| 52 | |||
| 53 | Core::HID::HIDCore& hid_core; | ||
| 54 | }; | ||
| 55 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_mouse.cpp b/src/core/hle/service/hid/controllers/debug_mouse.cpp deleted file mode 100644 index ceeb78d36..000000000 --- a/src/core/hle/service/hid/controllers/debug_mouse.cpp +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/frontend/emu_window.h" | ||
| 6 | #include "core/hid/emulated_devices.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 9 | #include "core/hle/service/hid/controllers/debug_mouse.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | DebugMouse::DebugMouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 15 | emulated_devices = hid_core.GetEmulatedDevices(); | ||
| 16 | } | ||
| 17 | |||
| 18 | DebugMouse::~DebugMouse() = default; | ||
| 19 | |||
| 20 | void DebugMouse::OnInit() {} | ||
| 21 | void DebugMouse::OnRelease() {} | ||
| 22 | |||
| 23 | void DebugMouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | MouseSharedMemoryFormat& shared_memory = data->shared_memory_format->debug_mouse; | ||
| 33 | |||
| 34 | if (!IsControllerActivated()) { | ||
| 35 | shared_memory.mouse_lifo.buffer_count = 0; | ||
| 36 | shared_memory.mouse_lifo.buffer_tail = 0; | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | |||
| 40 | next_state = {}; | ||
| 41 | |||
| 42 | const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state; | ||
| 43 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 44 | |||
| 45 | if (Settings::values.mouse_enabled) { | ||
| 46 | const auto& mouse_button_state = emulated_devices->GetMouseButtons(); | ||
| 47 | const auto& mouse_position_state = emulated_devices->GetMousePosition(); | ||
| 48 | const auto& mouse_wheel_state = emulated_devices->GetMouseWheel(); | ||
| 49 | next_state.attribute.is_connected.Assign(1); | ||
| 50 | next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width); | ||
| 51 | next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height); | ||
| 52 | next_state.delta_x = next_state.x - last_entry.x; | ||
| 53 | next_state.delta_y = next_state.y - last_entry.y; | ||
| 54 | next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x; | ||
| 55 | next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y; | ||
| 56 | |||
| 57 | last_mouse_wheel_state = mouse_wheel_state; | ||
| 58 | next_state.button = mouse_button_state; | ||
| 59 | } | ||
| 60 | |||
| 61 | shared_memory.mouse_lifo.WriteNextEntry(next_state); | ||
| 62 | } | ||
| 63 | |||
| 64 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_mouse.h b/src/core/hle/service/hid/controllers/debug_mouse.h deleted file mode 100644 index ec939fa9f..000000000 --- a/src/core/hle/service/hid/controllers/debug_mouse.h +++ /dev/null | |||
| @@ -1,34 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Core::HID { | ||
| 9 | class EmulatedDevices; | ||
| 10 | struct MouseState; | ||
| 11 | struct AnalogStickState; | ||
| 12 | } // namespace Core::HID | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | class DebugMouse final : public ControllerBase { | ||
| 16 | public: | ||
| 17 | explicit DebugMouse(Core::HID::HIDCore& hid_core_); | ||
| 18 | ~DebugMouse() override; | ||
| 19 | |||
| 20 | // Called when the controller is initialized | ||
| 21 | void OnInit() override; | ||
| 22 | |||
| 23 | // When the controller is released | ||
| 24 | void OnRelease() override; | ||
| 25 | |||
| 26 | // When the controller is requesting an update for the shared memory | ||
| 27 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 28 | |||
| 29 | private: | ||
| 30 | Core::HID::MouseState next_state{}; | ||
| 31 | Core::HID::AnalogStickState last_mouse_wheel_state{}; | ||
| 32 | Core::HID::EmulatedDevices* emulated_devices = nullptr; | ||
| 33 | }; | ||
| 34 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp deleted file mode 100644 index dc83f90f3..000000000 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 10 | #include "core/hle/service/hid/controllers/debug_pad.h" | ||
| 11 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | DebugPad::DebugPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 16 | controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); | ||
| 17 | } | ||
| 18 | |||
| 19 | DebugPad::~DebugPad() = default; | ||
| 20 | |||
| 21 | void DebugPad::OnInit() {} | ||
| 22 | |||
| 23 | void DebugPad::OnRelease() {} | ||
| 24 | |||
| 25 | void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 26 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 27 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 28 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 29 | |||
| 30 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | |||
| 34 | DebugPadSharedMemoryFormat& shared_memory = data->shared_memory_format->debug_pad; | ||
| 35 | |||
| 36 | if (!IsControllerActivated()) { | ||
| 37 | shared_memory.debug_pad_lifo.buffer_count = 0; | ||
| 38 | shared_memory.debug_pad_lifo.buffer_tail = 0; | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | |||
| 42 | const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state; | ||
| 43 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 44 | |||
| 45 | if (Settings::values.debug_pad_enabled) { | ||
| 46 | next_state.attribute.connected.Assign(1); | ||
| 47 | |||
| 48 | const auto& button_state = controller->GetDebugPadButtons(); | ||
| 49 | const auto& stick_state = controller->GetSticks(); | ||
| 50 | |||
| 51 | next_state.pad_state = button_state; | ||
| 52 | next_state.l_stick = stick_state.left; | ||
| 53 | next_state.r_stick = stick_state.right; | ||
| 54 | } | ||
| 55 | |||
| 56 | shared_memory.debug_pad_lifo.WriteNextEntry(next_state); | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h deleted file mode 100644 index dd00b2402..000000000 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ /dev/null | |||
| @@ -1,36 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/debug_pad_types.h" | ||
| 8 | |||
| 9 | namespace Core::HID { | ||
| 10 | class HIDCore; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Core::Timing { | ||
| 14 | class CoreTiming; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Service::HID { | ||
| 18 | class DebugPad final : public ControllerBase { | ||
| 19 | public: | ||
| 20 | explicit DebugPad(Core::HID::HIDCore& hid_core_); | ||
| 21 | ~DebugPad() override; | ||
| 22 | |||
| 23 | // Called when the controller is initialized | ||
| 24 | void OnInit() override; | ||
| 25 | |||
| 26 | // When the controller is released | ||
| 27 | void OnRelease() override; | ||
| 28 | |||
| 29 | // When the controller is requesting an update for the shared memory | ||
| 30 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 31 | |||
| 32 | private: | ||
| 33 | DebugPadState next_state{}; | ||
| 34 | Core::HID::EmulatedController* controller = nullptr; | ||
| 35 | }; | ||
| 36 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/digitizer.cpp b/src/core/hle/service/hid/controllers/digitizer.cpp deleted file mode 100644 index d5514c965..000000000 --- a/src/core/hle/service/hid/controllers/digitizer.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/digitizer.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | Digitizer::Digitizer(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | Digitizer::~Digitizer() = default; | ||
| 14 | |||
| 15 | void Digitizer::OnInit() {} | ||
| 16 | |||
| 17 | void Digitizer::OnRelease() {} | ||
| 18 | |||
| 19 | void Digitizer::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->digitizer.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/digitizer.h b/src/core/hle/service/hid/controllers/digitizer.h deleted file mode 100644 index d81f814c3..000000000 --- a/src/core/hle/service/hid/controllers/digitizer.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class Digitizer final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit Digitizer(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~Digitizer() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp deleted file mode 100644 index c73da13ee..000000000 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ /dev/null | |||
| @@ -1,366 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/math_util.h" | ||
| 5 | #include "common/settings.h" | ||
| 6 | #include "core/frontend/emu_window.h" | ||
| 7 | #include "core/hid/emulated_console.h" | ||
| 8 | #include "core/hid/hid_core.h" | ||
| 9 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 10 | #include "core/hle/service/hid/controllers/gesture.h" | ||
| 11 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | // HW is around 700, value is set to 400 to make it easier to trigger with mouse | ||
| 15 | constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s | ||
| 16 | constexpr f32 angle_threshold = 0.015f; // Threshold in radians | ||
| 17 | constexpr f32 pinch_threshold = 0.5f; // Threshold in pixels | ||
| 18 | constexpr f32 press_delay = 0.5f; // Time in seconds | ||
| 19 | constexpr f32 double_tap_delay = 0.35f; // Time in seconds | ||
| 20 | |||
| 21 | constexpr f32 Square(s32 num) { | ||
| 22 | return static_cast<f32>(num * num); | ||
| 23 | } | ||
| 24 | |||
| 25 | Gesture::Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) { | ||
| 26 | console = hid_core.GetEmulatedConsole(); | ||
| 27 | } | ||
| 28 | Gesture::~Gesture() = default; | ||
| 29 | |||
| 30 | void Gesture::OnInit() { | ||
| 31 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 32 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 33 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 34 | |||
| 35 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 36 | return; | ||
| 37 | } | ||
| 38 | |||
| 39 | shared_memory = &data->shared_memory_format->gesture; | ||
| 40 | shared_memory->gesture_lifo.buffer_count = 0; | ||
| 41 | shared_memory->gesture_lifo.buffer_tail = 0; | ||
| 42 | force_update = true; | ||
| 43 | } | ||
| 44 | |||
| 45 | void Gesture::OnRelease() {} | ||
| 46 | |||
| 47 | void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 48 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 49 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 50 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 51 | |||
| 52 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | shared_memory = &data->shared_memory_format->gesture; | ||
| 57 | |||
| 58 | if (!IsControllerActivated()) { | ||
| 59 | shared_memory->gesture_lifo.buffer_count = 0; | ||
| 60 | shared_memory->gesture_lifo.buffer_tail = 0; | ||
| 61 | return; | ||
| 62 | } | ||
| 63 | |||
| 64 | ReadTouchInput(); | ||
| 65 | |||
| 66 | GestureProperties gesture = GetGestureProperties(); | ||
| 67 | f32 time_difference = | ||
| 68 | static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) / | ||
| 69 | (1000 * 1000 * 1000); | ||
| 70 | |||
| 71 | // Only update if necessary | ||
| 72 | if (!ShouldUpdateGesture(gesture, time_difference)) { | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | |||
| 76 | last_update_timestamp = shared_memory->gesture_lifo.timestamp; | ||
| 77 | UpdateGestureSharedMemory(gesture, time_difference); | ||
| 78 | } | ||
| 79 | |||
| 80 | void Gesture::ReadTouchInput() { | ||
| 81 | if (!Settings::values.touchscreen.enabled) { | ||
| 82 | fingers = {}; | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | const auto touch_status = console->GetTouch(); | ||
| 87 | for (std::size_t id = 0; id < fingers.size(); ++id) { | ||
| 88 | fingers[id] = touch_status[id]; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | bool Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) { | ||
| 93 | const auto& last_entry = GetLastGestureEntry(); | ||
| 94 | if (force_update) { | ||
| 95 | force_update = false; | ||
| 96 | return true; | ||
| 97 | } | ||
| 98 | |||
| 99 | // Update if coordinates change | ||
| 100 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 101 | if (gesture.points[id] != last_gesture.points[id]) { | ||
| 102 | return true; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | // Update on press and hold event after 0.5 seconds | ||
| 107 | if (last_entry.type == GestureType::Touch && last_entry.point_count == 1 && | ||
| 108 | time_difference > press_delay) { | ||
| 109 | return enable_press_and_tap; | ||
| 110 | } | ||
| 111 | |||
| 112 | return false; | ||
| 113 | } | ||
| 114 | |||
| 115 | void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference) { | ||
| 116 | GestureType type = GestureType::Idle; | ||
| 117 | GestureAttribute attributes{}; | ||
| 118 | |||
| 119 | const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state; | ||
| 120 | |||
| 121 | // Reset next state to default | ||
| 122 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 123 | next_state.delta = {}; | ||
| 124 | next_state.vel_x = 0; | ||
| 125 | next_state.vel_y = 0; | ||
| 126 | next_state.direction = GestureDirection::None; | ||
| 127 | next_state.rotation_angle = 0; | ||
| 128 | next_state.scale = 0; | ||
| 129 | |||
| 130 | if (gesture.active_points > 0) { | ||
| 131 | if (last_gesture.active_points == 0) { | ||
| 132 | NewGesture(gesture, type, attributes); | ||
| 133 | } else { | ||
| 134 | UpdateExistingGesture(gesture, type, time_difference); | ||
| 135 | } | ||
| 136 | } else { | ||
| 137 | EndGesture(gesture, last_gesture, type, attributes, time_difference); | ||
| 138 | } | ||
| 139 | |||
| 140 | // Apply attributes | ||
| 141 | next_state.detection_count = gesture.detection_count; | ||
| 142 | next_state.type = type; | ||
| 143 | next_state.attributes = attributes; | ||
| 144 | next_state.pos = gesture.mid_point; | ||
| 145 | next_state.point_count = static_cast<s32>(gesture.active_points); | ||
| 146 | next_state.points = gesture.points; | ||
| 147 | last_gesture = gesture; | ||
| 148 | |||
| 149 | shared_memory->gesture_lifo.WriteNextEntry(next_state); | ||
| 150 | } | ||
| 151 | |||
| 152 | void Gesture::NewGesture(GestureProperties& gesture, GestureType& type, | ||
| 153 | GestureAttribute& attributes) { | ||
| 154 | const auto& last_entry = GetLastGestureEntry(); | ||
| 155 | |||
| 156 | gesture.detection_count++; | ||
| 157 | type = GestureType::Touch; | ||
| 158 | |||
| 159 | // New touch after cancel is not considered new | ||
| 160 | if (last_entry.type != GestureType::Cancel) { | ||
| 161 | attributes.is_new_touch.Assign(1); | ||
| 162 | enable_press_and_tap = true; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | void Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type, | ||
| 167 | f32 time_difference) { | ||
| 168 | const auto& last_entry = GetLastGestureEntry(); | ||
| 169 | |||
| 170 | // Promote to pan type if touch moved | ||
| 171 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 172 | if (gesture.points[id] != last_gesture.points[id]) { | ||
| 173 | type = GestureType::Pan; | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | // Number of fingers changed cancel the last event and clear data | ||
| 179 | if (gesture.active_points != last_gesture.active_points) { | ||
| 180 | type = GestureType::Cancel; | ||
| 181 | enable_press_and_tap = false; | ||
| 182 | gesture.active_points = 0; | ||
| 183 | gesture.mid_point = {}; | ||
| 184 | gesture.points.fill({}); | ||
| 185 | return; | ||
| 186 | } | ||
| 187 | |||
| 188 | // Calculate extra parameters of panning | ||
| 189 | if (type == GestureType::Pan) { | ||
| 190 | UpdatePanEvent(gesture, last_gesture, type, time_difference); | ||
| 191 | return; | ||
| 192 | } | ||
| 193 | |||
| 194 | // Promote to press type | ||
| 195 | if (last_entry.type == GestureType::Touch) { | ||
| 196 | type = GestureType::Press; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | void Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 201 | GestureType& type, GestureAttribute& attributes, f32 time_difference) { | ||
| 202 | const auto& last_entry = GetLastGestureEntry(); | ||
| 203 | |||
| 204 | if (last_gesture_props.active_points != 0) { | ||
| 205 | switch (last_entry.type) { | ||
| 206 | case GestureType::Touch: | ||
| 207 | if (enable_press_and_tap) { | ||
| 208 | SetTapEvent(gesture, last_gesture_props, type, attributes); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | type = GestureType::Cancel; | ||
| 212 | force_update = true; | ||
| 213 | break; | ||
| 214 | case GestureType::Press: | ||
| 215 | case GestureType::Tap: | ||
| 216 | case GestureType::Swipe: | ||
| 217 | case GestureType::Pinch: | ||
| 218 | case GestureType::Rotate: | ||
| 219 | type = GestureType::Complete; | ||
| 220 | force_update = true; | ||
| 221 | break; | ||
| 222 | case GestureType::Pan: | ||
| 223 | EndPanEvent(gesture, last_gesture_props, type, time_difference); | ||
| 224 | break; | ||
| 225 | default: | ||
| 226 | break; | ||
| 227 | } | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | if (last_entry.type == GestureType::Complete || last_entry.type == GestureType::Cancel) { | ||
| 231 | gesture.detection_count++; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 236 | GestureType& type, GestureAttribute& attributes) { | ||
| 237 | type = GestureType::Tap; | ||
| 238 | gesture = last_gesture_props; | ||
| 239 | force_update = true; | ||
| 240 | f32 tap_time_difference = | ||
| 241 | static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); | ||
| 242 | last_tap_timestamp = last_update_timestamp; | ||
| 243 | if (tap_time_difference < double_tap_delay) { | ||
| 244 | attributes.is_double_tap.Assign(1); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 249 | GestureType& type, f32 time_difference) { | ||
| 250 | const auto& last_entry = GetLastGestureEntry(); | ||
| 251 | |||
| 252 | next_state.delta = gesture.mid_point - last_entry.pos; | ||
| 253 | next_state.vel_x = static_cast<f32>(next_state.delta.x) / time_difference; | ||
| 254 | next_state.vel_y = static_cast<f32>(next_state.delta.y) / time_difference; | ||
| 255 | last_pan_time_difference = time_difference; | ||
| 256 | |||
| 257 | // Promote to pinch type | ||
| 258 | if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > | ||
| 259 | pinch_threshold) { | ||
| 260 | type = GestureType::Pinch; | ||
| 261 | next_state.scale = gesture.average_distance / last_gesture_props.average_distance; | ||
| 262 | } | ||
| 263 | |||
| 264 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / | ||
| 265 | (1 + (gesture.angle * last_gesture_props.angle))); | ||
| 266 | // Promote to rotate type | ||
| 267 | if (std::abs(angle_between_two_lines) > angle_threshold) { | ||
| 268 | type = GestureType::Rotate; | ||
| 269 | next_state.scale = 0; | ||
| 270 | next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 275 | GestureType& type, f32 time_difference) { | ||
| 276 | const auto& last_entry = GetLastGestureEntry(); | ||
| 277 | next_state.vel_x = | ||
| 278 | static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference); | ||
| 279 | next_state.vel_y = | ||
| 280 | static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference); | ||
| 281 | const f32 curr_vel = | ||
| 282 | std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y)); | ||
| 283 | |||
| 284 | // Set swipe event with parameters | ||
| 285 | if (curr_vel > swipe_threshold) { | ||
| 286 | SetSwipeEvent(gesture, last_gesture_props, type); | ||
| 287 | return; | ||
| 288 | } | ||
| 289 | |||
| 290 | // End panning without swipe | ||
| 291 | type = GestureType::Complete; | ||
| 292 | next_state.vel_x = 0; | ||
| 293 | next_state.vel_y = 0; | ||
| 294 | force_update = true; | ||
| 295 | } | ||
| 296 | |||
| 297 | void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 298 | GestureType& type) { | ||
| 299 | const auto& last_entry = GetLastGestureEntry(); | ||
| 300 | |||
| 301 | type = GestureType::Swipe; | ||
| 302 | gesture = last_gesture_props; | ||
| 303 | force_update = true; | ||
| 304 | next_state.delta = last_entry.delta; | ||
| 305 | |||
| 306 | if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) { | ||
| 307 | if (next_state.delta.x > 0) { | ||
| 308 | next_state.direction = GestureDirection::Right; | ||
| 309 | return; | ||
| 310 | } | ||
| 311 | next_state.direction = GestureDirection::Left; | ||
| 312 | return; | ||
| 313 | } | ||
| 314 | if (next_state.delta.y > 0) { | ||
| 315 | next_state.direction = GestureDirection::Down; | ||
| 316 | return; | ||
| 317 | } | ||
| 318 | next_state.direction = GestureDirection::Up; | ||
| 319 | } | ||
| 320 | |||
| 321 | const GestureState& Gesture::GetLastGestureEntry() const { | ||
| 322 | return shared_memory->gesture_lifo.ReadCurrentEntry().state; | ||
| 323 | } | ||
| 324 | |||
| 325 | GestureProperties Gesture::GetGestureProperties() { | ||
| 326 | GestureProperties gesture; | ||
| 327 | std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers; | ||
| 328 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | ||
| 329 | [](const auto& finger) { return finger.pressed; }); | ||
| 330 | gesture.active_points = | ||
| 331 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); | ||
| 332 | |||
| 333 | for (size_t id = 0; id < gesture.active_points; ++id) { | ||
| 334 | const auto& [active_x, active_y] = active_fingers[id].position; | ||
| 335 | gesture.points[id] = { | ||
| 336 | .x = static_cast<s32>(active_x * Layout::ScreenUndocked::Width), | ||
| 337 | .y = static_cast<s32>(active_y * Layout::ScreenUndocked::Height), | ||
| 338 | }; | ||
| 339 | |||
| 340 | // Hack: There is no touch in docked but games still allow it | ||
| 341 | if (Settings::IsDockedMode()) { | ||
| 342 | gesture.points[id] = { | ||
| 343 | .x = static_cast<s32>(active_x * Layout::ScreenDocked::Width), | ||
| 344 | .y = static_cast<s32>(active_y * Layout::ScreenDocked::Height), | ||
| 345 | }; | ||
| 346 | } | ||
| 347 | |||
| 348 | gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); | ||
| 349 | gesture.mid_point.y += static_cast<s32>(gesture.points[id].y / gesture.active_points); | ||
| 350 | } | ||
| 351 | |||
| 352 | for (size_t id = 0; id < gesture.active_points; ++id) { | ||
| 353 | const f32 distance = std::sqrt(Square(gesture.mid_point.x - gesture.points[id].x) + | ||
| 354 | Square(gesture.mid_point.y - gesture.points[id].y)); | ||
| 355 | gesture.average_distance += distance / static_cast<f32>(gesture.active_points); | ||
| 356 | } | ||
| 357 | |||
| 358 | gesture.angle = std::atan2(static_cast<f32>(gesture.mid_point.y - gesture.points[0].y), | ||
| 359 | static_cast<f32>(gesture.mid_point.x - gesture.points[0].x)); | ||
| 360 | |||
| 361 | gesture.detection_count = last_gesture.detection_count; | ||
| 362 | |||
| 363 | return gesture; | ||
| 364 | } | ||
| 365 | |||
| 366 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h deleted file mode 100644 index 78da1552a..000000000 --- a/src/core/hle/service/hid/controllers/gesture.h +++ /dev/null | |||
| @@ -1,87 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/touch_types.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class EmulatedConsole; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | struct GestureSharedMemoryFormat; | ||
| 18 | |||
| 19 | class Gesture final : public ControllerBase { | ||
| 20 | public: | ||
| 21 | explicit Gesture(Core::HID::HIDCore& hid_core_); | ||
| 22 | ~Gesture() override; | ||
| 23 | |||
| 24 | // Called when the controller is initialized | ||
| 25 | void OnInit() override; | ||
| 26 | |||
| 27 | // When the controller is released | ||
| 28 | void OnRelease() override; | ||
| 29 | |||
| 30 | // When the controller is requesting an update for the shared memory | ||
| 31 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 32 | |||
| 33 | private: | ||
| 34 | // Reads input from all available input engines | ||
| 35 | void ReadTouchInput(); | ||
| 36 | |||
| 37 | // Returns true if gesture state needs to be updated | ||
| 38 | bool ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference); | ||
| 39 | |||
| 40 | // Updates the shared memory to the next state | ||
| 41 | void UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference); | ||
| 42 | |||
| 43 | // Initializes new gesture | ||
| 44 | void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes); | ||
| 45 | |||
| 46 | // Updates existing gesture state | ||
| 47 | void UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference); | ||
| 48 | |||
| 49 | // Terminates exiting gesture | ||
| 50 | void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 51 | GestureType& type, GestureAttribute& attributes, f32 time_difference); | ||
| 52 | |||
| 53 | // Set current event to a tap event | ||
| 54 | void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 55 | GestureType& type, GestureAttribute& attributes); | ||
| 56 | |||
| 57 | // Calculates and set the extra parameters related to a pan event | ||
| 58 | void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 59 | GestureType& type, f32 time_difference); | ||
| 60 | |||
| 61 | // Terminates the pan event | ||
| 62 | void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 63 | GestureType& type, f32 time_difference); | ||
| 64 | |||
| 65 | // Set current event to a swipe event | ||
| 66 | void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, | ||
| 67 | GestureType& type); | ||
| 68 | |||
| 69 | // Retrieves the last gesture entry, as indicated by shared memory indices. | ||
| 70 | [[nodiscard]] const GestureState& GetLastGestureEntry() const; | ||
| 71 | |||
| 72 | // Returns the average distance, angle and middle point of the active fingers | ||
| 73 | GestureProperties GetGestureProperties(); | ||
| 74 | |||
| 75 | GestureState next_state{}; | ||
| 76 | GestureSharedMemoryFormat* shared_memory; | ||
| 77 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 78 | |||
| 79 | std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{}; | ||
| 80 | GestureProperties last_gesture{}; | ||
| 81 | s64 last_update_timestamp{}; | ||
| 82 | s64 last_tap_timestamp{}; | ||
| 83 | f32 last_pan_time_difference{}; | ||
| 84 | bool force_update{false}; | ||
| 85 | bool enable_press_and_tap{false}; | ||
| 86 | }; | ||
| 87 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/home_button.cpp b/src/core/hle/service/hid/controllers/home_button.cpp deleted file mode 100644 index 1397379f3..000000000 --- a/src/core/hle/service/hid/controllers/home_button.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/home_button.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | HomeButton::HomeButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | HomeButton::~HomeButton() = default; | ||
| 14 | |||
| 15 | void HomeButton::OnInit() {} | ||
| 16 | |||
| 17 | void HomeButton::OnRelease() {} | ||
| 18 | |||
| 19 | void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->home_button.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/home_button.h b/src/core/hle/service/hid/controllers/home_button.h deleted file mode 100644 index e91c2aa5d..000000000 --- a/src/core/hle/service/hid/controllers/home_button.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class HomeButton final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit HomeButton(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~HomeButton() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp deleted file mode 100644 index c069bcbb2..000000000 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ /dev/null | |||
| @@ -1,56 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_devices.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 9 | #include "core/hle/service/hid/controllers/keyboard.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | Keyboard::Keyboard(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 15 | emulated_devices = hid_core.GetEmulatedDevices(); | ||
| 16 | } | ||
| 17 | |||
| 18 | Keyboard::~Keyboard() = default; | ||
| 19 | |||
| 20 | void Keyboard::OnInit() {} | ||
| 21 | |||
| 22 | void Keyboard::OnRelease() {} | ||
| 23 | |||
| 24 | void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 25 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 26 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 27 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 28 | |||
| 29 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | |||
| 33 | KeyboardSharedMemoryFormat& shared_memory = data->shared_memory_format->keyboard; | ||
| 34 | |||
| 35 | if (!IsControllerActivated()) { | ||
| 36 | shared_memory.keyboard_lifo.buffer_count = 0; | ||
| 37 | shared_memory.keyboard_lifo.buffer_tail = 0; | ||
| 38 | return; | ||
| 39 | } | ||
| 40 | |||
| 41 | const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state; | ||
| 42 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 43 | |||
| 44 | if (Settings::values.keyboard_enabled) { | ||
| 45 | const auto& keyboard_state = emulated_devices->GetKeyboard(); | ||
| 46 | const auto& keyboard_modifier_state = emulated_devices->GetKeyboardModifier(); | ||
| 47 | |||
| 48 | next_state.key = keyboard_state; | ||
| 49 | next_state.modifier = keyboard_modifier_state; | ||
| 50 | next_state.attribute.is_connected.Assign(1); | ||
| 51 | } | ||
| 52 | |||
| 53 | shared_memory.keyboard_lifo.WriteNextEntry(next_state); | ||
| 54 | } | ||
| 55 | |||
| 56 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h deleted file mode 100644 index e8ca326c6..000000000 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ /dev/null | |||
| @@ -1,28 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/keyboard_types.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | class Keyboard final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit Keyboard(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~Keyboard() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | KeyboardState next_state{}; | ||
| 26 | Core::HID::EmulatedDevices* emulated_devices = nullptr; | ||
| 27 | }; | ||
| 28 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp deleted file mode 100644 index 3a8d1751b..000000000 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ /dev/null | |||
| @@ -1,64 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/frontend/emu_window.h" | ||
| 6 | #include "core/hid/emulated_devices.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 9 | #include "core/hle/service/hid/controllers/mouse.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | Mouse::Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { | ||
| 15 | emulated_devices = hid_core.GetEmulatedDevices(); | ||
| 16 | } | ||
| 17 | |||
| 18 | Mouse::~Mouse() = default; | ||
| 19 | |||
| 20 | void Mouse::OnInit() {} | ||
| 21 | void Mouse::OnRelease() {} | ||
| 22 | |||
| 23 | void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | MouseSharedMemoryFormat& shared_memory = data->shared_memory_format->mouse; | ||
| 33 | |||
| 34 | if (!IsControllerActivated()) { | ||
| 35 | shared_memory.mouse_lifo.buffer_count = 0; | ||
| 36 | shared_memory.mouse_lifo.buffer_tail = 0; | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | |||
| 40 | next_state = {}; | ||
| 41 | |||
| 42 | const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state; | ||
| 43 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 44 | |||
| 45 | if (Settings::values.mouse_enabled) { | ||
| 46 | const auto& mouse_button_state = emulated_devices->GetMouseButtons(); | ||
| 47 | const auto& mouse_position_state = emulated_devices->GetMousePosition(); | ||
| 48 | const auto& mouse_wheel_state = emulated_devices->GetMouseWheel(); | ||
| 49 | next_state.attribute.is_connected.Assign(1); | ||
| 50 | next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width); | ||
| 51 | next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height); | ||
| 52 | next_state.delta_x = next_state.x - last_entry.x; | ||
| 53 | next_state.delta_y = next_state.y - last_entry.y; | ||
| 54 | next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x; | ||
| 55 | next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y; | ||
| 56 | |||
| 57 | last_mouse_wheel_state = mouse_wheel_state; | ||
| 58 | next_state.button = mouse_button_state; | ||
| 59 | } | ||
| 60 | |||
| 61 | shared_memory.mouse_lifo.WriteNextEntry(next_state); | ||
| 62 | } | ||
| 63 | |||
| 64 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h deleted file mode 100644 index cefad956c..000000000 --- a/src/core/hle/service/hid/controllers/mouse.h +++ /dev/null | |||
| @@ -1,34 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Core::HID { | ||
| 9 | class EmulatedDevices; | ||
| 10 | struct MouseState; | ||
| 11 | struct AnalogStickState; | ||
| 12 | } // namespace Core::HID | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | class Mouse final : public ControllerBase { | ||
| 16 | public: | ||
| 17 | explicit Mouse(Core::HID::HIDCore& hid_core_); | ||
| 18 | ~Mouse() override; | ||
| 19 | |||
| 20 | // Called when the controller is initialized | ||
| 21 | void OnInit() override; | ||
| 22 | |||
| 23 | // When the controller is released | ||
| 24 | void OnRelease() override; | ||
| 25 | |||
| 26 | // When the controller is requesting an update for the shared memory | ||
| 27 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 28 | |||
| 29 | private: | ||
| 30 | Core::HID::MouseState next_state{}; | ||
| 31 | Core::HID::AnalogStickState last_mouse_wheel_state{}; | ||
| 32 | Core::HID::EmulatedDevices* emulated_devices = nullptr; | ||
| 33 | }; | ||
| 34 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp deleted file mode 100644 index 17cd0d7a0..000000000 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ /dev/null | |||
| @@ -1,1342 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <array> | ||
| 6 | #include <chrono> | ||
| 7 | #include <cstring> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/logging/log.h" | ||
| 13 | #include "common/settings.h" | ||
| 14 | #include "core/core_timing.h" | ||
| 15 | #include "core/hid/emulated_controller.h" | ||
| 16 | #include "core/hid/hid_core.h" | ||
| 17 | #include "core/hle/kernel/k_event.h" | ||
| 18 | #include "core/hle/kernel/k_readable_event.h" | ||
| 19 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 20 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 21 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 22 | #include "core/hle/service/hid/errors.h" | ||
| 23 | #include "core/hle/service/hid/hid_util.h" | ||
| 24 | #include "core/hle/service/kernel_helpers.h" | ||
| 25 | |||
| 26 | namespace Service::HID { | ||
| 27 | |||
| 28 | NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) | ||
| 29 | : hid_core{hid_core_}, service_context{service_context_}, npad_resource{service_context} { | ||
| 30 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { | ||
| 31 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 32 | auto& controller = controller_data[aruid_index][i]; | ||
| 33 | controller.device = hid_core.GetEmulatedControllerByIndex(i); | ||
| 34 | controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = | ||
| 35 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 36 | controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex] | ||
| 37 | .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 38 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 39 | .on_change = | ||
| 40 | [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, | ||
| 41 | .is_npad_service = true, | ||
| 42 | }; | ||
| 43 | controller.callback_key = controller.device->SetCallback(engine_callback); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | NPad::~NPad() { | ||
| 49 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { | ||
| 50 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 51 | auto& controller = controller_data[aruid_index][i]; | ||
| 52 | controller.device->DeleteCallback(controller.callback_key); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | Result NPad::Activate() { | ||
| 58 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 59 | return ResultNpadResourceOverflow; | ||
| 60 | } | ||
| 61 | |||
| 62 | if (ref_counter == 0) { | ||
| 63 | std::scoped_lock lock{mutex}; | ||
| 64 | |||
| 65 | // TODO: Activate handlers and AbstractedPad | ||
| 66 | } | ||
| 67 | |||
| 68 | ref_counter++; | ||
| 69 | return ResultSuccess; | ||
| 70 | } | ||
| 71 | |||
| 72 | Result NPad::Activate(u64 aruid) { | ||
| 73 | std::scoped_lock lock{mutex}; | ||
| 74 | std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex}; | ||
| 75 | |||
| 76 | auto* data = applet_resource_holder.applet_resource->GetAruidData(aruid); | ||
| 77 | const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); | ||
| 78 | |||
| 79 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 80 | return ResultSuccess; | ||
| 81 | } | ||
| 82 | |||
| 83 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 84 | auto& controller = controller_data[aruid_index][i]; | ||
| 85 | controller.shared_memory = &data->shared_memory_format->npad.npad_entry[i].internal_state; | ||
| 86 | } | ||
| 87 | |||
| 88 | // Prefill controller buffers | ||
| 89 | for (auto& controller : controller_data[aruid_index]) { | ||
| 90 | auto* npad = controller.shared_memory; | ||
| 91 | npad->fullkey_color = { | ||
| 92 | .attribute = ColorAttribute::NoController, | ||
| 93 | .fullkey = {}, | ||
| 94 | }; | ||
| 95 | npad->joycon_color = { | ||
| 96 | .attribute = ColorAttribute::NoController, | ||
| 97 | .left = {}, | ||
| 98 | .right = {}, | ||
| 99 | }; | ||
| 100 | // HW seems to initialize the first 19 entries | ||
| 101 | for (std::size_t i = 0; i < 19; ++i) { | ||
| 102 | WriteEmptyEntry(npad); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | return ResultSuccess; | ||
| 107 | } | ||
| 108 | |||
| 109 | Result NPad::ActivateNpadResource() { | ||
| 110 | return npad_resource.Activate(); | ||
| 111 | } | ||
| 112 | |||
| 113 | Result NPad::ActivateNpadResource(u64 aruid) { | ||
| 114 | return npad_resource.Activate(aruid); | ||
| 115 | } | ||
| 116 | |||
| 117 | void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) { | ||
| 118 | if (type == Core::HID::ControllerTriggerType::All) { | ||
| 119 | ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); | ||
| 120 | ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); | ||
| 121 | return; | ||
| 122 | } | ||
| 123 | |||
| 124 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 125 | if (controller_idx >= controller_data[aruid_index].size()) { | ||
| 126 | return; | ||
| 127 | } | ||
| 128 | |||
| 129 | auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 130 | |||
| 131 | if (!data->flag.is_assigned) { | ||
| 132 | continue; | ||
| 133 | } | ||
| 134 | |||
| 135 | auto& controller = controller_data[aruid_index][controller_idx]; | ||
| 136 | const auto is_connected = controller.device->IsConnected(); | ||
| 137 | const auto npad_type = controller.device->GetNpadStyleIndex(); | ||
| 138 | const auto npad_id = controller.device->GetNpadIdType(); | ||
| 139 | switch (type) { | ||
| 140 | case Core::HID::ControllerTriggerType::Connected: | ||
| 141 | case Core::HID::ControllerTriggerType::Disconnected: | ||
| 142 | if (is_connected == controller.is_connected) { | ||
| 143 | return; | ||
| 144 | } | ||
| 145 | UpdateControllerAt(data->aruid, npad_type, npad_id, is_connected); | ||
| 146 | break; | ||
| 147 | case Core::HID::ControllerTriggerType::Battery: { | ||
| 148 | if (!controller.device->IsConnected()) { | ||
| 149 | return; | ||
| 150 | } | ||
| 151 | auto* shared_memory = controller.shared_memory; | ||
| 152 | const auto& battery_level = controller.device->GetBattery(); | ||
| 153 | shared_memory->battery_level_dual = battery_level.dual.battery_level; | ||
| 154 | shared_memory->battery_level_left = battery_level.left.battery_level; | ||
| 155 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | default: | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 165 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 166 | if (!npad_resource.IsControllerSupported(aruid, controller.device->GetNpadStyleIndex())) { | ||
| 167 | return; | ||
| 168 | } | ||
| 169 | LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); | ||
| 170 | const auto controller_type = controller.device->GetNpadStyleIndex(); | ||
| 171 | const auto& body_colors = controller.device->GetColors(); | ||
| 172 | const auto& battery_level = controller.device->GetBattery(); | ||
| 173 | auto* shared_memory = controller.shared_memory; | ||
| 174 | if (controller_type == Core::HID::NpadStyleIndex::None) { | ||
| 175 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | ||
| 176 | return; | ||
| 177 | } | ||
| 178 | |||
| 179 | // Reset memory values | ||
| 180 | shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; | ||
| 181 | shared_memory->device_type.raw = 0; | ||
| 182 | shared_memory->system_properties.raw = 0; | ||
| 183 | shared_memory->joycon_color.attribute = ColorAttribute::NoController; | ||
| 184 | shared_memory->joycon_color.attribute = ColorAttribute::NoController; | ||
| 185 | shared_memory->fullkey_color = {}; | ||
| 186 | shared_memory->joycon_color.left = {}; | ||
| 187 | shared_memory->joycon_color.right = {}; | ||
| 188 | shared_memory->battery_level_dual = {}; | ||
| 189 | shared_memory->battery_level_left = {}; | ||
| 190 | shared_memory->battery_level_right = {}; | ||
| 191 | |||
| 192 | switch (controller_type) { | ||
| 193 | case Core::HID::NpadStyleIndex::None: | ||
| 194 | ASSERT(false); | ||
| 195 | break; | ||
| 196 | case Core::HID::NpadStyleIndex::ProController: | ||
| 197 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 198 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | ||
| 199 | shared_memory->battery_level_dual = battery_level.dual.battery_level; | ||
| 200 | shared_memory->style_tag.fullkey.Assign(1); | ||
| 201 | shared_memory->device_type.fullkey.Assign(1); | ||
| 202 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 203 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 204 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 205 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 206 | battery_level.dual.is_charging); | ||
| 207 | shared_memory->applet_footer_type = AppletFooterUiType::SwitchProController; | ||
| 208 | shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); | ||
| 209 | break; | ||
| 210 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 211 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 212 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 213 | shared_memory->fullkey_color.fullkey = body_colors.fullkey; | ||
| 214 | shared_memory->joycon_color.left = body_colors.left; | ||
| 215 | shared_memory->joycon_color.right = body_colors.right; | ||
| 216 | shared_memory->style_tag.handheld.Assign(1); | ||
| 217 | shared_memory->device_type.handheld_left.Assign(1); | ||
| 218 | shared_memory->device_type.handheld_right.Assign(1); | ||
| 219 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 220 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 221 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 222 | shared_memory->system_properties.use_directional_buttons.Assign(1); | ||
| 223 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 224 | battery_level.left.is_charging); | ||
| 225 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 226 | battery_level.left.is_charging); | ||
| 227 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 228 | battery_level.right.is_charging); | ||
| 229 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; | ||
| 230 | shared_memory->applet_footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; | ||
| 231 | shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); | ||
| 232 | break; | ||
| 233 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 234 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 235 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 236 | shared_memory->style_tag.joycon_dual.Assign(1); | ||
| 237 | if (controller.is_dual_left_connected) { | ||
| 238 | shared_memory->joycon_color.left = body_colors.left; | ||
| 239 | shared_memory->battery_level_left = battery_level.left.battery_level; | ||
| 240 | shared_memory->device_type.joycon_left.Assign(1); | ||
| 241 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 242 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 243 | battery_level.left.is_charging); | ||
| 244 | shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1); | ||
| 245 | } | ||
| 246 | if (controller.is_dual_right_connected) { | ||
| 247 | shared_memory->joycon_color.right = body_colors.right; | ||
| 248 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 249 | shared_memory->device_type.joycon_right.Assign(1); | ||
| 250 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 251 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 252 | battery_level.right.is_charging); | ||
| 253 | shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1); | ||
| 254 | } | ||
| 255 | shared_memory->system_properties.use_directional_buttons.Assign(1); | ||
| 256 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 257 | shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; | ||
| 258 | |||
| 259 | if (controller.is_dual_left_connected && controller.is_dual_right_connected) { | ||
| 260 | shared_memory->applet_footer_type = AppletFooterUiType::JoyDual; | ||
| 261 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 262 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 263 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 264 | battery_level.left.is_charging); | ||
| 265 | } else if (controller.is_dual_left_connected) { | ||
| 266 | shared_memory->applet_footer_type = AppletFooterUiType::JoyDualLeftOnly; | ||
| 267 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 268 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 269 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 270 | battery_level.left.is_charging); | ||
| 271 | } else { | ||
| 272 | shared_memory->applet_footer_type = AppletFooterUiType::JoyDualRightOnly; | ||
| 273 | shared_memory->fullkey_color.fullkey = body_colors.right; | ||
| 274 | shared_memory->battery_level_dual = battery_level.right.battery_level; | ||
| 275 | shared_memory->system_properties.is_charging_joy_dual.Assign( | ||
| 276 | battery_level.right.is_charging); | ||
| 277 | } | ||
| 278 | break; | ||
| 279 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 280 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 281 | shared_memory->fullkey_color.fullkey = body_colors.left; | ||
| 282 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 283 | shared_memory->joycon_color.left = body_colors.left; | ||
| 284 | shared_memory->battery_level_dual = battery_level.left.battery_level; | ||
| 285 | shared_memory->style_tag.joycon_left.Assign(1); | ||
| 286 | shared_memory->device_type.joycon_left.Assign(1); | ||
| 287 | shared_memory->system_properties.is_horizontal.Assign(1); | ||
| 288 | shared_memory->system_properties.use_minus.Assign(1); | ||
| 289 | shared_memory->system_properties.is_charging_joy_left.Assign( | ||
| 290 | battery_level.left.is_charging); | ||
| 291 | shared_memory->applet_footer_type = AppletFooterUiType::JoyLeftHorizontal; | ||
| 292 | shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); | ||
| 293 | break; | ||
| 294 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 295 | shared_memory->fullkey_color.attribute = ColorAttribute::Ok; | ||
| 296 | shared_memory->fullkey_color.fullkey = body_colors.right; | ||
| 297 | shared_memory->joycon_color.attribute = ColorAttribute::Ok; | ||
| 298 | shared_memory->joycon_color.right = body_colors.right; | ||
| 299 | shared_memory->battery_level_right = battery_level.right.battery_level; | ||
| 300 | shared_memory->style_tag.joycon_right.Assign(1); | ||
| 301 | shared_memory->device_type.joycon_right.Assign(1); | ||
| 302 | shared_memory->system_properties.is_horizontal.Assign(1); | ||
| 303 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 304 | shared_memory->system_properties.is_charging_joy_right.Assign( | ||
| 305 | battery_level.right.is_charging); | ||
| 306 | shared_memory->applet_footer_type = AppletFooterUiType::JoyRightHorizontal; | ||
| 307 | shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); | ||
| 308 | break; | ||
| 309 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 310 | shared_memory->style_tag.gamecube.Assign(1); | ||
| 311 | shared_memory->device_type.fullkey.Assign(1); | ||
| 312 | shared_memory->system_properties.is_vertical.Assign(1); | ||
| 313 | shared_memory->system_properties.use_plus.Assign(1); | ||
| 314 | break; | ||
| 315 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 316 | shared_memory->style_tag.palma.Assign(1); | ||
| 317 | shared_memory->device_type.palma.Assign(1); | ||
| 318 | shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); | ||
| 319 | break; | ||
| 320 | case Core::HID::NpadStyleIndex::NES: | ||
| 321 | shared_memory->style_tag.lark.Assign(1); | ||
| 322 | shared_memory->device_type.fullkey.Assign(1); | ||
| 323 | break; | ||
| 324 | case Core::HID::NpadStyleIndex::SNES: | ||
| 325 | shared_memory->style_tag.lucia.Assign(1); | ||
| 326 | shared_memory->device_type.fullkey.Assign(1); | ||
| 327 | shared_memory->applet_footer_type = AppletFooterUiType::Lucia; | ||
| 328 | break; | ||
| 329 | case Core::HID::NpadStyleIndex::N64: | ||
| 330 | shared_memory->style_tag.lagoon.Assign(1); | ||
| 331 | shared_memory->device_type.fullkey.Assign(1); | ||
| 332 | shared_memory->applet_footer_type = AppletFooterUiType::Lagon; | ||
| 333 | break; | ||
| 334 | case Core::HID::NpadStyleIndex::SegaGenesis: | ||
| 335 | shared_memory->style_tag.lager.Assign(1); | ||
| 336 | shared_memory->device_type.fullkey.Assign(1); | ||
| 337 | break; | ||
| 338 | default: | ||
| 339 | break; | ||
| 340 | } | ||
| 341 | |||
| 342 | controller.is_connected = true; | ||
| 343 | controller.device->Connect(); | ||
| 344 | controller.device->SetLedPattern(); | ||
| 345 | if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 346 | if (controller.is_dual_left_connected) { | ||
| 347 | controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex, | ||
| 348 | Common::Input::PollingMode::Active); | ||
| 349 | } | ||
| 350 | if (controller.is_dual_right_connected) { | ||
| 351 | controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, | ||
| 352 | Common::Input::PollingMode::Active); | ||
| 353 | } | ||
| 354 | } else { | ||
| 355 | controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, | ||
| 356 | Common::Input::PollingMode::Active); | ||
| 357 | } | ||
| 358 | |||
| 359 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | ||
| 360 | WriteEmptyEntry(controller.shared_memory); | ||
| 361 | hid_core.SetLastActiveController(npad_id); | ||
| 362 | } | ||
| 363 | |||
| 364 | void NPad::WriteEmptyEntry(NpadInternalState* npad) { | ||
| 365 | NPadGenericState dummy_pad_state{}; | ||
| 366 | NpadGcTriggerState dummy_gc_state{}; | ||
| 367 | dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 368 | npad->fullkey_lifo.WriteNextEntry(dummy_pad_state); | ||
| 369 | dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 370 | npad->handheld_lifo.WriteNextEntry(dummy_pad_state); | ||
| 371 | dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 372 | npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state); | ||
| 373 | dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 374 | npad->joy_left_lifo.WriteNextEntry(dummy_pad_state); | ||
| 375 | dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 376 | npad->joy_right_lifo.WriteNextEntry(dummy_pad_state); | ||
| 377 | dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 378 | npad->palma_lifo.WriteNextEntry(dummy_pad_state); | ||
| 379 | dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 380 | npad->system_ext_lifo.WriteNextEntry(dummy_pad_state); | ||
| 381 | dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; | ||
| 382 | npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); | ||
| 383 | } | ||
| 384 | |||
| 385 | void NPad::RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 386 | std::scoped_lock lock{*applet_resource_holder.shared_mutex}; | ||
| 387 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 388 | const auto controller_type = controller.device->GetNpadStyleIndex(); | ||
| 389 | |||
| 390 | if (!controller.device->IsConnected() && controller.is_connected) { | ||
| 391 | DisconnectNpad(aruid, npad_id); | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | if (!controller.device->IsConnected()) { | ||
| 395 | return; | ||
| 396 | } | ||
| 397 | if (controller.device->IsConnected() && !controller.is_connected) { | ||
| 398 | InitNewlyAddedController(aruid, npad_id); | ||
| 399 | } | ||
| 400 | |||
| 401 | // This function is unique to yuzu for the turbo buttons and motion to work properly | ||
| 402 | controller.device->StatusUpdate(); | ||
| 403 | |||
| 404 | auto& pad_entry = controller.npad_pad_state; | ||
| 405 | auto& trigger_entry = controller.npad_trigger_state; | ||
| 406 | const auto button_state = controller.device->GetNpadButtons(); | ||
| 407 | const auto stick_state = controller.device->GetSticks(); | ||
| 408 | |||
| 409 | using btn = Core::HID::NpadButton; | ||
| 410 | pad_entry.npad_buttons.raw = btn::None; | ||
| 411 | if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) { | ||
| 412 | constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | | ||
| 413 | btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | | ||
| 414 | btn::StickRRight | btn::StickRDown; | ||
| 415 | pad_entry.npad_buttons.raw = button_state.raw & right_button_mask; | ||
| 416 | pad_entry.r_stick = stick_state.right; | ||
| 417 | } | ||
| 418 | |||
| 419 | if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 420 | constexpr btn left_button_mask = | ||
| 421 | btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL | | ||
| 422 | btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown; | ||
| 423 | pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask; | ||
| 424 | pad_entry.l_stick = stick_state.left; | ||
| 425 | } | ||
| 426 | |||
| 427 | if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft || | ||
| 428 | controller_type == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 429 | pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); | ||
| 430 | pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); | ||
| 431 | } | ||
| 432 | |||
| 433 | if (controller_type == Core::HID::NpadStyleIndex::JoyconRight || | ||
| 434 | controller_type == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 435 | pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); | ||
| 436 | pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); | ||
| 437 | } | ||
| 438 | |||
| 439 | if (controller_type == Core::HID::NpadStyleIndex::GameCube) { | ||
| 440 | const auto& trigger_state = controller.device->GetTriggers(); | ||
| 441 | trigger_entry.l_analog = trigger_state.left; | ||
| 442 | trigger_entry.r_analog = trigger_state.right; | ||
| 443 | pad_entry.npad_buttons.zl.Assign(false); | ||
| 444 | pad_entry.npad_buttons.zr.Assign(button_state.r); | ||
| 445 | pad_entry.npad_buttons.l.Assign(button_state.zl); | ||
| 446 | pad_entry.npad_buttons.r.Assign(button_state.zr); | ||
| 447 | } | ||
| 448 | |||
| 449 | if (pad_entry.npad_buttons.raw != Core::HID::NpadButton::None) { | ||
| 450 | hid_core.SetLastActiveController(npad_id); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 455 | if (ref_counter == 0) { | ||
| 456 | return; | ||
| 457 | } | ||
| 458 | |||
| 459 | std::scoped_lock lock{*applet_resource_holder.shared_mutex}; | ||
| 460 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { | ||
| 461 | const auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); | ||
| 462 | const auto aruid = data->aruid; | ||
| 463 | |||
| 464 | if (!data->flag.is_assigned) { | ||
| 465 | continue; | ||
| 466 | } | ||
| 467 | |||
| 468 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | ||
| 469 | auto& controller = controller_data[aruid_index][i]; | ||
| 470 | controller.shared_memory = | ||
| 471 | &data->shared_memory_format->npad.npad_entry[i].internal_state; | ||
| 472 | auto* npad = controller.shared_memory; | ||
| 473 | |||
| 474 | const auto& controller_type = controller.device->GetNpadStyleIndex(); | ||
| 475 | |||
| 476 | if (controller_type == Core::HID::NpadStyleIndex::None || | ||
| 477 | !controller.device->IsConnected()) { | ||
| 478 | continue; | ||
| 479 | } | ||
| 480 | |||
| 481 | RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); | ||
| 482 | auto& pad_state = controller.npad_pad_state; | ||
| 483 | auto& libnx_state = controller.npad_libnx_state; | ||
| 484 | auto& trigger_state = controller.npad_trigger_state; | ||
| 485 | |||
| 486 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't | ||
| 487 | // activate any controllers. | ||
| 488 | libnx_state.connection_status.raw = 0; | ||
| 489 | libnx_state.connection_status.is_connected.Assign(1); | ||
| 490 | switch (controller_type) { | ||
| 491 | case Core::HID::NpadStyleIndex::None: | ||
| 492 | ASSERT(false); | ||
| 493 | break; | ||
| 494 | case Core::HID::NpadStyleIndex::ProController: | ||
| 495 | case Core::HID::NpadStyleIndex::NES: | ||
| 496 | case Core::HID::NpadStyleIndex::SNES: | ||
| 497 | case Core::HID::NpadStyleIndex::N64: | ||
| 498 | case Core::HID::NpadStyleIndex::SegaGenesis: | ||
| 499 | pad_state.connection_status.raw = 0; | ||
| 500 | pad_state.connection_status.is_connected.Assign(1); | ||
| 501 | pad_state.connection_status.is_wired.Assign(1); | ||
| 502 | |||
| 503 | libnx_state.connection_status.is_wired.Assign(1); | ||
| 504 | pad_state.sampling_number = | ||
| 505 | npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 506 | npad->fullkey_lifo.WriteNextEntry(pad_state); | ||
| 507 | break; | ||
| 508 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 509 | pad_state.connection_status.raw = 0; | ||
| 510 | pad_state.connection_status.is_connected.Assign(1); | ||
| 511 | pad_state.connection_status.is_wired.Assign(1); | ||
| 512 | pad_state.connection_status.is_left_connected.Assign(1); | ||
| 513 | pad_state.connection_status.is_right_connected.Assign(1); | ||
| 514 | pad_state.connection_status.is_left_wired.Assign(1); | ||
| 515 | pad_state.connection_status.is_right_wired.Assign(1); | ||
| 516 | |||
| 517 | libnx_state.connection_status.is_wired.Assign(1); | ||
| 518 | libnx_state.connection_status.is_left_connected.Assign(1); | ||
| 519 | libnx_state.connection_status.is_right_connected.Assign(1); | ||
| 520 | libnx_state.connection_status.is_left_wired.Assign(1); | ||
| 521 | libnx_state.connection_status.is_right_wired.Assign(1); | ||
| 522 | pad_state.sampling_number = | ||
| 523 | npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 524 | npad->handheld_lifo.WriteNextEntry(pad_state); | ||
| 525 | break; | ||
| 526 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 527 | pad_state.connection_status.raw = 0; | ||
| 528 | pad_state.connection_status.is_connected.Assign(1); | ||
| 529 | if (controller.is_dual_left_connected) { | ||
| 530 | pad_state.connection_status.is_left_connected.Assign(1); | ||
| 531 | libnx_state.connection_status.is_left_connected.Assign(1); | ||
| 532 | } | ||
| 533 | if (controller.is_dual_right_connected) { | ||
| 534 | pad_state.connection_status.is_right_connected.Assign(1); | ||
| 535 | libnx_state.connection_status.is_right_connected.Assign(1); | ||
| 536 | } | ||
| 537 | |||
| 538 | pad_state.sampling_number = | ||
| 539 | npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 540 | npad->joy_dual_lifo.WriteNextEntry(pad_state); | ||
| 541 | break; | ||
| 542 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 543 | pad_state.connection_status.raw = 0; | ||
| 544 | pad_state.connection_status.is_connected.Assign(1); | ||
| 545 | pad_state.connection_status.is_left_connected.Assign(1); | ||
| 546 | |||
| 547 | libnx_state.connection_status.is_left_connected.Assign(1); | ||
| 548 | pad_state.sampling_number = | ||
| 549 | npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 550 | npad->joy_left_lifo.WriteNextEntry(pad_state); | ||
| 551 | break; | ||
| 552 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 553 | pad_state.connection_status.raw = 0; | ||
| 554 | pad_state.connection_status.is_connected.Assign(1); | ||
| 555 | pad_state.connection_status.is_right_connected.Assign(1); | ||
| 556 | |||
| 557 | libnx_state.connection_status.is_right_connected.Assign(1); | ||
| 558 | pad_state.sampling_number = | ||
| 559 | npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 560 | npad->joy_right_lifo.WriteNextEntry(pad_state); | ||
| 561 | break; | ||
| 562 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 563 | pad_state.connection_status.raw = 0; | ||
| 564 | pad_state.connection_status.is_connected.Assign(1); | ||
| 565 | pad_state.connection_status.is_wired.Assign(1); | ||
| 566 | |||
| 567 | libnx_state.connection_status.is_wired.Assign(1); | ||
| 568 | pad_state.sampling_number = | ||
| 569 | npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 570 | trigger_state.sampling_number = | ||
| 571 | npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 572 | npad->fullkey_lifo.WriteNextEntry(pad_state); | ||
| 573 | npad->gc_trigger_lifo.WriteNextEntry(trigger_state); | ||
| 574 | break; | ||
| 575 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 576 | pad_state.connection_status.raw = 0; | ||
| 577 | pad_state.connection_status.is_connected.Assign(1); | ||
| 578 | pad_state.sampling_number = | ||
| 579 | npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 580 | npad->palma_lifo.WriteNextEntry(pad_state); | ||
| 581 | break; | ||
| 582 | default: | ||
| 583 | break; | ||
| 584 | } | ||
| 585 | |||
| 586 | libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; | ||
| 587 | libnx_state.l_stick = pad_state.l_stick; | ||
| 588 | libnx_state.r_stick = pad_state.r_stick; | ||
| 589 | npad->system_ext_lifo.WriteNextEntry(pad_state); | ||
| 590 | |||
| 591 | press_state |= static_cast<u64>(pad_state.npad_buttons.raw); | ||
| 592 | } | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | Result NPad::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set) { | ||
| 597 | std::scoped_lock lock{mutex}; | ||
| 598 | hid_core.SetSupportedStyleTag({supported_style_set}); | ||
| 599 | const Result result = npad_resource.SetSupportedNpadStyleSet(aruid, supported_style_set); | ||
| 600 | if (result.IsSuccess()) { | ||
| 601 | OnUpdate({}); | ||
| 602 | } | ||
| 603 | return result; | ||
| 604 | } | ||
| 605 | |||
| 606 | Result NPad::GetSupportedNpadStyleSet(u64 aruid, | ||
| 607 | Core::HID::NpadStyleSet& out_supported_style_set) const { | ||
| 608 | std::scoped_lock lock{mutex}; | ||
| 609 | const Result result = npad_resource.GetSupportedNpadStyleSet(out_supported_style_set, aruid); | ||
| 610 | |||
| 611 | if (result == ResultUndefinedStyleset) { | ||
| 612 | out_supported_style_set = Core::HID::NpadStyleSet::None; | ||
| 613 | return ResultSuccess; | ||
| 614 | } | ||
| 615 | |||
| 616 | return result; | ||
| 617 | } | ||
| 618 | |||
| 619 | Result NPad::GetMaskedSupportedNpadStyleSet( | ||
| 620 | u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { | ||
| 621 | std::scoped_lock lock{mutex}; | ||
| 622 | const Result result = | ||
| 623 | npad_resource.GetMaskedSupportedNpadStyleSet(out_supported_style_set, aruid); | ||
| 624 | |||
| 625 | if (result == ResultUndefinedStyleset) { | ||
| 626 | out_supported_style_set = Core::HID::NpadStyleSet::None; | ||
| 627 | return ResultSuccess; | ||
| 628 | } | ||
| 629 | |||
| 630 | return result; | ||
| 631 | } | ||
| 632 | |||
| 633 | Result NPad::SetSupportedNpadIdType(u64 aruid, | ||
| 634 | std::span<const Core::HID::NpadIdType> supported_npad_list) { | ||
| 635 | std::scoped_lock lock{mutex}; | ||
| 636 | if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { | ||
| 637 | return ResultInvalidArraySize; | ||
| 638 | } | ||
| 639 | |||
| 640 | Result result = npad_resource.SetSupportedNpadIdType(aruid, supported_npad_list); | ||
| 641 | |||
| 642 | if (result.IsSuccess()) { | ||
| 643 | OnUpdate({}); | ||
| 644 | } | ||
| 645 | |||
| 646 | return result; | ||
| 647 | } | ||
| 648 | |||
| 649 | Result NPad::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { | ||
| 650 | std::scoped_lock lock{mutex}; | ||
| 651 | return npad_resource.SetNpadJoyHoldType(aruid, hold_type); | ||
| 652 | } | ||
| 653 | |||
| 654 | Result NPad::GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const { | ||
| 655 | std::scoped_lock lock{mutex}; | ||
| 656 | return npad_resource.GetNpadJoyHoldType(out_hold_type, aruid); | ||
| 657 | } | ||
| 658 | |||
| 659 | Result NPad::SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode) { | ||
| 660 | std::scoped_lock lock{mutex}; | ||
| 661 | Result result = npad_resource.SetNpadHandheldActivationMode(aruid, mode); | ||
| 662 | if (result.IsSuccess()) { | ||
| 663 | OnUpdate({}); | ||
| 664 | } | ||
| 665 | return result; | ||
| 666 | } | ||
| 667 | |||
| 668 | Result NPad::GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const { | ||
| 669 | std::scoped_lock lock{mutex}; | ||
| 670 | return npad_resource.GetNpadHandheldActivationMode(out_mode, aruid); | ||
| 671 | } | ||
| 672 | |||
| 673 | bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, | ||
| 674 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { | ||
| 675 | if (!IsNpadIdValid(npad_id)) { | ||
| 676 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 677 | return false; | ||
| 678 | } | ||
| 679 | |||
| 680 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 681 | if (controller.shared_memory->assignment_mode != assignment_mode) { | ||
| 682 | controller.shared_memory->assignment_mode = assignment_mode; | ||
| 683 | } | ||
| 684 | |||
| 685 | if (!controller.device->IsConnected()) { | ||
| 686 | return false; | ||
| 687 | } | ||
| 688 | |||
| 689 | if (assignment_mode == NpadJoyAssignmentMode::Dual) { | ||
| 690 | if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) { | ||
| 691 | DisconnectNpad(aruid, npad_id); | ||
| 692 | controller.is_dual_left_connected = true; | ||
| 693 | controller.is_dual_right_connected = false; | ||
| 694 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); | ||
| 695 | return false; | ||
| 696 | } | ||
| 697 | if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 698 | DisconnectNpad(aruid, npad_id); | ||
| 699 | controller.is_dual_left_connected = false; | ||
| 700 | controller.is_dual_right_connected = true; | ||
| 701 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); | ||
| 702 | return false; | ||
| 703 | } | ||
| 704 | return false; | ||
| 705 | } | ||
| 706 | |||
| 707 | // This is for NpadJoyAssignmentMode::Single | ||
| 708 | |||
| 709 | // Only JoyconDual get affected by this function | ||
| 710 | if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 711 | return false; | ||
| 712 | } | ||
| 713 | |||
| 714 | if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { | ||
| 715 | DisconnectNpad(aruid, npad_id); | ||
| 716 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); | ||
| 717 | return false; | ||
| 718 | } | ||
| 719 | if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { | ||
| 720 | DisconnectNpad(aruid, npad_id); | ||
| 721 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); | ||
| 722 | return false; | ||
| 723 | } | ||
| 724 | |||
| 725 | // We have two controllers connected to the same npad_id we need to split them | ||
| 726 | new_npad_id = hid_core.GetFirstDisconnectedNpadId(); | ||
| 727 | auto& controller_2 = GetControllerFromNpadIdType(aruid, new_npad_id); | ||
| 728 | DisconnectNpad(aruid, npad_id); | ||
| 729 | if (npad_device_type == NpadJoyDeviceType::Left) { | ||
| 730 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); | ||
| 731 | controller_2.is_dual_left_connected = false; | ||
| 732 | controller_2.is_dual_right_connected = true; | ||
| 733 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); | ||
| 734 | } else { | ||
| 735 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); | ||
| 736 | controller_2.is_dual_left_connected = true; | ||
| 737 | controller_2.is_dual_right_connected = false; | ||
| 738 | UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); | ||
| 739 | } | ||
| 740 | return true; | ||
| 741 | } | ||
| 742 | |||
| 743 | bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 744 | std::size_t device_index, | ||
| 745 | const Core::HID::VibrationValue& vibration_value) { | ||
| 746 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 747 | if (!controller.device->IsConnected()) { | ||
| 748 | return false; | ||
| 749 | } | ||
| 750 | |||
| 751 | if (!controller.device->IsVibrationEnabled(device_index)) { | ||
| 752 | if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || | ||
| 753 | controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { | ||
| 754 | // Send an empty vibration to stop any vibrations. | ||
| 755 | Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; | ||
| 756 | controller.device->SetVibration(device_index, vibration); | ||
| 757 | // Then reset the vibration value to its default value. | ||
| 758 | controller.vibration[device_index].latest_vibration_value = | ||
| 759 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 760 | } | ||
| 761 | |||
| 762 | return false; | ||
| 763 | } | ||
| 764 | |||
| 765 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { | ||
| 766 | using std::chrono::duration_cast; | ||
| 767 | using std::chrono::milliseconds; | ||
| 768 | using std::chrono::steady_clock; | ||
| 769 | |||
| 770 | const auto now = steady_clock::now(); | ||
| 771 | |||
| 772 | // Filter out non-zero vibrations that are within 15ms of each other. | ||
| 773 | if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && | ||
| 774 | duration_cast<milliseconds>( | ||
| 775 | now - controller.vibration[device_index].last_vibration_timepoint) < | ||
| 776 | milliseconds(15)) { | ||
| 777 | return false; | ||
| 778 | } | ||
| 779 | |||
| 780 | controller.vibration[device_index].last_vibration_timepoint = now; | ||
| 781 | } | ||
| 782 | |||
| 783 | Core::HID::VibrationValue vibration{ | ||
| 784 | vibration_value.low_amplitude, vibration_value.low_frequency, | ||
| 785 | vibration_value.high_amplitude, vibration_value.high_frequency}; | ||
| 786 | return controller.device->SetVibration(device_index, vibration); | ||
| 787 | } | ||
| 788 | |||
| 789 | void NPad::VibrateController(u64 aruid, | ||
| 790 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 791 | const Core::HID::VibrationValue& vibration_value) { | ||
| 792 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 793 | return; | ||
| 794 | } | ||
| 795 | |||
| 796 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 801 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 802 | |||
| 803 | if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { | ||
| 804 | return; | ||
| 805 | } | ||
| 806 | |||
| 807 | if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { | ||
| 808 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 809 | return; | ||
| 810 | } | ||
| 811 | |||
| 812 | // Some games try to send mismatched parameters in the device handle, block these. | ||
| 813 | if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 814 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || | ||
| 815 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || | ||
| 816 | (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && | ||
| 817 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || | ||
| 818 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { | ||
| 819 | return; | ||
| 820 | } | ||
| 821 | |||
| 822 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | ||
| 823 | if (vibration_value.low_amplitude == | ||
| 824 | controller.vibration[device_index].latest_vibration_value.low_amplitude && | ||
| 825 | vibration_value.high_amplitude == | ||
| 826 | controller.vibration[device_index].latest_vibration_value.high_amplitude) { | ||
| 827 | return; | ||
| 828 | } | ||
| 829 | |||
| 830 | if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index, | ||
| 831 | vibration_value)) { | ||
| 832 | controller.vibration[device_index].latest_vibration_value = vibration_value; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | void NPad::VibrateControllers( | ||
| 837 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 838 | std::span<const Core::HID::VibrationValue> vibration_values) { | ||
| 839 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 840 | return; | ||
| 841 | } | ||
| 842 | |||
| 843 | ASSERT_OR_EXECUTE_MSG( | ||
| 844 | vibration_device_handles.size() == vibration_values.size(), { return; }, | ||
| 845 | "The amount of device handles does not match with the amount of vibration values," | ||
| 846 | "this is undefined behavior!"); | ||
| 847 | |||
| 848 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 849 | VibrateController(aruid, vibration_device_handles[i], vibration_values[i]); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 853 | Core::HID::VibrationValue NPad::GetLastVibration( | ||
| 854 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 855 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 856 | return {}; | ||
| 857 | } | ||
| 858 | |||
| 859 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 860 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 861 | return controller.vibration[device_index].latest_vibration_value; | ||
| 862 | } | ||
| 863 | |||
| 864 | void NPad::InitializeVibrationDevice( | ||
| 865 | const Core::HID::VibrationDeviceHandle& vibration_device_handle) { | ||
| 866 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 867 | return; | ||
| 868 | } | ||
| 869 | |||
| 870 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 871 | const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id); | ||
| 872 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 873 | InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index); | ||
| 874 | } | ||
| 875 | |||
| 876 | void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 877 | std::size_t device_index) { | ||
| 878 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 879 | if (!Settings::values.vibration_enabled.GetValue()) { | ||
| 880 | controller.vibration[device_index].device_mounted = false; | ||
| 881 | return; | ||
| 882 | } | ||
| 883 | |||
| 884 | controller.vibration[device_index].device_mounted = | ||
| 885 | controller.device->IsVibrationEnabled(device_index); | ||
| 886 | } | ||
| 887 | |||
| 888 | void NPad::SetPermitVibrationSession(bool permit_vibration_session) { | ||
| 889 | permit_vibration_session_enabled = permit_vibration_session; | ||
| 890 | } | ||
| 891 | |||
| 892 | bool NPad::IsVibrationDeviceMounted( | ||
| 893 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 894 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 895 | return false; | ||
| 896 | } | ||
| 897 | |||
| 898 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 899 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 900 | return controller.vibration[device_index].device_mounted; | ||
| 901 | } | ||
| 902 | |||
| 903 | Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | ||
| 904 | Core::HID::NpadIdType npad_id) { | ||
| 905 | std::scoped_lock lock{mutex}; | ||
| 906 | return npad_resource.AcquireNpadStyleSetUpdateEventHandle(aruid, out_event, npad_id); | ||
| 907 | } | ||
| 908 | |||
| 909 | void NPad::AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, | ||
| 910 | Core::HID::NpadIdType npad_id) { | ||
| 911 | UpdateControllerAt(aruid, controller, npad_id, true); | ||
| 912 | } | ||
| 913 | |||
| 914 | void NPad::UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex type, | ||
| 915 | Core::HID::NpadIdType npad_id, bool connected) { | ||
| 916 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 917 | if (!connected) { | ||
| 918 | DisconnectNpad(aruid, npad_id); | ||
| 919 | return; | ||
| 920 | } | ||
| 921 | |||
| 922 | controller.device->SetNpadStyleIndex(type); | ||
| 923 | InitNewlyAddedController(aruid, npad_id); | ||
| 924 | } | ||
| 925 | |||
| 926 | Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 927 | if (!IsNpadIdValid(npad_id)) { | ||
| 928 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 929 | return ResultInvalidNpadId; | ||
| 930 | } | ||
| 931 | |||
| 932 | LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); | ||
| 933 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 934 | for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { | ||
| 935 | // Send an empty vibration to stop any vibrations. | ||
| 936 | VibrateControllerAtIndex(aruid, npad_id, device_idx, {}); | ||
| 937 | controller.vibration[device_idx].device_mounted = false; | ||
| 938 | } | ||
| 939 | |||
| 940 | auto* shared_memory = controller.shared_memory; | ||
| 941 | // Don't reset shared_memory->assignment_mode this value is persistent | ||
| 942 | shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out | ||
| 943 | shared_memory->device_type.raw = 0; | ||
| 944 | shared_memory->system_properties.raw = 0; | ||
| 945 | shared_memory->button_properties.raw = 0; | ||
| 946 | shared_memory->sixaxis_fullkey_properties.raw = 0; | ||
| 947 | shared_memory->sixaxis_handheld_properties.raw = 0; | ||
| 948 | shared_memory->sixaxis_dual_left_properties.raw = 0; | ||
| 949 | shared_memory->sixaxis_dual_right_properties.raw = 0; | ||
| 950 | shared_memory->sixaxis_left_properties.raw = 0; | ||
| 951 | shared_memory->sixaxis_right_properties.raw = 0; | ||
| 952 | shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty; | ||
| 953 | shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty; | ||
| 954 | shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty; | ||
| 955 | shared_memory->fullkey_color = { | ||
| 956 | .attribute = ColorAttribute::NoController, | ||
| 957 | .fullkey = {}, | ||
| 958 | }; | ||
| 959 | shared_memory->joycon_color = { | ||
| 960 | .attribute = ColorAttribute::NoController, | ||
| 961 | .left = {}, | ||
| 962 | .right = {}, | ||
| 963 | }; | ||
| 964 | shared_memory->applet_footer_type = AppletFooterUiType::None; | ||
| 965 | |||
| 966 | controller.is_dual_left_connected = true; | ||
| 967 | controller.is_dual_right_connected = true; | ||
| 968 | controller.is_connected = false; | ||
| 969 | controller.device->Disconnect(); | ||
| 970 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | ||
| 971 | WriteEmptyEntry(shared_memory); | ||
| 972 | return ResultSuccess; | ||
| 973 | } | ||
| 974 | |||
| 975 | Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor( | ||
| 976 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 977 | bool& is_firmware_available) const { | ||
| 978 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 979 | if (is_valid.IsError()) { | ||
| 980 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 981 | return is_valid; | ||
| 982 | } | ||
| 983 | |||
| 984 | const auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle); | ||
| 985 | is_firmware_available = sixaxis_properties.is_firmware_update_available != 0; | ||
| 986 | return ResultSuccess; | ||
| 987 | } | ||
| 988 | |||
| 989 | Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( | ||
| 990 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||
| 991 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 992 | if (is_valid.IsError()) { | ||
| 993 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 994 | return is_valid; | ||
| 995 | } | ||
| 996 | |||
| 997 | auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle); | ||
| 998 | sixaxis_properties.is_newly_assigned.Assign(0); | ||
| 999 | |||
| 1000 | return ResultSuccess; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 1004 | Core::HID::NpadIdType npad_id_2) { | ||
| 1005 | if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { | ||
| 1006 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, | ||
| 1007 | npad_id_2); | ||
| 1008 | return ResultInvalidNpadId; | ||
| 1009 | } | ||
| 1010 | auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1); | ||
| 1011 | auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2); | ||
| 1012 | auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); | ||
| 1013 | auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); | ||
| 1014 | |||
| 1015 | // Simplify this code by converting dualjoycon with only a side connected to single joycons | ||
| 1016 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 1017 | if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { | ||
| 1018 | controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft; | ||
| 1019 | } | ||
| 1020 | if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { | ||
| 1021 | controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight; | ||
| 1022 | } | ||
| 1023 | } | ||
| 1024 | if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 1025 | if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { | ||
| 1026 | controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft; | ||
| 1027 | } | ||
| 1028 | if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { | ||
| 1029 | controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight; | ||
| 1030 | } | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | // Invalid merge errors | ||
| 1034 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual || | ||
| 1035 | controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { | ||
| 1036 | return NpadIsDualJoycon; | ||
| 1037 | } | ||
| 1038 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 1039 | controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) { | ||
| 1040 | return NpadIsSameType; | ||
| 1041 | } | ||
| 1042 | if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && | ||
| 1043 | controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 1044 | return NpadIsSameType; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | // These exceptions are handled as if they where dual joycon | ||
| 1048 | if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 1049 | controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 1050 | return NpadIsDualJoycon; | ||
| 1051 | } | ||
| 1052 | if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 1053 | controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) { | ||
| 1054 | return NpadIsDualJoycon; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | // Disconnect the joycons and connect them as dual joycon at the first index. | ||
| 1058 | DisconnectNpad(aruid, npad_id_1); | ||
| 1059 | DisconnectNpad(aruid, npad_id_2); | ||
| 1060 | controller_1.is_dual_left_connected = true; | ||
| 1061 | controller_1.is_dual_right_connected = true; | ||
| 1062 | AddNewControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); | ||
| 1063 | return ResultSuccess; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | Result NPad::StartLrAssignmentMode(u64 aruid) { | ||
| 1067 | std::scoped_lock lock{mutex}; | ||
| 1068 | bool is_enabled{}; | ||
| 1069 | Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); | ||
| 1070 | if (result.IsSuccess() && is_enabled == false) { | ||
| 1071 | result = npad_resource.SetLrAssignmentMode(aruid, true); | ||
| 1072 | } | ||
| 1073 | return result; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | Result NPad::StopLrAssignmentMode(u64 aruid) { | ||
| 1077 | std::scoped_lock lock{mutex}; | ||
| 1078 | bool is_enabled{}; | ||
| 1079 | Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); | ||
| 1080 | if (result.IsSuccess() && is_enabled == true) { | ||
| 1081 | result = npad_resource.SetLrAssignmentMode(aruid, false); | ||
| 1082 | } | ||
| 1083 | return result; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 1087 | Core::HID::NpadIdType npad_id_2) { | ||
| 1088 | if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { | ||
| 1089 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, | ||
| 1090 | npad_id_2); | ||
| 1091 | return ResultInvalidNpadId; | ||
| 1092 | } | ||
| 1093 | if (npad_id_1 == Core::HID::NpadIdType::Handheld || | ||
| 1094 | npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other || | ||
| 1095 | npad_id_2 == Core::HID::NpadIdType::Other) { | ||
| 1096 | return ResultSuccess; | ||
| 1097 | } | ||
| 1098 | const auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1).device; | ||
| 1099 | const auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2).device; | ||
| 1100 | const auto type_index_1 = controller_1->GetNpadStyleIndex(); | ||
| 1101 | const auto type_index_2 = controller_2->GetNpadStyleIndex(); | ||
| 1102 | const auto is_connected_1 = controller_1->IsConnected(); | ||
| 1103 | const auto is_connected_2 = controller_2->IsConnected(); | ||
| 1104 | |||
| 1105 | if (!npad_resource.IsControllerSupported(aruid, type_index_1) && is_connected_1) { | ||
| 1106 | return ResultNpadNotConnected; | ||
| 1107 | } | ||
| 1108 | if (!npad_resource.IsControllerSupported(aruid, type_index_2) && is_connected_2) { | ||
| 1109 | return ResultNpadNotConnected; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | UpdateControllerAt(aruid, type_index_2, npad_id_1, is_connected_2); | ||
| 1113 | UpdateControllerAt(aruid, type_index_1, npad_id_2, is_connected_1); | ||
| 1114 | |||
| 1115 | return ResultSuccess; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const { | ||
| 1119 | if (!IsNpadIdValid(npad_id)) { | ||
| 1120 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 1121 | return ResultInvalidNpadId; | ||
| 1122 | } | ||
| 1123 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 1124 | const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device; | ||
| 1125 | pattern = controller->GetLedPattern(); | ||
| 1126 | return ResultSuccess; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | ||
| 1130 | Core::HID::NpadIdType npad_id) const { | ||
| 1131 | std::scoped_lock lock{mutex}; | ||
| 1132 | return npad_resource.GetHomeProtectionEnabled(out_is_enabled, aruid, npad_id); | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 1136 | bool is_enabled) { | ||
| 1137 | std::scoped_lock lock{mutex}; | ||
| 1138 | return npad_resource.SetHomeProtectionEnabled(aruid, npad_id, is_enabled); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | void NPad::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { | ||
| 1142 | std::scoped_lock lock{mutex}; | ||
| 1143 | npad_resource.SetNpadAnalogStickUseCenterClamp(aruid, is_enabled); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | void NPad::ClearAllConnectedControllers() { | ||
| 1147 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1148 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1149 | if (controller.device->IsConnected() && | ||
| 1150 | controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) { | ||
| 1151 | controller.device->Disconnect(); | ||
| 1152 | controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); | ||
| 1153 | } | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | void NPad::DisconnectAllConnectedControllers() { | ||
| 1159 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1160 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1161 | controller.device->Disconnect(); | ||
| 1162 | } | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | void NPad::ConnectAllDisconnectedControllers() { | ||
| 1167 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1168 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1169 | if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None && | ||
| 1170 | !controller.device->IsConnected()) { | ||
| 1171 | controller.device->Connect(); | ||
| 1172 | } | ||
| 1173 | } | ||
| 1174 | } | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | void NPad::ClearAllControllers() { | ||
| 1178 | for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { | ||
| 1179 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1180 | controller.device->Disconnect(); | ||
| 1181 | controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); | ||
| 1182 | } | ||
| 1183 | } | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | Core::HID::NpadButton NPad::GetAndResetPressState() { | ||
| 1187 | return static_cast<Core::HID::NpadButton>(press_state.exchange(0)); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | Result NPad::ApplyNpadSystemCommonPolicy(u64 aruid) { | ||
| 1191 | std::scoped_lock lock{mutex}; | ||
| 1192 | const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, false); | ||
| 1193 | if (result.IsSuccess()) { | ||
| 1194 | OnUpdate({}); | ||
| 1195 | } | ||
| 1196 | return result; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | Result NPad::ApplyNpadSystemCommonPolicyFull(u64 aruid) { | ||
| 1200 | std::scoped_lock lock{mutex}; | ||
| 1201 | const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, true); | ||
| 1202 | if (result.IsSuccess()) { | ||
| 1203 | OnUpdate({}); | ||
| 1204 | } | ||
| 1205 | return result; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | Result NPad::ClearNpadSystemCommonPolicy(u64 aruid) { | ||
| 1209 | std::scoped_lock lock{mutex}; | ||
| 1210 | const Result result = npad_resource.ClearNpadSystemCommonPolicy(aruid); | ||
| 1211 | if (result.IsSuccess()) { | ||
| 1212 | OnUpdate({}); | ||
| 1213 | } | ||
| 1214 | return result; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | void NPad::SetRevision(u64 aruid, NpadRevision revision) { | ||
| 1218 | npad_resource.SetNpadRevision(aruid, revision); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | NpadRevision NPad::GetRevision(u64 aruid) { | ||
| 1222 | return npad_resource.GetNpadRevision(aruid); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | Result NPad::RegisterAppletResourceUserId(u64 aruid) { | ||
| 1226 | return npad_resource.RegisterAppletResourceUserId(aruid); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | void NPad::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 1230 | npad_resource.UnregisterAppletResourceUserId(aruid); | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, | ||
| 1234 | std::recursive_mutex* shared_mutex) { | ||
| 1235 | applet_resource_holder.applet_resource = resource; | ||
| 1236 | applet_resource_holder.shared_mutex = shared_mutex; | ||
| 1237 | applet_resource_holder.shared_npad_resource = &npad_resource; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1241 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) { | ||
| 1242 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1243 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | const NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1247 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { | ||
| 1248 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1249 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1253 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) { | ||
| 1254 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1255 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | const NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1259 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const { | ||
| 1260 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1261 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(u64 aruid, | ||
| 1265 | Core::HID::NpadIdType npad_id) { | ||
| 1266 | if (!IsNpadIdValid(npad_id)) { | ||
| 1267 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 1268 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 1269 | } | ||
| 1270 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 1271 | const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); | ||
| 1272 | return controller_data[aruid_index][npad_index]; | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType( | ||
| 1276 | u64 aruid, Core::HID::NpadIdType npad_id) const { | ||
| 1277 | if (!IsNpadIdValid(npad_id)) { | ||
| 1278 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 1279 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 1280 | } | ||
| 1281 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 1282 | const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); | ||
| 1283 | return controller_data[aruid_index][npad_index]; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( | ||
| 1287 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||
| 1288 | auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); | ||
| 1289 | switch (sixaxis_handle.npad_type) { | ||
| 1290 | case Core::HID::NpadStyleIndex::ProController: | ||
| 1291 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 1292 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1293 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 1294 | return controller.shared_memory->sixaxis_handheld_properties; | ||
| 1295 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 1296 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 1297 | return controller.shared_memory->sixaxis_dual_left_properties; | ||
| 1298 | } | ||
| 1299 | return controller.shared_memory->sixaxis_dual_right_properties; | ||
| 1300 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 1301 | return controller.shared_memory->sixaxis_left_properties; | ||
| 1302 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 1303 | return controller.shared_memory->sixaxis_right_properties; | ||
| 1304 | default: | ||
| 1305 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1306 | } | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( | ||
| 1310 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | ||
| 1311 | const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); | ||
| 1312 | switch (sixaxis_handle.npad_type) { | ||
| 1313 | case Core::HID::NpadStyleIndex::ProController: | ||
| 1314 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 1315 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1316 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 1317 | return controller.shared_memory->sixaxis_handheld_properties; | ||
| 1318 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 1319 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 1320 | return controller.shared_memory->sixaxis_dual_left_properties; | ||
| 1321 | } | ||
| 1322 | return controller.shared_memory->sixaxis_dual_right_properties; | ||
| 1323 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 1324 | return controller.shared_memory->sixaxis_left_properties; | ||
| 1325 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 1326 | return controller.shared_memory->sixaxis_right_properties; | ||
| 1327 | default: | ||
| 1328 | return controller.shared_memory->sixaxis_fullkey_properties; | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) { | ||
| 1333 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 1334 | const auto& shared_memory = GetControllerFromNpadIdType(aruid, npad_id).shared_memory; | ||
| 1335 | |||
| 1336 | return { | ||
| 1337 | .ui_variant = 0, | ||
| 1338 | .footer = shared_memory->applet_footer_type, | ||
| 1339 | }; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h deleted file mode 100644 index 8ab333064..000000000 --- a/src/core/hle/service/hid/controllers/npad.h +++ /dev/null | |||
| @@ -1,214 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <atomic> | ||
| 8 | #include <mutex> | ||
| 9 | #include <span> | ||
| 10 | |||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "core/hid/hid_types.h" | ||
| 13 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 14 | #include "core/hle/service/hid/controllers/npad/npad_resource.h" | ||
| 15 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 16 | |||
| 17 | namespace Core::HID { | ||
| 18 | class EmulatedController; | ||
| 19 | enum class ControllerTriggerType; | ||
| 20 | } // namespace Core::HID | ||
| 21 | |||
| 22 | namespace Kernel { | ||
| 23 | class KEvent; | ||
| 24 | class KReadableEvent; | ||
| 25 | } // namespace Kernel | ||
| 26 | |||
| 27 | namespace Service::KernelHelpers { | ||
| 28 | class ServiceContext; | ||
| 29 | } // namespace Service::KernelHelpers | ||
| 30 | |||
| 31 | union Result; | ||
| 32 | |||
| 33 | namespace Service::HID { | ||
| 34 | class AppletResource; | ||
| 35 | struct NpadInternalState; | ||
| 36 | struct NpadSixAxisSensorLifo; | ||
| 37 | struct NpadSharedMemoryFormat; | ||
| 38 | |||
| 39 | class NPad final { | ||
| 40 | public: | ||
| 41 | explicit NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); | ||
| 42 | ~NPad(); | ||
| 43 | |||
| 44 | Result Activate(); | ||
| 45 | Result Activate(u64 aruid); | ||
| 46 | |||
| 47 | Result ActivateNpadResource(); | ||
| 48 | Result ActivateNpadResource(u64 aruid); | ||
| 49 | |||
| 50 | // When the controller is requesting an update for the shared memory | ||
| 51 | void OnUpdate(const Core::Timing::CoreTiming& core_timing); | ||
| 52 | |||
| 53 | Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set); | ||
| 54 | Result GetSupportedNpadStyleSet(u64 aruid, | ||
| 55 | Core::HID::NpadStyleSet& out_supported_style_set) const; | ||
| 56 | Result GetMaskedSupportedNpadStyleSet(u64 aruid, | ||
| 57 | Core::HID::NpadStyleSet& out_supported_style_set) const; | ||
| 58 | |||
| 59 | Result SetSupportedNpadIdType(u64 aruid, | ||
| 60 | std::span<const Core::HID::NpadIdType> supported_npad_list); | ||
| 61 | |||
| 62 | Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); | ||
| 63 | Result GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const; | ||
| 64 | |||
| 65 | Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode); | ||
| 66 | Result GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const; | ||
| 67 | |||
| 68 | bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, | ||
| 69 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); | ||
| 70 | |||
| 71 | bool VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 72 | std::size_t device_index, | ||
| 73 | const Core::HID::VibrationValue& vibration_value); | ||
| 74 | |||
| 75 | void VibrateController(u64 aruid, | ||
| 76 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 77 | const Core::HID::VibrationValue& vibration_value); | ||
| 78 | |||
| 79 | void VibrateControllers( | ||
| 80 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 81 | std::span<const Core::HID::VibrationValue> vibration_values); | ||
| 82 | |||
| 83 | Core::HID::VibrationValue GetLastVibration( | ||
| 84 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 85 | |||
| 86 | void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); | ||
| 87 | |||
| 88 | void InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 89 | std::size_t device_index); | ||
| 90 | |||
| 91 | void SetPermitVibrationSession(bool permit_vibration_session); | ||
| 92 | |||
| 93 | bool IsVibrationDeviceMounted( | ||
| 94 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 95 | |||
| 96 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | ||
| 97 | Core::HID::NpadIdType npad_id); | ||
| 98 | |||
| 99 | // Adds a new controller at an index. | ||
| 100 | void AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, | ||
| 101 | Core::HID::NpadIdType npad_id); | ||
| 102 | // Adds a new controller at an index with connection status. | ||
| 103 | void UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, | ||
| 104 | Core::HID::NpadIdType npad_id, bool connected); | ||
| 105 | |||
| 106 | Result DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 107 | |||
| 108 | Result IsFirmwareUpdateAvailableForSixAxisSensor( | ||
| 109 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 110 | bool& is_firmware_available) const; | ||
| 111 | Result ResetIsSixAxisSensorDeviceNewlyAssigned( | ||
| 112 | u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); | ||
| 113 | |||
| 114 | Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; | ||
| 115 | |||
| 116 | Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, | ||
| 117 | Core::HID::NpadIdType npad_id) const; | ||
| 118 | Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 119 | bool is_enabled); | ||
| 120 | |||
| 121 | void SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); | ||
| 122 | void ClearAllConnectedControllers(); | ||
| 123 | void DisconnectAllConnectedControllers(); | ||
| 124 | void ConnectAllDisconnectedControllers(); | ||
| 125 | void ClearAllControllers(); | ||
| 126 | |||
| 127 | Result MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 128 | Core::HID::NpadIdType npad_id_2); | ||
| 129 | Result StartLrAssignmentMode(u64 aruid); | ||
| 130 | Result StopLrAssignmentMode(u64 aruid); | ||
| 131 | Result SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, | ||
| 132 | Core::HID::NpadIdType npad_id_2); | ||
| 133 | |||
| 134 | // Logical OR for all buttons presses on all controllers | ||
| 135 | // Specifically for cheat engine and other features. | ||
| 136 | Core::HID::NpadButton GetAndResetPressState(); | ||
| 137 | |||
| 138 | Result ApplyNpadSystemCommonPolicy(u64 aruid); | ||
| 139 | Result ApplyNpadSystemCommonPolicyFull(u64 aruid); | ||
| 140 | Result ClearNpadSystemCommonPolicy(u64 aruid); | ||
| 141 | |||
| 142 | void SetRevision(u64 aruid, NpadRevision revision); | ||
| 143 | NpadRevision GetRevision(u64 aruid); | ||
| 144 | |||
| 145 | Result RegisterAppletResourceUserId(u64 aruid); | ||
| 146 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 147 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, | ||
| 148 | std::recursive_mutex* shared_mutex); | ||
| 149 | |||
| 150 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); | ||
| 151 | |||
| 152 | private: | ||
| 153 | struct VibrationData { | ||
| 154 | bool device_mounted{}; | ||
| 155 | Core::HID::VibrationValue latest_vibration_value{}; | ||
| 156 | std::chrono::steady_clock::time_point last_vibration_timepoint{}; | ||
| 157 | }; | ||
| 158 | |||
| 159 | struct NpadControllerData { | ||
| 160 | NpadInternalState* shared_memory = nullptr; | ||
| 161 | Core::HID::EmulatedController* device = nullptr; | ||
| 162 | |||
| 163 | std::array<VibrationData, 2> vibration{}; | ||
| 164 | bool is_connected{}; | ||
| 165 | |||
| 166 | // Dual joycons can have only one side connected | ||
| 167 | bool is_dual_left_connected{true}; | ||
| 168 | bool is_dual_right_connected{true}; | ||
| 169 | |||
| 170 | // Current pad state | ||
| 171 | NPadGenericState npad_pad_state{}; | ||
| 172 | NPadGenericState npad_libnx_state{}; | ||
| 173 | NpadGcTriggerState npad_trigger_state{}; | ||
| 174 | int callback_key{}; | ||
| 175 | }; | ||
| 176 | |||
| 177 | void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); | ||
| 178 | void InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 179 | void RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 180 | void WriteEmptyEntry(NpadInternalState* npad); | ||
| 181 | |||
| 182 | NpadControllerData& GetControllerFromHandle( | ||
| 183 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle); | ||
| 184 | const NpadControllerData& GetControllerFromHandle( | ||
| 185 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const; | ||
| 186 | NpadControllerData& GetControllerFromHandle( | ||
| 187 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 188 | const NpadControllerData& GetControllerFromHandle( | ||
| 189 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 190 | NpadControllerData& GetControllerFromNpadIdType(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 191 | const NpadControllerData& GetControllerFromNpadIdType(u64 aruid, | ||
| 192 | Core::HID::NpadIdType npad_id) const; | ||
| 193 | |||
| 194 | Core::HID::SixAxisSensorProperties& GetSixaxisProperties( | ||
| 195 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 196 | const Core::HID::SixAxisSensorProperties& GetSixaxisProperties( | ||
| 197 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 198 | |||
| 199 | Core::HID::HIDCore& hid_core; | ||
| 200 | KernelHelpers::ServiceContext& service_context; | ||
| 201 | |||
| 202 | s32 ref_counter{}; | ||
| 203 | mutable std::mutex mutex; | ||
| 204 | NPadResource npad_resource; | ||
| 205 | AppletResourceHolder applet_resource_holder{}; | ||
| 206 | Kernel::KEvent* input_event{nullptr}; | ||
| 207 | std::mutex* input_mutex{nullptr}; | ||
| 208 | |||
| 209 | std::atomic<u64> press_state{}; | ||
| 210 | bool permit_vibration_session_enabled; | ||
| 211 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> | ||
| 212 | controller_data{}; | ||
| 213 | }; | ||
| 214 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_data.cpp b/src/core/hle/service/hid/controllers/npad/npad_data.cpp deleted file mode 100644 index d2423b6d3..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_data.cpp +++ /dev/null | |||
| @@ -1,228 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/controllers/npad/npad_data.h" | ||
| 5 | #include "core/hle/service/hid/hid_util.h" | ||
| 6 | |||
| 7 | namespace Service::HID { | ||
| 8 | |||
| 9 | NPadData::NPadData() { | ||
| 10 | ClearNpadSystemCommonPolicy(); | ||
| 11 | } | ||
| 12 | |||
| 13 | NPadData::~NPadData() = default; | ||
| 14 | |||
| 15 | NpadStatus NPadData::GetNpadStatus() const { | ||
| 16 | return status; | ||
| 17 | } | ||
| 18 | |||
| 19 | void NPadData::SetNpadAnalogStickUseCenterClamp(bool is_enabled) { | ||
| 20 | status.use_center_clamp.Assign(is_enabled); | ||
| 21 | } | ||
| 22 | |||
| 23 | bool NPadData::GetNpadAnalogStickUseCenterClamp() const { | ||
| 24 | return status.use_center_clamp.As<bool>(); | ||
| 25 | } | ||
| 26 | |||
| 27 | void NPadData::SetNpadSystemExtStateEnabled(bool is_enabled) { | ||
| 28 | status.system_ext_state.Assign(is_enabled); | ||
| 29 | } | ||
| 30 | |||
| 31 | bool NPadData::GetNpadSystemExtState() const { | ||
| 32 | return status.system_ext_state.As<bool>(); | ||
| 33 | } | ||
| 34 | |||
| 35 | Result NPadData::SetSupportedNpadIdType(std::span<const Core::HID::NpadIdType> list) { | ||
| 36 | // Note: Real limit is 11. But array size is 10. N's bug? | ||
| 37 | if (list.size() > MaxSupportedNpadIdTypes) { | ||
| 38 | return ResultInvalidArraySize; | ||
| 39 | } | ||
| 40 | |||
| 41 | supported_npad_id_types_count = list.size(); | ||
| 42 | memcpy(supported_npad_id_types.data(), list.data(), | ||
| 43 | list.size() * sizeof(Core::HID::NpadIdType)); | ||
| 44 | |||
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | |||
| 48 | std::size_t NPadData::GetSupportedNpadIdType(std::span<Core::HID::NpadIdType> out_list) const { | ||
| 49 | std::size_t out_size = std::min(supported_npad_id_types_count, out_list.size()); | ||
| 50 | |||
| 51 | memcpy(out_list.data(), supported_npad_id_types.data(), | ||
| 52 | out_size * sizeof(Core::HID::NpadIdType)); | ||
| 53 | |||
| 54 | return out_size; | ||
| 55 | } | ||
| 56 | |||
| 57 | bool NPadData::IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const { | ||
| 58 | for (std::size_t i = 0; i < supported_npad_id_types_count; i++) { | ||
| 59 | if (supported_npad_id_types[i] == npad_id) { | ||
| 60 | return true; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | return false; | ||
| 65 | } | ||
| 66 | |||
| 67 | void NPadData::SetNpadSystemCommonPolicy(bool is_full_policy) { | ||
| 68 | supported_npad_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::JoyDual | | ||
| 69 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 70 | handheld_activation_mode = NpadHandheldActivationMode::Dual; | ||
| 71 | |||
| 72 | status.is_supported_styleset_set.Assign(true); | ||
| 73 | status.is_hold_type_set.Assign(true); | ||
| 74 | status.lr_assignment_mode.Assign(false); | ||
| 75 | status.is_policy.Assign(true); | ||
| 76 | if (is_full_policy) { | ||
| 77 | status.is_full_policy.Assign(true); | ||
| 78 | } | ||
| 79 | |||
| 80 | supported_npad_id_types_count = 10; | ||
| 81 | supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; | ||
| 82 | supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; | ||
| 83 | supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; | ||
| 84 | supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; | ||
| 85 | supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; | ||
| 86 | supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; | ||
| 87 | supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; | ||
| 88 | supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; | ||
| 89 | supported_npad_id_types[8] = Core::HID::NpadIdType::Other; | ||
| 90 | supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; | ||
| 91 | |||
| 92 | for (auto& input_protection : is_unintended_home_button_input_protection) { | ||
| 93 | input_protection = true; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | void NPadData::ClearNpadSystemCommonPolicy() { | ||
| 98 | status.raw = 0; | ||
| 99 | supported_npad_style_set = Core::HID::NpadStyleSet::All; | ||
| 100 | npad_hold_type = NpadJoyHoldType::Vertical; | ||
| 101 | handheld_activation_mode = NpadHandheldActivationMode::Dual; | ||
| 102 | |||
| 103 | for (auto& button_assignment : npad_button_assignment) { | ||
| 104 | button_assignment = Core::HID::NpadButton::None; | ||
| 105 | } | ||
| 106 | |||
| 107 | supported_npad_id_types_count = 10; | ||
| 108 | supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; | ||
| 109 | supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; | ||
| 110 | supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; | ||
| 111 | supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; | ||
| 112 | supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; | ||
| 113 | supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; | ||
| 114 | supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; | ||
| 115 | supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; | ||
| 116 | supported_npad_id_types[8] = Core::HID::NpadIdType::Other; | ||
| 117 | supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; | ||
| 118 | |||
| 119 | for (auto& input_protection : is_unintended_home_button_input_protection) { | ||
| 120 | input_protection = true; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | void NPadData::SetNpadJoyHoldType(NpadJoyHoldType hold_type) { | ||
| 125 | npad_hold_type = hold_type; | ||
| 126 | status.is_hold_type_set.Assign(true); | ||
| 127 | } | ||
| 128 | |||
| 129 | NpadJoyHoldType NPadData::GetNpadJoyHoldType() const { | ||
| 130 | return npad_hold_type; | ||
| 131 | } | ||
| 132 | |||
| 133 | void NPadData::SetHandheldActivationMode(NpadHandheldActivationMode activation_mode) { | ||
| 134 | handheld_activation_mode = activation_mode; | ||
| 135 | } | ||
| 136 | |||
| 137 | NpadHandheldActivationMode NPadData::GetHandheldActivationMode() const { | ||
| 138 | return handheld_activation_mode; | ||
| 139 | } | ||
| 140 | |||
| 141 | void NPadData::SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set) { | ||
| 142 | supported_npad_style_set = style_set; | ||
| 143 | status.is_supported_styleset_set.Assign(true); | ||
| 144 | status.is_hold_type_set.Assign(true); | ||
| 145 | } | ||
| 146 | |||
| 147 | Core::HID::NpadStyleSet NPadData::GetSupportedNpadStyleSet() const { | ||
| 148 | return supported_npad_style_set; | ||
| 149 | } | ||
| 150 | |||
| 151 | bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const { | ||
| 152 | Core::HID::NpadStyleTag style = {supported_npad_style_set}; | ||
| 153 | switch (style_index) { | ||
| 154 | case Core::HID::NpadStyleIndex::ProController: | ||
| 155 | return style.fullkey.As<bool>(); | ||
| 156 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 157 | return style.handheld.As<bool>(); | ||
| 158 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 159 | return style.joycon_dual.As<bool>(); | ||
| 160 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 161 | return style.joycon_left.As<bool>(); | ||
| 162 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 163 | return style.joycon_right.As<bool>(); | ||
| 164 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 165 | return style.gamecube.As<bool>(); | ||
| 166 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 167 | return style.palma.As<bool>(); | ||
| 168 | case Core::HID::NpadStyleIndex::NES: | ||
| 169 | return style.lark.As<bool>(); | ||
| 170 | case Core::HID::NpadStyleIndex::SNES: | ||
| 171 | return style.lucia.As<bool>(); | ||
| 172 | case Core::HID::NpadStyleIndex::N64: | ||
| 173 | return style.lagoon.As<bool>(); | ||
| 174 | case Core::HID::NpadStyleIndex::SegaGenesis: | ||
| 175 | return style.lager.As<bool>(); | ||
| 176 | default: | ||
| 177 | return false; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | void NPadData::SetLrAssignmentMode(bool is_enabled) { | ||
| 182 | status.lr_assignment_mode.Assign(is_enabled); | ||
| 183 | } | ||
| 184 | |||
| 185 | bool NPadData::GetLrAssignmentMode() const { | ||
| 186 | return status.lr_assignment_mode.As<bool>(); | ||
| 187 | } | ||
| 188 | |||
| 189 | void NPadData::SetAssigningSingleOnSlSrPress(bool is_enabled) { | ||
| 190 | status.assigning_single_on_sl_sr_press.Assign(is_enabled); | ||
| 191 | } | ||
| 192 | |||
| 193 | bool NPadData::GetAssigningSingleOnSlSrPress() const { | ||
| 194 | return status.assigning_single_on_sl_sr_press.As<bool>(); | ||
| 195 | } | ||
| 196 | |||
| 197 | void NPadData::SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id) { | ||
| 198 | is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)] = is_enabled; | ||
| 199 | } | ||
| 200 | |||
| 201 | bool NPadData::GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const { | ||
| 202 | return is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)]; | ||
| 203 | } | ||
| 204 | |||
| 205 | void NPadData::SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, | ||
| 206 | std::size_t style_index) { | ||
| 207 | npad_button_assignment[style_index] = button_assignment; | ||
| 208 | } | ||
| 209 | |||
| 210 | Core::HID::NpadButton NPadData::GetCaptureButtonAssignment(std::size_t style_index) const { | ||
| 211 | return npad_button_assignment[style_index]; | ||
| 212 | } | ||
| 213 | |||
| 214 | std::size_t NPadData::GetNpadCaptureButtonAssignmentList( | ||
| 215 | std::span<Core::HID::NpadButton> out_list) const { | ||
| 216 | for (std::size_t i = 0; i < out_list.size(); i++) { | ||
| 217 | Core::HID::NpadStyleSet style_set = GetStylesetByIndex(i); | ||
| 218 | if ((style_set & supported_npad_style_set) == Core::HID::NpadStyleSet::None || | ||
| 219 | npad_button_assignment[i] == Core::HID::NpadButton::None) { | ||
| 220 | return i; | ||
| 221 | } | ||
| 222 | out_list[i] = npad_button_assignment[i]; | ||
| 223 | } | ||
| 224 | |||
| 225 | return out_list.size(); | ||
| 226 | } | ||
| 227 | |||
| 228 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_data.h b/src/core/hle/service/hid/controllers/npad/npad_data.h deleted file mode 100644 index f799a9f9c..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_data.h +++ /dev/null | |||
| @@ -1,88 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <span> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hid/hid_types.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | |||
| 16 | struct NpadStatus { | ||
| 17 | union { | ||
| 18 | u32 raw{}; | ||
| 19 | |||
| 20 | BitField<0, 1, u32> is_supported_styleset_set; | ||
| 21 | BitField<1, 1, u32> is_hold_type_set; | ||
| 22 | BitField<2, 1, u32> lr_assignment_mode; | ||
| 23 | BitField<3, 1, u32> assigning_single_on_sl_sr_press; | ||
| 24 | BitField<4, 1, u32> is_full_policy; | ||
| 25 | BitField<5, 1, u32> is_policy; | ||
| 26 | BitField<6, 1, u32> use_center_clamp; | ||
| 27 | BitField<7, 1, u32> system_ext_state; | ||
| 28 | }; | ||
| 29 | }; | ||
| 30 | static_assert(sizeof(NpadStatus) == 4, "NpadStatus is an invalid size"); | ||
| 31 | |||
| 32 | /// Handles Npad request from HID interfaces | ||
| 33 | class NPadData final { | ||
| 34 | public: | ||
| 35 | explicit NPadData(); | ||
| 36 | ~NPadData(); | ||
| 37 | |||
| 38 | NpadStatus GetNpadStatus() const; | ||
| 39 | |||
| 40 | void SetNpadAnalogStickUseCenterClamp(bool is_enabled); | ||
| 41 | bool GetNpadAnalogStickUseCenterClamp() const; | ||
| 42 | |||
| 43 | void SetNpadSystemExtStateEnabled(bool is_enabled); | ||
| 44 | bool GetNpadSystemExtState() const; | ||
| 45 | |||
| 46 | Result SetSupportedNpadIdType(std::span<const Core::HID::NpadIdType> list); | ||
| 47 | std::size_t GetSupportedNpadIdType(std::span<Core::HID::NpadIdType> out_list) const; | ||
| 48 | bool IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const; | ||
| 49 | |||
| 50 | void SetNpadSystemCommonPolicy(bool is_full_policy); | ||
| 51 | void ClearNpadSystemCommonPolicy(); | ||
| 52 | |||
| 53 | void SetNpadJoyHoldType(NpadJoyHoldType hold_type); | ||
| 54 | NpadJoyHoldType GetNpadJoyHoldType() const; | ||
| 55 | |||
| 56 | void SetHandheldActivationMode(NpadHandheldActivationMode activation_mode); | ||
| 57 | NpadHandheldActivationMode GetHandheldActivationMode() const; | ||
| 58 | |||
| 59 | void SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set); | ||
| 60 | Core::HID::NpadStyleSet GetSupportedNpadStyleSet() const; | ||
| 61 | bool IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const; | ||
| 62 | |||
| 63 | void SetLrAssignmentMode(bool is_enabled); | ||
| 64 | bool GetLrAssignmentMode() const; | ||
| 65 | |||
| 66 | void SetAssigningSingleOnSlSrPress(bool is_enabled); | ||
| 67 | bool GetAssigningSingleOnSlSrPress() const; | ||
| 68 | |||
| 69 | void SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id); | ||
| 70 | bool GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const; | ||
| 71 | |||
| 72 | void SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, | ||
| 73 | std::size_t style_index); | ||
| 74 | Core::HID::NpadButton GetCaptureButtonAssignment(std::size_t style_index) const; | ||
| 75 | std::size_t GetNpadCaptureButtonAssignmentList(std::span<Core::HID::NpadButton> out_list) const; | ||
| 76 | |||
| 77 | private: | ||
| 78 | NpadStatus status{}; | ||
| 79 | Core::HID::NpadStyleSet supported_npad_style_set{Core::HID::NpadStyleSet::All}; | ||
| 80 | NpadJoyHoldType npad_hold_type{NpadJoyHoldType::Vertical}; | ||
| 81 | NpadHandheldActivationMode handheld_activation_mode{}; | ||
| 82 | std::array<Core::HID::NpadIdType, MaxSupportedNpadIdTypes> supported_npad_id_types{}; | ||
| 83 | std::array<Core::HID::NpadButton, StyleIndexCount> npad_button_assignment{}; | ||
| 84 | std::size_t supported_npad_id_types_count{}; | ||
| 85 | std::array<bool, MaxSupportedNpadIdTypes> is_unintended_home_button_input_protection{}; | ||
| 86 | }; | ||
| 87 | |||
| 88 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_resource.cpp b/src/core/hle/service/hid/controllers/npad/npad_resource.cpp deleted file mode 100644 index 0a9341a39..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_resource.cpp +++ /dev/null | |||
| @@ -1,685 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/kernel/k_event.h" | ||
| 5 | #include "core/hle/kernel/k_readable_event.h" | ||
| 6 | #include "core/hle/service/hid/controllers/npad/npad_resource.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 8 | #include "core/hle/service/hid/errors.h" | ||
| 9 | #include "core/hle/service/hid/hid_util.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | |||
| 13 | NPadResource::NPadResource(KernelHelpers::ServiceContext& context) : service_context{context} {} | ||
| 14 | |||
| 15 | NPadResource::~NPadResource() = default; | ||
| 16 | |||
| 17 | Result NPadResource::RegisterAppletResourceUserId(u64 aruid) { | ||
| 18 | const auto aruid_index = GetIndexFromAruid(aruid); | ||
| 19 | if (aruid_index < AruidIndexMax) { | ||
| 20 | return ResultAruidAlreadyRegistered; | ||
| 21 | } | ||
| 22 | |||
| 23 | std::size_t data_index = AruidIndexMax; | ||
| 24 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 25 | if (!state[i].flag.is_initialized) { | ||
| 26 | data_index = i; | ||
| 27 | break; | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | if (data_index == AruidIndexMax) { | ||
| 32 | return ResultAruidNoAvailableEntries; | ||
| 33 | } | ||
| 34 | |||
| 35 | auto& aruid_data = state[data_index]; | ||
| 36 | |||
| 37 | aruid_data.aruid = aruid; | ||
| 38 | aruid_data.flag.is_initialized.Assign(true); | ||
| 39 | |||
| 40 | data_index = AruidIndexMax; | ||
| 41 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 42 | if (registration_list.flag[i] == RegistrationStatus::Initialized) { | ||
| 43 | if (registration_list.aruid[i] != aruid) { | ||
| 44 | continue; | ||
| 45 | } | ||
| 46 | data_index = i; | ||
| 47 | break; | ||
| 48 | } | ||
| 49 | if (registration_list.flag[i] == RegistrationStatus::None) { | ||
| 50 | data_index = i; | ||
| 51 | break; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | if (data_index == AruidIndexMax) { | ||
| 56 | return ResultSuccess; | ||
| 57 | } | ||
| 58 | |||
| 59 | registration_list.flag[data_index] = RegistrationStatus::Initialized; | ||
| 60 | registration_list.aruid[data_index] = aruid; | ||
| 61 | |||
| 62 | return ResultSuccess; | ||
| 63 | } | ||
| 64 | |||
| 65 | void NPadResource::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 66 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 67 | |||
| 68 | DestroyStyleSetUpdateEvents(aruid); | ||
| 69 | if (aruid_index < AruidIndexMax) { | ||
| 70 | state[aruid_index] = {}; | ||
| 71 | registration_list.flag[aruid_index] = RegistrationStatus::PendingDelete; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | void NPadResource::DestroyStyleSetUpdateEvents(u64 aruid) { | ||
| 76 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 77 | |||
| 78 | if (aruid_index >= AruidIndexMax) { | ||
| 79 | return; | ||
| 80 | } | ||
| 81 | |||
| 82 | for (auto& controller_state : state[aruid_index].controller_state) { | ||
| 83 | if (!controller_state.is_styleset_update_event_initialized) { | ||
| 84 | continue; | ||
| 85 | } | ||
| 86 | service_context.CloseEvent(controller_state.style_set_update_event); | ||
| 87 | controller_state.is_styleset_update_event_initialized = false; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | Result NPadResource::Activate(u64 aruid) { | ||
| 92 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 93 | |||
| 94 | if (aruid_index >= AruidIndexMax) { | ||
| 95 | return ResultSuccess; | ||
| 96 | } | ||
| 97 | |||
| 98 | auto& state_data = state[aruid_index]; | ||
| 99 | |||
| 100 | if (state_data.flag.is_assigned) { | ||
| 101 | return ResultAruidAlreadyRegistered; | ||
| 102 | } | ||
| 103 | |||
| 104 | state_data.flag.is_assigned.Assign(true); | ||
| 105 | state_data.data.ClearNpadSystemCommonPolicy(); | ||
| 106 | state_data.npad_revision = NpadRevision::Revision0; | ||
| 107 | state_data.button_config = {}; | ||
| 108 | |||
| 109 | if (active_data_aruid == aruid) { | ||
| 110 | default_hold_type = active_data.GetNpadJoyHoldType(); | ||
| 111 | active_data.SetNpadJoyHoldType(default_hold_type); | ||
| 112 | } | ||
| 113 | return ResultSuccess; | ||
| 114 | } | ||
| 115 | |||
| 116 | Result NPadResource::Activate() { | ||
| 117 | if (ref_counter == std::numeric_limits<s32>::max() - 1) { | ||
| 118 | return ResultAppletResourceOverflow; | ||
| 119 | } | ||
| 120 | if (ref_counter == 0) { | ||
| 121 | RegisterAppletResourceUserId(SystemAruid); | ||
| 122 | Activate(SystemAruid); | ||
| 123 | } | ||
| 124 | ref_counter++; | ||
| 125 | return ResultSuccess; | ||
| 126 | } | ||
| 127 | |||
| 128 | Result NPadResource::Deactivate() { | ||
| 129 | if (ref_counter == 0) { | ||
| 130 | return ResultAppletResourceNotInitialized; | ||
| 131 | } | ||
| 132 | |||
| 133 | UnregisterAppletResourceUserId(SystemAruid); | ||
| 134 | ref_counter--; | ||
| 135 | return ResultSuccess; | ||
| 136 | } | ||
| 137 | |||
| 138 | NPadData* NPadResource::GetActiveData() { | ||
| 139 | return &active_data; | ||
| 140 | } | ||
| 141 | |||
| 142 | u64 NPadResource::GetActiveDataAruid() { | ||
| 143 | return active_data_aruid; | ||
| 144 | } | ||
| 145 | |||
| 146 | void NPadResource::SetAppletResourceUserId(u64 aruid) { | ||
| 147 | if (active_data_aruid == aruid) { | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | |||
| 151 | active_data_aruid = aruid; | ||
| 152 | default_hold_type = active_data.GetNpadJoyHoldType(); | ||
| 153 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 154 | |||
| 155 | if (aruid_index >= AruidIndexMax) { | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | |||
| 159 | auto& data = state[aruid_index].data; | ||
| 160 | if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { | ||
| 161 | data.SetNpadJoyHoldType(default_hold_type); | ||
| 162 | } | ||
| 163 | |||
| 164 | active_data = data; | ||
| 165 | if (data.GetNpadStatus().is_hold_type_set) { | ||
| 166 | active_data.SetNpadJoyHoldType(default_hold_type); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | std::size_t NPadResource::GetIndexFromAruid(u64 aruid) const { | ||
| 171 | for (std::size_t i = 0; i < AruidIndexMax; i++) { | ||
| 172 | if (registration_list.flag[i] == RegistrationStatus::Initialized && | ||
| 173 | registration_list.aruid[i] == aruid) { | ||
| 174 | return i; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | return AruidIndexMax; | ||
| 178 | } | ||
| 179 | |||
| 180 | Result NPadResource::ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy) { | ||
| 181 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 182 | if (aruid_index >= AruidIndexMax) { | ||
| 183 | return ResultNpadNotConnected; | ||
| 184 | } | ||
| 185 | |||
| 186 | auto& data = state[aruid_index].data; | ||
| 187 | data.SetNpadSystemCommonPolicy(is_full_policy); | ||
| 188 | data.SetNpadJoyHoldType(default_hold_type); | ||
| 189 | if (active_data_aruid == aruid) { | ||
| 190 | active_data.SetNpadSystemCommonPolicy(is_full_policy); | ||
| 191 | active_data.SetNpadJoyHoldType(default_hold_type); | ||
| 192 | } | ||
| 193 | return ResultSuccess; | ||
| 194 | } | ||
| 195 | |||
| 196 | Result NPadResource::ClearNpadSystemCommonPolicy(u64 aruid) { | ||
| 197 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 198 | if (aruid_index >= AruidIndexMax) { | ||
| 199 | return ResultNpadNotConnected; | ||
| 200 | } | ||
| 201 | |||
| 202 | state[aruid_index].data.ClearNpadSystemCommonPolicy(); | ||
| 203 | if (active_data_aruid == aruid) { | ||
| 204 | active_data.ClearNpadSystemCommonPolicy(); | ||
| 205 | } | ||
| 206 | return ResultSuccess; | ||
| 207 | } | ||
| 208 | |||
| 209 | Result NPadResource::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set) { | ||
| 210 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 211 | if (aruid_index >= AruidIndexMax) { | ||
| 212 | return ResultNpadNotConnected; | ||
| 213 | } | ||
| 214 | |||
| 215 | auto& data = state[aruid_index].data; | ||
| 216 | data.SetSupportedNpadStyleSet(style_set); | ||
| 217 | if (active_data_aruid == aruid) { | ||
| 218 | active_data.SetSupportedNpadStyleSet(style_set); | ||
| 219 | active_data.SetNpadJoyHoldType(data.GetNpadJoyHoldType()); | ||
| 220 | } | ||
| 221 | return ResultSuccess; | ||
| 222 | } | ||
| 223 | |||
| 224 | Result NPadResource::GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, | ||
| 225 | u64 aruid) const { | ||
| 226 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 227 | if (aruid_index >= AruidIndexMax) { | ||
| 228 | return ResultNpadNotConnected; | ||
| 229 | } | ||
| 230 | |||
| 231 | auto& data = state[aruid_index].data; | ||
| 232 | if (!data.GetNpadStatus().is_supported_styleset_set) { | ||
| 233 | return ResultUndefinedStyleset; | ||
| 234 | } | ||
| 235 | |||
| 236 | out_style_Set = data.GetSupportedNpadStyleSet(); | ||
| 237 | return ResultSuccess; | ||
| 238 | } | ||
| 239 | |||
| 240 | Result NPadResource::GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, | ||
| 241 | u64 aruid) const { | ||
| 242 | if (aruid == SystemAruid) { | ||
| 243 | out_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 244 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 245 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Palma | | ||
| 246 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 247 | return ResultSuccess; | ||
| 248 | } | ||
| 249 | |||
| 250 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 251 | if (aruid_index >= AruidIndexMax) { | ||
| 252 | return ResultNpadNotConnected; | ||
| 253 | } | ||
| 254 | |||
| 255 | auto& data = state[aruid_index].data; | ||
| 256 | if (!data.GetNpadStatus().is_supported_styleset_set) { | ||
| 257 | return ResultUndefinedStyleset; | ||
| 258 | } | ||
| 259 | |||
| 260 | Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; | ||
| 261 | out_style_set = data.GetSupportedNpadStyleSet(); | ||
| 262 | |||
| 263 | switch (state[aruid_index].npad_revision) { | ||
| 264 | case NpadRevision::Revision1: | ||
| 265 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 266 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 267 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 268 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | | ||
| 269 | Core::HID::NpadStyleSet::System; | ||
| 270 | break; | ||
| 271 | case NpadRevision::Revision2: | ||
| 272 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 273 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 274 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 275 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 276 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 277 | break; | ||
| 278 | case NpadRevision::Revision3: | ||
| 279 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 280 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 281 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 282 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 283 | Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | | ||
| 284 | Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | | ||
| 285 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 286 | break; | ||
| 287 | default: | ||
| 288 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 289 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 290 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | | ||
| 291 | Core::HID::NpadStyleSet::System; | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | |||
| 295 | out_style_set = out_style_set & mask; | ||
| 296 | return ResultSuccess; | ||
| 297 | } | ||
| 298 | |||
| 299 | Result NPadResource::GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const { | ||
| 300 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 301 | if (aruid_index >= AruidIndexMax) { | ||
| 302 | return ResultNpadNotConnected; | ||
| 303 | } | ||
| 304 | |||
| 305 | auto& data = state[aruid_index].data; | ||
| 306 | if (!data.GetNpadStatus().is_supported_styleset_set) { | ||
| 307 | return ResultUndefinedStyleset; | ||
| 308 | } | ||
| 309 | |||
| 310 | Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; | ||
| 311 | out_style_set = data.GetSupportedNpadStyleSet(); | ||
| 312 | |||
| 313 | switch (state[aruid_index].npad_revision) { | ||
| 314 | case NpadRevision::Revision1: | ||
| 315 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 316 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 317 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 318 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | | ||
| 319 | Core::HID::NpadStyleSet::System; | ||
| 320 | break; | ||
| 321 | case NpadRevision::Revision2: | ||
| 322 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 323 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 324 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 325 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 326 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 327 | break; | ||
| 328 | case NpadRevision::Revision3: | ||
| 329 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 330 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 331 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | | ||
| 332 | Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | | ||
| 333 | Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | | ||
| 334 | Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | | ||
| 335 | Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; | ||
| 336 | break; | ||
| 337 | default: | ||
| 338 | mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | | ||
| 339 | Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | | ||
| 340 | Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | | ||
| 341 | Core::HID::NpadStyleSet::System; | ||
| 342 | break; | ||
| 343 | } | ||
| 344 | |||
| 345 | out_style_set = out_style_set & mask; | ||
| 346 | return ResultSuccess; | ||
| 347 | } | ||
| 348 | |||
| 349 | NpadRevision NPadResource::GetNpadRevision(u64 aruid) const { | ||
| 350 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 351 | if (aruid_index >= AruidIndexMax) { | ||
| 352 | return NpadRevision::Revision0; | ||
| 353 | } | ||
| 354 | |||
| 355 | return state[aruid_index].npad_revision; | ||
| 356 | } | ||
| 357 | |||
| 358 | Result NPadResource::IsSupportedNpadStyleSet(bool& is_set, u64 aruid) { | ||
| 359 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 360 | if (aruid_index >= AruidIndexMax) { | ||
| 361 | return ResultNpadNotConnected; | ||
| 362 | } | ||
| 363 | |||
| 364 | is_set = state[aruid_index].data.GetNpadStatus().is_supported_styleset_set.Value() != 0; | ||
| 365 | return ResultSuccess; | ||
| 366 | } | ||
| 367 | |||
| 368 | Result NPadResource::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { | ||
| 369 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 370 | if (aruid_index >= AruidIndexMax) { | ||
| 371 | return ResultNpadNotConnected; | ||
| 372 | } | ||
| 373 | |||
| 374 | state[aruid_index].data.SetNpadJoyHoldType(hold_type); | ||
| 375 | if (active_data_aruid == aruid) { | ||
| 376 | active_data.SetNpadJoyHoldType(hold_type); | ||
| 377 | } | ||
| 378 | return ResultSuccess; | ||
| 379 | } | ||
| 380 | |||
| 381 | Result NPadResource::GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const { | ||
| 382 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 383 | if (aruid_index >= AruidIndexMax) { | ||
| 384 | return ResultNpadNotConnected; | ||
| 385 | } | ||
| 386 | |||
| 387 | auto& data = state[aruid_index].data; | ||
| 388 | if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { | ||
| 389 | hold_type = active_data.GetNpadJoyHoldType(); | ||
| 390 | return ResultSuccess; | ||
| 391 | } | ||
| 392 | hold_type = data.GetNpadJoyHoldType(); | ||
| 393 | return ResultSuccess; | ||
| 394 | } | ||
| 395 | |||
| 396 | Result NPadResource::SetNpadHandheldActivationMode(u64 aruid, | ||
| 397 | NpadHandheldActivationMode activation_mode) { | ||
| 398 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 399 | if (aruid_index >= AruidIndexMax) { | ||
| 400 | return ResultNpadNotConnected; | ||
| 401 | } | ||
| 402 | |||
| 403 | state[aruid_index].data.SetHandheldActivationMode(activation_mode); | ||
| 404 | if (active_data_aruid == aruid) { | ||
| 405 | active_data.SetHandheldActivationMode(activation_mode); | ||
| 406 | } | ||
| 407 | return ResultSuccess; | ||
| 408 | } | ||
| 409 | |||
| 410 | Result NPadResource::GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, | ||
| 411 | u64 aruid) const { | ||
| 412 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 413 | if (aruid_index >= AruidIndexMax) { | ||
| 414 | return ResultNpadNotConnected; | ||
| 415 | } | ||
| 416 | |||
| 417 | activation_mode = state[aruid_index].data.GetHandheldActivationMode(); | ||
| 418 | return ResultSuccess; | ||
| 419 | } | ||
| 420 | |||
| 421 | Result NPadResource::SetSupportedNpadIdType( | ||
| 422 | u64 aruid, std::span<const Core::HID::NpadIdType> supported_npad_list) { | ||
| 423 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 424 | if (aruid_index >= AruidIndexMax) { | ||
| 425 | return ResultNpadNotConnected; | ||
| 426 | } | ||
| 427 | if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { | ||
| 428 | return ResultInvalidArraySize; | ||
| 429 | } | ||
| 430 | |||
| 431 | Result result = state[aruid_index].data.SetSupportedNpadIdType(supported_npad_list); | ||
| 432 | if (result.IsSuccess() && active_data_aruid == aruid) { | ||
| 433 | result = active_data.SetSupportedNpadIdType(supported_npad_list); | ||
| 434 | } | ||
| 435 | |||
| 436 | return result; | ||
| 437 | } | ||
| 438 | |||
| 439 | bool NPadResource::IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const { | ||
| 440 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 441 | if (aruid_index >= AruidIndexMax) { | ||
| 442 | return false; | ||
| 443 | } | ||
| 444 | return state[aruid_index].data.IsNpadStyleIndexSupported(style_index); | ||
| 445 | } | ||
| 446 | |||
| 447 | Result NPadResource::SetLrAssignmentMode(u64 aruid, bool is_enabled) { | ||
| 448 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 449 | if (aruid_index >= AruidIndexMax) { | ||
| 450 | return ResultNpadNotConnected; | ||
| 451 | } | ||
| 452 | |||
| 453 | state[aruid_index].data.SetLrAssignmentMode(is_enabled); | ||
| 454 | if (active_data_aruid == aruid) { | ||
| 455 | active_data.SetLrAssignmentMode(is_enabled); | ||
| 456 | } | ||
| 457 | return ResultSuccess; | ||
| 458 | } | ||
| 459 | |||
| 460 | Result NPadResource::GetLrAssignmentMode(bool& is_enabled, u64 aruid) const { | ||
| 461 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 462 | if (aruid_index >= AruidIndexMax) { | ||
| 463 | return ResultNpadNotConnected; | ||
| 464 | } | ||
| 465 | |||
| 466 | is_enabled = state[aruid_index].data.GetLrAssignmentMode(); | ||
| 467 | return ResultSuccess; | ||
| 468 | } | ||
| 469 | |||
| 470 | Result NPadResource::SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled) { | ||
| 471 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 472 | if (aruid_index >= AruidIndexMax) { | ||
| 473 | return ResultNpadNotConnected; | ||
| 474 | } | ||
| 475 | |||
| 476 | state[aruid_index].data.SetAssigningSingleOnSlSrPress(is_enabled); | ||
| 477 | if (active_data_aruid == aruid) { | ||
| 478 | active_data.SetAssigningSingleOnSlSrPress(is_enabled); | ||
| 479 | } | ||
| 480 | return ResultSuccess; | ||
| 481 | } | ||
| 482 | |||
| 483 | Result NPadResource::IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const { | ||
| 484 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 485 | if (aruid_index >= AruidIndexMax) { | ||
| 486 | return ResultNpadNotConnected; | ||
| 487 | } | ||
| 488 | |||
| 489 | is_enabled = state[aruid_index].data.GetAssigningSingleOnSlSrPress(); | ||
| 490 | return ResultSuccess; | ||
| 491 | } | ||
| 492 | |||
| 493 | Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, | ||
| 494 | Kernel::KReadableEvent** out_event, | ||
| 495 | Core::HID::NpadIdType npad_id) { | ||
| 496 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 497 | if (aruid_index >= AruidIndexMax) { | ||
| 498 | return ResultNpadNotConnected; | ||
| 499 | } | ||
| 500 | |||
| 501 | auto& controller_state = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; | ||
| 502 | if (!controller_state.is_styleset_update_event_initialized) { | ||
| 503 | // Auto clear = true | ||
| 504 | controller_state.style_set_update_event = | ||
| 505 | service_context.CreateEvent("NpadResource:StylesetUpdateEvent"); | ||
| 506 | |||
| 507 | // Assume creating the event succeeds otherwise crash the system here | ||
| 508 | controller_state.is_styleset_update_event_initialized = true; | ||
| 509 | } | ||
| 510 | |||
| 511 | *out_event = &controller_state.style_set_update_event->GetReadableEvent(); | ||
| 512 | |||
| 513 | if (controller_state.is_styleset_update_event_initialized) { | ||
| 514 | controller_state.style_set_update_event->Signal(); | ||
| 515 | } | ||
| 516 | |||
| 517 | return ResultSuccess; | ||
| 518 | } | ||
| 519 | |||
| 520 | Result NPadResource::SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id) { | ||
| 521 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 522 | if (aruid_index >= AruidIndexMax) { | ||
| 523 | return ResultNpadNotConnected; | ||
| 524 | } | ||
| 525 | auto controller = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; | ||
| 526 | if (controller.is_styleset_update_event_initialized) { | ||
| 527 | controller.style_set_update_event->Signal(); | ||
| 528 | } | ||
| 529 | return ResultSuccess; | ||
| 530 | } | ||
| 531 | |||
| 532 | Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, | ||
| 533 | Core::HID::NpadIdType npad_id) const { | ||
| 534 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 535 | if (aruid_index >= AruidIndexMax) { | ||
| 536 | return ResultNpadNotConnected; | ||
| 537 | } | ||
| 538 | |||
| 539 | is_enabled = state[aruid_index].data.GetHomeProtectionEnabled(npad_id); | ||
| 540 | return ResultSuccess; | ||
| 541 | } | ||
| 542 | |||
| 543 | Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 544 | bool is_enabled) { | ||
| 545 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 546 | if (aruid_index >= AruidIndexMax) { | ||
| 547 | return ResultNpadNotConnected; | ||
| 548 | } | ||
| 549 | |||
| 550 | state[aruid_index].data.SetHomeProtectionEnabled(is_enabled, npad_id); | ||
| 551 | if (active_data_aruid == aruid) { | ||
| 552 | active_data.SetHomeProtectionEnabled(is_enabled, npad_id); | ||
| 553 | } | ||
| 554 | return ResultSuccess; | ||
| 555 | } | ||
| 556 | |||
| 557 | Result NPadResource::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { | ||
| 558 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 559 | if (aruid_index >= AruidIndexMax) { | ||
| 560 | return ResultNpadNotConnected; | ||
| 561 | } | ||
| 562 | |||
| 563 | state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 564 | if (active_data_aruid == aruid) { | ||
| 565 | active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 566 | } | ||
| 567 | return ResultSuccess; | ||
| 568 | } | ||
| 569 | |||
| 570 | Result NPadResource::SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, | ||
| 571 | Core::HID::NpadButton button_config) { | ||
| 572 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 573 | if (aruid_index >= AruidIndexMax) { | ||
| 574 | return ResultNpadNotConnected; | ||
| 575 | } | ||
| 576 | |||
| 577 | state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index] = button_config; | ||
| 578 | return ResultSuccess; | ||
| 579 | } | ||
| 580 | |||
| 581 | Core::HID::NpadButton NPadResource::GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 582 | std::size_t index, Core::HID::NpadButton mask, | ||
| 583 | bool is_enabled) { | ||
| 584 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 585 | if (aruid_index >= AruidIndexMax) { | ||
| 586 | return Core::HID::NpadButton::None; | ||
| 587 | } | ||
| 588 | |||
| 589 | auto& button_config = state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index]; | ||
| 590 | if (is_enabled) { | ||
| 591 | button_config = button_config | mask; | ||
| 592 | return button_config; | ||
| 593 | } | ||
| 594 | |||
| 595 | button_config = Core::HID::NpadButton::None; | ||
| 596 | return Core::HID::NpadButton::None; | ||
| 597 | } | ||
| 598 | |||
| 599 | void NPadResource::ResetButtonConfig() { | ||
| 600 | for (auto& selected_state : state) { | ||
| 601 | selected_state.button_config = {}; | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | Result NPadResource::SetNpadCaptureButtonAssignment(u64 aruid, | ||
| 606 | Core::HID::NpadStyleSet npad_style_set, | ||
| 607 | Core::HID::NpadButton button_assignment) { | ||
| 608 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 609 | if (aruid_index >= AruidIndexMax) { | ||
| 610 | return ResultNpadNotConnected; | ||
| 611 | } | ||
| 612 | |||
| 613 | // Must be a power of two | ||
| 614 | const auto raw_styleset = static_cast<u32>(npad_style_set); | ||
| 615 | if (raw_styleset == 0 && (raw_styleset & (raw_styleset - 1)) != 0) { | ||
| 616 | return ResultMultipleStyleSetSelected; | ||
| 617 | } | ||
| 618 | |||
| 619 | std::size_t style_index{}; | ||
| 620 | Core::HID::NpadStyleSet style_selected{}; | ||
| 621 | for (style_index = 0; style_index < StyleIndexCount; ++style_index) { | ||
| 622 | style_selected = GetStylesetByIndex(style_index); | ||
| 623 | if (npad_style_set == style_selected) { | ||
| 624 | break; | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 628 | if (style_selected == Core::HID::NpadStyleSet::None) { | ||
| 629 | return ResultMultipleStyleSetSelected; | ||
| 630 | } | ||
| 631 | |||
| 632 | state[aruid_index].data.SetCaptureButtonAssignment(button_assignment, style_index); | ||
| 633 | if (active_data_aruid == aruid) { | ||
| 634 | active_data.SetCaptureButtonAssignment(button_assignment, style_index); | ||
| 635 | } | ||
| 636 | return ResultSuccess; | ||
| 637 | } | ||
| 638 | |||
| 639 | Result NPadResource::ClearNpadCaptureButtonAssignment(u64 aruid) { | ||
| 640 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 641 | if (aruid_index >= AruidIndexMax) { | ||
| 642 | return ResultNpadNotConnected; | ||
| 643 | } | ||
| 644 | |||
| 645 | for (std::size_t i = 0; i < StyleIndexCount; i++) { | ||
| 646 | state[aruid_index].data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); | ||
| 647 | if (active_data_aruid == aruid) { | ||
| 648 | active_data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); | ||
| 649 | } | ||
| 650 | } | ||
| 651 | return ResultSuccess; | ||
| 652 | } | ||
| 653 | |||
| 654 | std::size_t NPadResource::GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list, | ||
| 655 | u64 aruid) const { | ||
| 656 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 657 | if (aruid_index >= AruidIndexMax) { | ||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | return state[aruid_index].data.GetNpadCaptureButtonAssignmentList(out_list); | ||
| 661 | } | ||
| 662 | |||
| 663 | void NPadResource::SetNpadRevision(u64 aruid, NpadRevision revision) { | ||
| 664 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 665 | if (aruid_index >= AruidIndexMax) { | ||
| 666 | return; | ||
| 667 | } | ||
| 668 | |||
| 669 | state[aruid_index].npad_revision = revision; | ||
| 670 | } | ||
| 671 | |||
| 672 | Result NPadResource::SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled) { | ||
| 673 | const u64 aruid_index = GetIndexFromAruid(aruid); | ||
| 674 | if (aruid_index >= AruidIndexMax) { | ||
| 675 | return ResultNpadNotConnected; | ||
| 676 | } | ||
| 677 | |||
| 678 | state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 679 | if (active_data_aruid == aruid) { | ||
| 680 | active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); | ||
| 681 | } | ||
| 682 | return ResultSuccess; | ||
| 683 | } | ||
| 684 | |||
| 685 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/npad/npad_resource.h b/src/core/hle/service/hid/controllers/npad/npad_resource.h deleted file mode 100644 index 4c7e6ab0e..000000000 --- a/src/core/hle/service/hid/controllers/npad/npad_resource.h +++ /dev/null | |||
| @@ -1,132 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <mutex> | ||
| 8 | #include <span> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "core/hid/hid_types.h" | ||
| 12 | #include "core/hle/result.h" | ||
| 13 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 14 | #include "core/hle/service/hid/controllers/npad/npad_data.h" | ||
| 15 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 16 | #include "core/hle/service/kernel_helpers.h" | ||
| 17 | |||
| 18 | namespace Core { | ||
| 19 | class System; | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace Kernel { | ||
| 23 | class KReadableEvent; | ||
| 24 | } | ||
| 25 | |||
| 26 | namespace Service::HID { | ||
| 27 | struct DataStatusFlag; | ||
| 28 | |||
| 29 | struct NpadControllerState { | ||
| 30 | bool is_styleset_update_event_initialized{}; | ||
| 31 | INSERT_PADDING_BYTES(0x7); | ||
| 32 | Kernel::KEvent* style_set_update_event{nullptr}; | ||
| 33 | INSERT_PADDING_BYTES(0x27); | ||
| 34 | }; | ||
| 35 | |||
| 36 | struct NpadState { | ||
| 37 | DataStatusFlag flag{}; | ||
| 38 | u64 aruid{}; | ||
| 39 | NPadData data{}; | ||
| 40 | std::array<std::array<Core::HID::NpadButton, StyleIndexCount>, MaxSupportedNpadIdTypes> | ||
| 41 | button_config; | ||
| 42 | std::array<NpadControllerState, MaxSupportedNpadIdTypes> controller_state; | ||
| 43 | NpadRevision npad_revision; | ||
| 44 | }; | ||
| 45 | |||
| 46 | /// Handles Npad request from HID interfaces | ||
| 47 | class NPadResource final { | ||
| 48 | public: | ||
| 49 | explicit NPadResource(KernelHelpers::ServiceContext& context); | ||
| 50 | ~NPadResource(); | ||
| 51 | |||
| 52 | NPadData* GetActiveData(); | ||
| 53 | u64 GetActiveDataAruid(); | ||
| 54 | |||
| 55 | Result RegisterAppletResourceUserId(u64 aruid); | ||
| 56 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 57 | |||
| 58 | void DestroyStyleSetUpdateEvents(u64 aruid); | ||
| 59 | |||
| 60 | Result Activate(u64 aruid); | ||
| 61 | Result Activate(); | ||
| 62 | Result Deactivate(); | ||
| 63 | |||
| 64 | void SetAppletResourceUserId(u64 aruid); | ||
| 65 | std::size_t GetIndexFromAruid(u64 aruid) const; | ||
| 66 | |||
| 67 | Result ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy); | ||
| 68 | Result ClearNpadSystemCommonPolicy(u64 aruid); | ||
| 69 | |||
| 70 | Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set); | ||
| 71 | Result GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, u64 aruid) const; | ||
| 72 | Result GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; | ||
| 73 | Result GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; | ||
| 74 | |||
| 75 | NpadRevision GetNpadRevision(u64 aruid) const; | ||
| 76 | void SetNpadRevision(u64 aruid, NpadRevision revision); | ||
| 77 | |||
| 78 | Result IsSupportedNpadStyleSet(bool& is_set, u64 aruid); | ||
| 79 | |||
| 80 | Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); | ||
| 81 | Result GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const; | ||
| 82 | |||
| 83 | Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode activation_mode); | ||
| 84 | Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, | ||
| 85 | u64 aruid) const; | ||
| 86 | |||
| 87 | Result SetSupportedNpadIdType(u64 aruid, | ||
| 88 | std::span<const Core::HID::NpadIdType> supported_npad_list); | ||
| 89 | bool IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const; | ||
| 90 | |||
| 91 | Result SetLrAssignmentMode(u64 aruid, bool is_enabled); | ||
| 92 | Result GetLrAssignmentMode(bool& is_enabled, u64 aruid) const; | ||
| 93 | |||
| 94 | Result SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled); | ||
| 95 | Result IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const; | ||
| 96 | |||
| 97 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | ||
| 98 | Core::HID::NpadIdType npad_id); | ||
| 99 | Result SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id); | ||
| 100 | |||
| 101 | Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, | ||
| 102 | Core::HID::NpadIdType npad_id) const; | ||
| 103 | Result SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled); | ||
| 104 | |||
| 105 | Result SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); | ||
| 106 | |||
| 107 | Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, | ||
| 108 | Core::HID::NpadButton button_config); | ||
| 109 | Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 110 | std::size_t index, Core::HID::NpadButton mask, | ||
| 111 | bool is_enabled); | ||
| 112 | void ResetButtonConfig(); | ||
| 113 | |||
| 114 | Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, | ||
| 115 | Core::HID::NpadButton button_assignment); | ||
| 116 | Result ClearNpadCaptureButtonAssignment(u64 aruid); | ||
| 117 | std::size_t GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list, | ||
| 118 | u64 aruid) const; | ||
| 119 | |||
| 120 | Result SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled); | ||
| 121 | |||
| 122 | private: | ||
| 123 | NPadData active_data{}; | ||
| 124 | AruidRegisterList registration_list{}; | ||
| 125 | std::array<NpadState, AruidIndexMax> state{}; | ||
| 126 | u64 active_data_aruid{}; | ||
| 127 | NpadJoyHoldType default_hold_type{}; | ||
| 128 | s32 ref_counter{}; | ||
| 129 | |||
| 130 | KernelHelpers::ServiceContext& service_context; | ||
| 131 | }; | ||
| 132 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp deleted file mode 100644 index aa0454b5e..000000000 --- a/src/core/hle/service/hid/controllers/palma.cpp +++ /dev/null | |||
| @@ -1,226 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hid/emulated_controller.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | #include "core/hle/kernel/k_event.h" | ||
| 9 | #include "core/hle/kernel/k_readable_event.h" | ||
| 10 | #include "core/hle/service/hid/controllers/palma.h" | ||
| 11 | #include "core/hle/service/kernel_helpers.h" | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) | ||
| 16 | : ControllerBase{hid_core_}, service_context{service_context_} { | ||
| 17 | controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); | ||
| 18 | operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); | ||
| 19 | } | ||
| 20 | |||
| 21 | Palma::~Palma() { | ||
| 22 | service_context.CloseEvent(operation_complete_event); | ||
| 23 | }; | ||
| 24 | |||
| 25 | void Palma::OnInit() {} | ||
| 26 | |||
| 27 | void Palma::OnRelease() {} | ||
| 28 | |||
| 29 | void Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 30 | if (!IsControllerActivated()) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | Result Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, | ||
| 36 | PalmaConnectionHandle& handle) { | ||
| 37 | active_handle.npad_id = npad_id; | ||
| 38 | handle = active_handle; | ||
| 39 | return ResultSuccess; | ||
| 40 | } | ||
| 41 | |||
| 42 | Result Palma::InitializePalma(const PalmaConnectionHandle& handle) { | ||
| 43 | if (handle.npad_id != active_handle.npad_id) { | ||
| 44 | return InvalidPalmaHandle; | ||
| 45 | } | ||
| 46 | Activate(); | ||
| 47 | return ResultSuccess; | ||
| 48 | } | ||
| 49 | |||
| 50 | Kernel::KReadableEvent& Palma::AcquirePalmaOperationCompleteEvent( | ||
| 51 | const PalmaConnectionHandle& handle) const { | ||
| 52 | if (handle.npad_id != active_handle.npad_id) { | ||
| 53 | LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id); | ||
| 54 | } | ||
| 55 | return operation_complete_event->GetReadableEvent(); | ||
| 56 | } | ||
| 57 | |||
| 58 | Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle, | ||
| 59 | PalmaOperationType& operation_type, | ||
| 60 | PalmaOperationData& data) const { | ||
| 61 | if (handle.npad_id != active_handle.npad_id) { | ||
| 62 | return InvalidPalmaHandle; | ||
| 63 | } | ||
| 64 | operation_type = operation.operation; | ||
| 65 | data = operation.data; | ||
| 66 | return ResultSuccess; | ||
| 67 | } | ||
| 68 | |||
| 69 | Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity) { | ||
| 70 | if (handle.npad_id != active_handle.npad_id) { | ||
| 71 | return InvalidPalmaHandle; | ||
| 72 | } | ||
| 73 | operation.operation = PalmaOperationType::PlayActivity; | ||
| 74 | operation.result = PalmaResultSuccess; | ||
| 75 | operation.data = {}; | ||
| 76 | operation_complete_event->Signal(); | ||
| 77 | return ResultSuccess; | ||
| 78 | } | ||
| 79 | |||
| 80 | Result Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_) { | ||
| 81 | if (handle.npad_id != active_handle.npad_id) { | ||
| 82 | return InvalidPalmaHandle; | ||
| 83 | } | ||
| 84 | fr_mode = fr_mode_; | ||
| 85 | return ResultSuccess; | ||
| 86 | } | ||
| 87 | |||
| 88 | Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { | ||
| 89 | if (handle.npad_id != active_handle.npad_id) { | ||
| 90 | return InvalidPalmaHandle; | ||
| 91 | } | ||
| 92 | operation.operation = PalmaOperationType::ReadStep; | ||
| 93 | operation.result = PalmaResultSuccess; | ||
| 94 | operation.data = {}; | ||
| 95 | operation_complete_event->Signal(); | ||
| 96 | return ResultSuccess; | ||
| 97 | } | ||
| 98 | |||
| 99 | Result Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) { | ||
| 100 | if (handle.npad_id != active_handle.npad_id) { | ||
| 101 | return InvalidPalmaHandle; | ||
| 102 | } | ||
| 103 | return ResultSuccess; | ||
| 104 | } | ||
| 105 | |||
| 106 | Result Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) { | ||
| 107 | if (handle.npad_id != active_handle.npad_id) { | ||
| 108 | return InvalidPalmaHandle; | ||
| 109 | } | ||
| 110 | return ResultSuccess; | ||
| 111 | } | ||
| 112 | |||
| 113 | void Palma::ReadPalmaApplicationSection() {} | ||
| 114 | |||
| 115 | void Palma::WritePalmaApplicationSection() {} | ||
| 116 | |||
| 117 | Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { | ||
| 118 | if (handle.npad_id != active_handle.npad_id) { | ||
| 119 | return InvalidPalmaHandle; | ||
| 120 | } | ||
| 121 | operation.operation = PalmaOperationType::ReadUniqueCode; | ||
| 122 | operation.result = PalmaResultSuccess; | ||
| 123 | operation.data = {}; | ||
| 124 | operation_complete_event->Signal(); | ||
| 125 | return ResultSuccess; | ||
| 126 | } | ||
| 127 | |||
| 128 | Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { | ||
| 129 | if (handle.npad_id != active_handle.npad_id) { | ||
| 130 | return InvalidPalmaHandle; | ||
| 131 | } | ||
| 132 | operation.operation = PalmaOperationType::SetUniqueCodeInvalid; | ||
| 133 | operation.result = PalmaResultSuccess; | ||
| 134 | operation.data = {}; | ||
| 135 | operation_complete_event->Signal(); | ||
| 136 | return ResultSuccess; | ||
| 137 | } | ||
| 138 | |||
| 139 | void Palma::WritePalmaActivityEntry() {} | ||
| 140 | |||
| 141 | Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown) { | ||
| 142 | if (handle.npad_id != active_handle.npad_id) { | ||
| 143 | return InvalidPalmaHandle; | ||
| 144 | } | ||
| 145 | operation.operation = PalmaOperationType::WriteRgbLedPatternEntry; | ||
| 146 | operation.result = PalmaResultSuccess; | ||
| 147 | operation.data = {}; | ||
| 148 | operation_complete_event->Signal(); | ||
| 149 | return ResultSuccess; | ||
| 150 | } | ||
| 151 | |||
| 152 | Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, | ||
| 153 | Common::ProcessAddress t_mem, u64 size) { | ||
| 154 | if (handle.npad_id != active_handle.npad_id) { | ||
| 155 | return InvalidPalmaHandle; | ||
| 156 | } | ||
| 157 | operation.operation = PalmaOperationType::WriteWaveEntry; | ||
| 158 | operation.result = PalmaResultSuccess; | ||
| 159 | operation.data = {}; | ||
| 160 | operation_complete_event->Signal(); | ||
| 161 | return ResultSuccess; | ||
| 162 | } | ||
| 163 | |||
| 164 | Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, | ||
| 165 | s32 database_id_version_) { | ||
| 166 | if (handle.npad_id != active_handle.npad_id) { | ||
| 167 | return InvalidPalmaHandle; | ||
| 168 | } | ||
| 169 | database_id_version = database_id_version_; | ||
| 170 | operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; | ||
| 171 | operation.result = PalmaResultSuccess; | ||
| 172 | operation.data[0] = {}; | ||
| 173 | operation_complete_event->Signal(); | ||
| 174 | return ResultSuccess; | ||
| 175 | } | ||
| 176 | |||
| 177 | Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle) { | ||
| 178 | if (handle.npad_id != active_handle.npad_id) { | ||
| 179 | return InvalidPalmaHandle; | ||
| 180 | } | ||
| 181 | operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; | ||
| 182 | operation.result = PalmaResultSuccess; | ||
| 183 | operation.data = {}; | ||
| 184 | operation.data[0] = static_cast<u8>(database_id_version); | ||
| 185 | operation_complete_event->Signal(); | ||
| 186 | return ResultSuccess; | ||
| 187 | } | ||
| 188 | |||
| 189 | void Palma::SuspendPalmaFeature() {} | ||
| 190 | |||
| 191 | Result Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const { | ||
| 192 | if (handle.npad_id != active_handle.npad_id) { | ||
| 193 | return InvalidPalmaHandle; | ||
| 194 | } | ||
| 195 | return operation.result; | ||
| 196 | } | ||
| 197 | void Palma::ReadPalmaPlayLog() {} | ||
| 198 | |||
| 199 | void Palma::ResetPalmaPlayLog() {} | ||
| 200 | |||
| 201 | void Palma::SetIsPalmaAllConnectable(bool is_all_connectable) { | ||
| 202 | // If true controllers are able to be paired | ||
| 203 | is_connectable = is_all_connectable; | ||
| 204 | } | ||
| 205 | |||
| 206 | void Palma::SetIsPalmaPairedConnectable() {} | ||
| 207 | |||
| 208 | Result Palma::PairPalma(const PalmaConnectionHandle& handle) { | ||
| 209 | if (handle.npad_id != active_handle.npad_id) { | ||
| 210 | return InvalidPalmaHandle; | ||
| 211 | } | ||
| 212 | // TODO: Do something | ||
| 213 | return ResultSuccess; | ||
| 214 | } | ||
| 215 | |||
| 216 | void Palma::SetPalmaBoostMode(bool boost_mode) {} | ||
| 217 | |||
| 218 | void Palma::CancelWritePalmaWaveEntry() {} | ||
| 219 | |||
| 220 | void Palma::EnablePalmaBoostMode() {} | ||
| 221 | |||
| 222 | void Palma::GetPalmaBluetoothAddress() {} | ||
| 223 | |||
| 224 | void Palma::SetDisallowedPalmaConnection() {} | ||
| 225 | |||
| 226 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h deleted file mode 100644 index 73884230d..000000000 --- a/src/core/hle/service/hid/controllers/palma.h +++ /dev/null | |||
| @@ -1,162 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include "common/common_funcs.h" | ||
| 8 | #include "common/typed_address.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/errors.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | class KEvent; | ||
| 14 | class KReadableEvent; | ||
| 15 | } // namespace Kernel | ||
| 16 | |||
| 17 | namespace Service::KernelHelpers { | ||
| 18 | class ServiceContext; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Core::HID { | ||
| 22 | class EmulatedController; | ||
| 23 | } // namespace Core::HID | ||
| 24 | |||
| 25 | namespace Service::HID { | ||
| 26 | class Palma final : public ControllerBase { | ||
| 27 | public: | ||
| 28 | using PalmaOperationData = std::array<u8, 0x140>; | ||
| 29 | |||
| 30 | // This is nn::hid::PalmaOperationType | ||
| 31 | enum class PalmaOperationType { | ||
| 32 | PlayActivity, | ||
| 33 | SetFrModeType, | ||
| 34 | ReadStep, | ||
| 35 | EnableStep, | ||
| 36 | ResetStep, | ||
| 37 | ReadApplicationSection, | ||
| 38 | WriteApplicationSection, | ||
| 39 | ReadUniqueCode, | ||
| 40 | SetUniqueCodeInvalid, | ||
| 41 | WriteActivityEntry, | ||
| 42 | WriteRgbLedPatternEntry, | ||
| 43 | WriteWaveEntry, | ||
| 44 | ReadDataBaseIdentificationVersion, | ||
| 45 | WriteDataBaseIdentificationVersion, | ||
| 46 | SuspendFeature, | ||
| 47 | ReadPlayLog, | ||
| 48 | ResetPlayLog, | ||
| 49 | }; | ||
| 50 | |||
| 51 | // This is nn::hid::PalmaWaveSet | ||
| 52 | enum class PalmaWaveSet : u64 { | ||
| 53 | Small, | ||
| 54 | Medium, | ||
| 55 | Large, | ||
| 56 | }; | ||
| 57 | |||
| 58 | // This is nn::hid::PalmaFrModeType | ||
| 59 | enum class PalmaFrModeType : u64 { | ||
| 60 | Off, | ||
| 61 | B01, | ||
| 62 | B02, | ||
| 63 | B03, | ||
| 64 | Downloaded, | ||
| 65 | }; | ||
| 66 | |||
| 67 | // This is nn::hid::PalmaFeature | ||
| 68 | enum class PalmaFeature : u64 { | ||
| 69 | FrMode, | ||
| 70 | RumbleFeedback, | ||
| 71 | Step, | ||
| 72 | MuteSwitch, | ||
| 73 | }; | ||
| 74 | |||
| 75 | // This is nn::hid::PalmaOperationInfo | ||
| 76 | struct PalmaOperationInfo { | ||
| 77 | PalmaOperationType operation{}; | ||
| 78 | Result result{PalmaResultSuccess}; | ||
| 79 | PalmaOperationData data{}; | ||
| 80 | }; | ||
| 81 | static_assert(sizeof(PalmaOperationInfo) == 0x148, "PalmaOperationInfo is an invalid size"); | ||
| 82 | |||
| 83 | // This is nn::hid::PalmaActivityEntry | ||
| 84 | struct PalmaActivityEntry { | ||
| 85 | u32 rgb_led_pattern_index; | ||
| 86 | INSERT_PADDING_BYTES(2); | ||
| 87 | PalmaWaveSet wave_set; | ||
| 88 | u32 wave_index; | ||
| 89 | INSERT_PADDING_BYTES(12); | ||
| 90 | }; | ||
| 91 | static_assert(sizeof(PalmaActivityEntry) == 0x20, "PalmaActivityEntry is an invalid size"); | ||
| 92 | |||
| 93 | struct PalmaConnectionHandle { | ||
| 94 | Core::HID::NpadIdType npad_id; | ||
| 95 | INSERT_PADDING_BYTES(4); // Unknown | ||
| 96 | }; | ||
| 97 | static_assert(sizeof(PalmaConnectionHandle) == 0x8, | ||
| 98 | "PalmaConnectionHandle has incorrect size."); | ||
| 99 | |||
| 100 | explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); | ||
| 101 | ~Palma() override; | ||
| 102 | |||
| 103 | // Called when the controller is initialized | ||
| 104 | void OnInit() override; | ||
| 105 | |||
| 106 | // When the controller is released | ||
| 107 | void OnRelease() override; | ||
| 108 | |||
| 109 | // When the controller is requesting an update for the shared memory | ||
| 110 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 111 | |||
| 112 | Result GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, PalmaConnectionHandle& handle); | ||
| 113 | Result InitializePalma(const PalmaConnectionHandle& handle); | ||
| 114 | Kernel::KReadableEvent& AcquirePalmaOperationCompleteEvent( | ||
| 115 | const PalmaConnectionHandle& handle) const; | ||
| 116 | Result GetPalmaOperationInfo(const PalmaConnectionHandle& handle, | ||
| 117 | PalmaOperationType& operation_type, | ||
| 118 | PalmaOperationData& data) const; | ||
| 119 | Result PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity); | ||
| 120 | Result SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_); | ||
| 121 | Result ReadPalmaStep(const PalmaConnectionHandle& handle); | ||
| 122 | Result EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled); | ||
| 123 | Result ResetPalmaStep(const PalmaConnectionHandle& handle); | ||
| 124 | Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle); | ||
| 125 | Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle); | ||
| 126 | Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown); | ||
| 127 | Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, | ||
| 128 | Common::ProcessAddress t_mem, u64 size); | ||
| 129 | Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, | ||
| 130 | s32 database_id_version_); | ||
| 131 | Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle); | ||
| 132 | Result GetPalmaOperationResult(const PalmaConnectionHandle& handle) const; | ||
| 133 | void SetIsPalmaAllConnectable(bool is_all_connectable); | ||
| 134 | Result PairPalma(const PalmaConnectionHandle& handle); | ||
| 135 | void SetPalmaBoostMode(bool boost_mode); | ||
| 136 | |||
| 137 | private: | ||
| 138 | void ReadPalmaApplicationSection(); | ||
| 139 | void WritePalmaApplicationSection(); | ||
| 140 | void WritePalmaActivityEntry(); | ||
| 141 | void SuspendPalmaFeature(); | ||
| 142 | void ReadPalmaPlayLog(); | ||
| 143 | void ResetPalmaPlayLog(); | ||
| 144 | void SetIsPalmaPairedConnectable(); | ||
| 145 | void CancelWritePalmaWaveEntry(); | ||
| 146 | void EnablePalmaBoostMode(); | ||
| 147 | void GetPalmaBluetoothAddress(); | ||
| 148 | void SetDisallowedPalmaConnection(); | ||
| 149 | |||
| 150 | bool is_connectable{}; | ||
| 151 | s32 database_id_version{}; | ||
| 152 | PalmaOperationInfo operation{}; | ||
| 153 | PalmaFrModeType fr_mode{}; | ||
| 154 | PalmaConnectionHandle active_handle{}; | ||
| 155 | |||
| 156 | Core::HID::EmulatedController* controller; | ||
| 157 | |||
| 158 | Kernel::KEvent* operation_complete_event; | ||
| 159 | KernelHelpers::ServiceContext& service_context; | ||
| 160 | }; | ||
| 161 | |||
| 162 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/seven_six_axis.cpp b/src/core/hle/service/hid/controllers/seven_six_axis.cpp deleted file mode 100644 index 495568484..000000000 --- a/src/core/hle/service/hid/controllers/seven_six_axis.cpp +++ /dev/null | |||
| @@ -1,66 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <cstring> | ||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/core_timing.h" | ||
| 8 | #include "core/frontend/emu_window.h" | ||
| 9 | #include "core/hid/emulated_console.h" | ||
| 10 | #include "core/hid/emulated_devices.h" | ||
| 11 | #include "core/hid/hid_core.h" | ||
| 12 | #include "core/hle/service/hid/controllers/seven_six_axis.h" | ||
| 13 | #include "core/memory.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | SevenSixAxis::SevenSixAxis(Core::System& system_) | ||
| 17 | : ControllerBase{system_.HIDCore()}, system{system_} { | ||
| 18 | console = hid_core.GetEmulatedConsole(); | ||
| 19 | } | ||
| 20 | |||
| 21 | SevenSixAxis::~SevenSixAxis() = default; | ||
| 22 | |||
| 23 | void SevenSixAxis::OnInit() {} | ||
| 24 | void SevenSixAxis::OnRelease() {} | ||
| 25 | |||
| 26 | void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 27 | if (!IsControllerActivated() || transfer_memory == 0) { | ||
| 28 | seven_sixaxis_lifo.buffer_count = 0; | ||
| 29 | seven_sixaxis_lifo.buffer_tail = 0; | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | |||
| 33 | const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state; | ||
| 34 | next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1; | ||
| 35 | |||
| 36 | const auto motion_status = console->GetMotion(); | ||
| 37 | last_global_timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 38 | |||
| 39 | // This value increments every time the switch goes to sleep | ||
| 40 | next_seven_sixaxis_state.unknown = 1; | ||
| 41 | next_seven_sixaxis_state.timestamp = last_global_timestamp - last_saved_timestamp; | ||
| 42 | next_seven_sixaxis_state.accel = motion_status.accel; | ||
| 43 | next_seven_sixaxis_state.gyro = motion_status.gyro; | ||
| 44 | next_seven_sixaxis_state.quaternion = { | ||
| 45 | { | ||
| 46 | motion_status.quaternion.xyz.y, | ||
| 47 | motion_status.quaternion.xyz.x, | ||
| 48 | -motion_status.quaternion.w, | ||
| 49 | }, | ||
| 50 | -motion_status.quaternion.xyz.z, | ||
| 51 | }; | ||
| 52 | |||
| 53 | seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); | ||
| 54 | system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, | ||
| 55 | sizeof(seven_sixaxis_lifo)); | ||
| 56 | } | ||
| 57 | |||
| 58 | void SevenSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { | ||
| 59 | transfer_memory = t_mem; | ||
| 60 | } | ||
| 61 | |||
| 62 | void SevenSixAxis::ResetTimestamp() { | ||
| 63 | last_saved_timestamp = last_global_timestamp; | ||
| 64 | } | ||
| 65 | |||
| 66 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/seven_six_axis.h b/src/core/hle/service/hid/controllers/seven_six_axis.h deleted file mode 100644 index 40e3f5d12..000000000 --- a/src/core/hle/service/hid/controllers/seven_six_axis.h +++ /dev/null | |||
| @@ -1,65 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "common/quaternion.h" | ||
| 8 | #include "common/typed_address.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/ring_lifo.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } // namespace Core | ||
| 15 | |||
| 16 | namespace Core::HID { | ||
| 17 | class EmulatedConsole; | ||
| 18 | } // namespace Core::HID | ||
| 19 | |||
| 20 | namespace Service::HID { | ||
| 21 | class SevenSixAxis final : public ControllerBase { | ||
| 22 | public: | ||
| 23 | explicit SevenSixAxis(Core::System& system_); | ||
| 24 | ~SevenSixAxis() override; | ||
| 25 | |||
| 26 | // Called when the controller is initialized | ||
| 27 | void OnInit() override; | ||
| 28 | |||
| 29 | // When the controller is released | ||
| 30 | void OnRelease() override; | ||
| 31 | |||
| 32 | // When the controller is requesting an update for the shared memory | ||
| 33 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 34 | |||
| 35 | // Called on InitializeSevenSixAxisSensor | ||
| 36 | void SetTransferMemoryAddress(Common::ProcessAddress t_mem); | ||
| 37 | |||
| 38 | // Called on ResetSevenSixAxisSensorTimestamp | ||
| 39 | void ResetTimestamp(); | ||
| 40 | |||
| 41 | private: | ||
| 42 | struct SevenSixAxisState { | ||
| 43 | INSERT_PADDING_WORDS(2); // unused | ||
| 44 | u64 timestamp{}; | ||
| 45 | u64 sampling_number{}; | ||
| 46 | u64 unknown{}; | ||
| 47 | Common::Vec3f accel{}; | ||
| 48 | Common::Vec3f gyro{}; | ||
| 49 | Common::Quaternion<f32> quaternion{}; | ||
| 50 | }; | ||
| 51 | static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size"); | ||
| 52 | |||
| 53 | Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{}; | ||
| 54 | static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); | ||
| 55 | |||
| 56 | u64 last_saved_timestamp{}; | ||
| 57 | u64 last_global_timestamp{}; | ||
| 58 | |||
| 59 | SevenSixAxisState next_seven_sixaxis_state{}; | ||
| 60 | Common::ProcessAddress transfer_memory{}; | ||
| 61 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 62 | |||
| 63 | Core::System& system; | ||
| 64 | }; | ||
| 65 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.cpp b/src/core/hle/service/hid/controllers/shared_memory_holder.cpp deleted file mode 100644 index 0bc5169c6..000000000 --- a/src/core/hle/service/hid/controllers/shared_memory_holder.cpp +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 6 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 7 | #include "core/hle/service/hid/controllers/shared_memory_holder.h" | ||
| 8 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 9 | #include "core/hle/service/hid/errors.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | SharedMemoryHolder::SharedMemoryHolder() {} | ||
| 13 | |||
| 14 | SharedMemoryHolder::~SharedMemoryHolder() { | ||
| 15 | Finalize(); | ||
| 16 | } | ||
| 17 | |||
| 18 | Result SharedMemoryHolder::Initialize(Core::System& system) { | ||
| 19 | shared_memory = Kernel::KSharedMemory::Create(system.Kernel()); | ||
| 20 | const Result result = shared_memory->Initialize( | ||
| 21 | system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, | ||
| 22 | Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); | ||
| 23 | if (result.IsError()) { | ||
| 24 | return result; | ||
| 25 | } | ||
| 26 | Kernel::KSharedMemory::Register(system.Kernel(), shared_memory); | ||
| 27 | |||
| 28 | is_created = true; | ||
| 29 | is_mapped = true; | ||
| 30 | address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer())); | ||
| 31 | return ResultSuccess; | ||
| 32 | } | ||
| 33 | |||
| 34 | void SharedMemoryHolder::Finalize() { | ||
| 35 | if (address != nullptr) { | ||
| 36 | shared_memory->Close(); | ||
| 37 | } | ||
| 38 | is_created = false; | ||
| 39 | is_mapped = false; | ||
| 40 | address = nullptr; | ||
| 41 | } | ||
| 42 | |||
| 43 | bool SharedMemoryHolder::IsMapped() { | ||
| 44 | return is_mapped; | ||
| 45 | } | ||
| 46 | |||
| 47 | SharedMemoryFormat* SharedMemoryHolder::GetAddress() { | ||
| 48 | return address; | ||
| 49 | } | ||
| 50 | |||
| 51 | Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() { | ||
| 52 | return shared_memory; | ||
| 53 | } | ||
| 54 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/shared_memory_holder.h b/src/core/hle/service/hid/controllers/shared_memory_holder.h deleted file mode 100644 index 943407c00..000000000 --- a/src/core/hle/service/hid/controllers/shared_memory_holder.h +++ /dev/null | |||
| @@ -1,44 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Core { | ||
| 9 | class System; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | class KSharedMemory; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | struct SharedMemoryFormat; | ||
| 18 | |||
| 19 | // This is nn::hid::detail::SharedMemoryHolder | ||
| 20 | class SharedMemoryHolder { | ||
| 21 | public: | ||
| 22 | SharedMemoryHolder(); | ||
| 23 | ~SharedMemoryHolder(); | ||
| 24 | |||
| 25 | Result Initialize(Core::System& system); | ||
| 26 | void Finalize(); | ||
| 27 | |||
| 28 | bool IsMapped(); | ||
| 29 | SharedMemoryFormat* GetAddress(); | ||
| 30 | Kernel::KSharedMemory* GetHandle(); | ||
| 31 | |||
| 32 | private: | ||
| 33 | bool is_owner{}; | ||
| 34 | bool is_created{}; | ||
| 35 | bool is_mapped{}; | ||
| 36 | INSERT_PADDING_BYTES(0x5); | ||
| 37 | Kernel::KSharedMemory* shared_memory; | ||
| 38 | INSERT_PADDING_BYTES(0x38); | ||
| 39 | SharedMemoryFormat* address = nullptr; | ||
| 40 | }; | ||
| 41 | // Correct size is 0x50 bytes | ||
| 42 | static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size"); | ||
| 43 | |||
| 44 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/six_axis.cpp b/src/core/hle/service/hid/controllers/six_axis.cpp deleted file mode 100644 index adab60911..000000000 --- a/src/core/hle/service/hid/controllers/six_axis.cpp +++ /dev/null | |||
| @@ -1,421 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "common/common_types.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 9 | #include "core/hle/service/hid/controllers/six_axis.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 11 | #include "core/hle/service/hid/errors.h" | ||
| 12 | #include "core/hle/service/hid/hid_util.h" | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | |||
| 16 | SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_) | ||
| 17 | : ControllerBase{hid_core_}, npad{npad_} { | ||
| 18 | for (std::size_t i = 0; i < controller_data.size(); ++i) { | ||
| 19 | auto& controller = controller_data[i]; | ||
| 20 | controller.device = hid_core.GetEmulatedControllerByIndex(i); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | SixAxis::~SixAxis() = default; | ||
| 25 | |||
| 26 | void SixAxis::OnInit() {} | ||
| 27 | void SixAxis::OnRelease() {} | ||
| 28 | |||
| 29 | void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 30 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 31 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 32 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 33 | |||
| 34 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 38 | if (!IsControllerActivated()) { | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | |||
| 42 | for (std::size_t i = 0; i < controller_data.size(); ++i) { | ||
| 43 | NpadSharedMemoryEntry& shared_memory = data->shared_memory_format->npad.npad_entry[i]; | ||
| 44 | auto& controller = controller_data[i]; | ||
| 45 | const auto& controller_type = controller.device->GetNpadStyleIndex(); | ||
| 46 | |||
| 47 | if (controller_type == Core::HID::NpadStyleIndex::None || | ||
| 48 | !controller.device->IsConnected()) { | ||
| 49 | continue; | ||
| 50 | } | ||
| 51 | |||
| 52 | const auto& motion_state = controller.device->GetMotions(); | ||
| 53 | auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; | ||
| 54 | auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; | ||
| 55 | auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state; | ||
| 56 | auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state; | ||
| 57 | auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; | ||
| 58 | auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; | ||
| 59 | |||
| 60 | auto& sixaxis_fullkey_lifo = shared_memory.internal_state.sixaxis_fullkey_lifo; | ||
| 61 | auto& sixaxis_handheld_lifo = shared_memory.internal_state.sixaxis_handheld_lifo; | ||
| 62 | auto& sixaxis_dual_left_lifo = shared_memory.internal_state.sixaxis_dual_left_lifo; | ||
| 63 | auto& sixaxis_dual_right_lifo = shared_memory.internal_state.sixaxis_dual_right_lifo; | ||
| 64 | auto& sixaxis_left_lifo = shared_memory.internal_state.sixaxis_left_lifo; | ||
| 65 | auto& sixaxis_right_lifo = shared_memory.internal_state.sixaxis_right_lifo; | ||
| 66 | |||
| 67 | // Clear previous state | ||
| 68 | sixaxis_fullkey_state = {}; | ||
| 69 | sixaxis_handheld_state = {}; | ||
| 70 | sixaxis_dual_left_state = {}; | ||
| 71 | sixaxis_dual_right_state = {}; | ||
| 72 | sixaxis_left_lifo_state = {}; | ||
| 73 | sixaxis_right_lifo_state = {}; | ||
| 74 | |||
| 75 | if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) { | ||
| 76 | controller.sixaxis_at_rest = true; | ||
| 77 | for (std::size_t e = 0; e < motion_state.size(); ++e) { | ||
| 78 | controller.sixaxis_at_rest = | ||
| 79 | controller.sixaxis_at_rest && motion_state[e].is_at_rest; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state, | ||
| 84 | const Core::HID::ControllerMotion& hid_state) { | ||
| 85 | using namespace std::literals::chrono_literals; | ||
| 86 | static constexpr Core::HID::SixAxisSensorState default_motion_state = { | ||
| 87 | .delta_time = std::chrono::nanoseconds(5ms).count(), | ||
| 88 | .accel = {0, 0, -1.0f}, | ||
| 89 | .orientation = | ||
| 90 | { | ||
| 91 | Common::Vec3f{1.0f, 0, 0}, | ||
| 92 | Common::Vec3f{0, 1.0f, 0}, | ||
| 93 | Common::Vec3f{0, 0, 1.0f}, | ||
| 94 | }, | ||
| 95 | .attribute = {1}, | ||
| 96 | }; | ||
| 97 | if (!controller.sixaxis_sensor_enabled) { | ||
| 98 | state = default_motion_state; | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | if (!Settings::values.motion_enabled.GetValue()) { | ||
| 102 | state = default_motion_state; | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | state.attribute.is_connected.Assign(1); | ||
| 106 | state.delta_time = std::chrono::nanoseconds(5ms).count(); | ||
| 107 | state.accel = hid_state.accel; | ||
| 108 | state.gyro = hid_state.gyro; | ||
| 109 | state.rotation = hid_state.rotation; | ||
| 110 | state.orientation = hid_state.orientation; | ||
| 111 | }; | ||
| 112 | |||
| 113 | switch (controller_type) { | ||
| 114 | case Core::HID::NpadStyleIndex::None: | ||
| 115 | ASSERT(false); | ||
| 116 | break; | ||
| 117 | case Core::HID::NpadStyleIndex::ProController: | ||
| 118 | set_motion_state(sixaxis_fullkey_state, motion_state[0]); | ||
| 119 | break; | ||
| 120 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 121 | set_motion_state(sixaxis_handheld_state, motion_state[0]); | ||
| 122 | break; | ||
| 123 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 124 | set_motion_state(sixaxis_dual_left_state, motion_state[0]); | ||
| 125 | set_motion_state(sixaxis_dual_right_state, motion_state[1]); | ||
| 126 | break; | ||
| 127 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 128 | set_motion_state(sixaxis_left_lifo_state, motion_state[0]); | ||
| 129 | break; | ||
| 130 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 131 | set_motion_state(sixaxis_right_lifo_state, motion_state[1]); | ||
| 132 | break; | ||
| 133 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 134 | using namespace std::literals::chrono_literals; | ||
| 135 | set_motion_state(sixaxis_fullkey_state, motion_state[0]); | ||
| 136 | sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count(); | ||
| 137 | break; | ||
| 138 | default: | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | sixaxis_fullkey_state.sampling_number = | ||
| 143 | sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 144 | sixaxis_handheld_state.sampling_number = | ||
| 145 | sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 146 | sixaxis_dual_left_state.sampling_number = | ||
| 147 | sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 148 | sixaxis_dual_right_state.sampling_number = | ||
| 149 | sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 150 | sixaxis_left_lifo_state.sampling_number = | ||
| 151 | sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 152 | sixaxis_right_lifo_state.sampling_number = | ||
| 153 | sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; | ||
| 154 | |||
| 155 | if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { | ||
| 156 | // This buffer only is updated on handheld on HW | ||
| 157 | sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state); | ||
| 158 | } else { | ||
| 159 | // Handheld doesn't update this buffer on HW | ||
| 160 | sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state); | ||
| 161 | } | ||
| 162 | |||
| 163 | sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state); | ||
| 164 | sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state); | ||
| 165 | sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state); | ||
| 166 | sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 171 | Core::HID::GyroscopeZeroDriftMode drift_mode) { | ||
| 172 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 173 | if (is_valid.IsError()) { | ||
| 174 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 175 | return is_valid; | ||
| 176 | } | ||
| 177 | |||
| 178 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 179 | auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 180 | sixaxis.gyroscope_zero_drift_mode = drift_mode; | ||
| 181 | controller.device->SetGyroscopeZeroDriftMode(drift_mode); | ||
| 182 | |||
| 183 | return ResultSuccess; | ||
| 184 | } | ||
| 185 | |||
| 186 | Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 187 | Core::HID::GyroscopeZeroDriftMode& drift_mode) const { | ||
| 188 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 189 | if (is_valid.IsError()) { | ||
| 190 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 191 | return is_valid; | ||
| 192 | } | ||
| 193 | |||
| 194 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 195 | drift_mode = sixaxis.gyroscope_zero_drift_mode; | ||
| 196 | |||
| 197 | return ResultSuccess; | ||
| 198 | } | ||
| 199 | |||
| 200 | Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 201 | bool& is_at_rest) const { | ||
| 202 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 203 | if (is_valid.IsError()) { | ||
| 204 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 205 | return is_valid; | ||
| 206 | } | ||
| 207 | |||
| 208 | const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 209 | is_at_rest = controller.sixaxis_at_rest; | ||
| 210 | return ResultSuccess; | ||
| 211 | } | ||
| 212 | |||
| 213 | Result SixAxis::LoadSixAxisSensorCalibrationParameter( | ||
| 214 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 215 | Core::HID::SixAxisSensorCalibrationParameter& calibration) const { | ||
| 216 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 217 | if (is_valid.IsError()) { | ||
| 218 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 219 | return is_valid; | ||
| 220 | } | ||
| 221 | |||
| 222 | // TODO: Request this data to the controller. On error return 0xd8ca | ||
| 223 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 224 | calibration = sixaxis.calibration; | ||
| 225 | return ResultSuccess; | ||
| 226 | } | ||
| 227 | |||
| 228 | Result SixAxis::GetSixAxisSensorIcInformation( | ||
| 229 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 230 | Core::HID::SixAxisSensorIcInformation& ic_information) const { | ||
| 231 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 232 | if (is_valid.IsError()) { | ||
| 233 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 234 | return is_valid; | ||
| 235 | } | ||
| 236 | |||
| 237 | // TODO: Request this data to the controller. On error return 0xd8ca | ||
| 238 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 239 | ic_information = sixaxis.ic_information; | ||
| 240 | return ResultSuccess; | ||
| 241 | } | ||
| 242 | |||
| 243 | Result SixAxis::EnableSixAxisSensorUnalteredPassthrough( | ||
| 244 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) { | ||
| 245 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 246 | if (is_valid.IsError()) { | ||
| 247 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 248 | return is_valid; | ||
| 249 | } | ||
| 250 | |||
| 251 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 252 | sixaxis.unaltered_passtrough = is_enabled; | ||
| 253 | return ResultSuccess; | ||
| 254 | } | ||
| 255 | |||
| 256 | Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled( | ||
| 257 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const { | ||
| 258 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 259 | if (is_valid.IsError()) { | ||
| 260 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 261 | return is_valid; | ||
| 262 | } | ||
| 263 | |||
| 264 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 265 | is_enabled = sixaxis.unaltered_passtrough; | ||
| 266 | return ResultSuccess; | ||
| 267 | } | ||
| 268 | |||
| 269 | Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 270 | bool sixaxis_status) { | ||
| 271 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 272 | if (is_valid.IsError()) { | ||
| 273 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 274 | return is_valid; | ||
| 275 | } | ||
| 276 | |||
| 277 | auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 278 | controller.sixaxis_sensor_enabled = sixaxis_status; | ||
| 279 | return ResultSuccess; | ||
| 280 | } | ||
| 281 | |||
| 282 | Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 283 | bool& is_fusion_enabled) const { | ||
| 284 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 285 | if (is_valid.IsError()) { | ||
| 286 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 287 | return is_valid; | ||
| 288 | } | ||
| 289 | |||
| 290 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 291 | is_fusion_enabled = sixaxis.is_fusion_enabled; | ||
| 292 | |||
| 293 | return ResultSuccess; | ||
| 294 | } | ||
| 295 | Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 296 | bool is_fusion_enabled) { | ||
| 297 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 298 | if (is_valid.IsError()) { | ||
| 299 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 300 | return is_valid; | ||
| 301 | } | ||
| 302 | |||
| 303 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 304 | sixaxis.is_fusion_enabled = is_fusion_enabled; | ||
| 305 | |||
| 306 | return ResultSuccess; | ||
| 307 | } | ||
| 308 | |||
| 309 | Result SixAxis::SetSixAxisFusionParameters( | ||
| 310 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 311 | Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { | ||
| 312 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 313 | if (is_valid.IsError()) { | ||
| 314 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 315 | return is_valid; | ||
| 316 | } | ||
| 317 | |||
| 318 | const auto param1 = sixaxis_fusion_parameters.parameter1; | ||
| 319 | if (param1 < 0.0f || param1 > 1.0f) { | ||
| 320 | return InvalidSixAxisFusionRange; | ||
| 321 | } | ||
| 322 | |||
| 323 | auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 324 | sixaxis.fusion = sixaxis_fusion_parameters; | ||
| 325 | |||
| 326 | return ResultSuccess; | ||
| 327 | } | ||
| 328 | |||
| 329 | Result SixAxis::GetSixAxisFusionParameters( | ||
| 330 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 331 | Core::HID::SixAxisSensorFusionParameters& parameters) const { | ||
| 332 | const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); | ||
| 333 | if (is_valid.IsError()) { | ||
| 334 | LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); | ||
| 335 | return is_valid; | ||
| 336 | } | ||
| 337 | |||
| 338 | const auto& sixaxis = GetSixaxisState(sixaxis_handle); | ||
| 339 | parameters = sixaxis.fusion; | ||
| 340 | |||
| 341 | return ResultSuccess; | ||
| 342 | } | ||
| 343 | |||
| 344 | SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( | ||
| 345 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) { | ||
| 346 | auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 347 | switch (sixaxis_handle.npad_type) { | ||
| 348 | case Core::HID::NpadStyleIndex::ProController: | ||
| 349 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 350 | return controller.sixaxis_fullkey; | ||
| 351 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 352 | return controller.sixaxis_handheld; | ||
| 353 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 354 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 355 | return controller.sixaxis_dual_left; | ||
| 356 | } | ||
| 357 | return controller.sixaxis_dual_right; | ||
| 358 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 359 | return controller.sixaxis_left; | ||
| 360 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 361 | return controller.sixaxis_right; | ||
| 362 | default: | ||
| 363 | return controller.sixaxis_unknown; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( | ||
| 368 | const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { | ||
| 369 | const auto& controller = GetControllerFromHandle(sixaxis_handle); | ||
| 370 | switch (sixaxis_handle.npad_type) { | ||
| 371 | case Core::HID::NpadStyleIndex::ProController: | ||
| 372 | case Core::HID::NpadStyleIndex::Pokeball: | ||
| 373 | return controller.sixaxis_fullkey; | ||
| 374 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 375 | return controller.sixaxis_handheld; | ||
| 376 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 377 | if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { | ||
| 378 | return controller.sixaxis_dual_left; | ||
| 379 | } | ||
| 380 | return controller.sixaxis_dual_right; | ||
| 381 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 382 | return controller.sixaxis_left; | ||
| 383 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 384 | return controller.sixaxis_right; | ||
| 385 | default: | ||
| 386 | return controller.sixaxis_unknown; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( | ||
| 391 | const Core::HID::SixAxisSensorHandle& device_handle) { | ||
| 392 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 393 | return GetControllerFromNpadIdType(npad_id); | ||
| 394 | } | ||
| 395 | |||
| 396 | const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( | ||
| 397 | const Core::HID::SixAxisSensorHandle& device_handle) const { | ||
| 398 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 399 | return GetControllerFromNpadIdType(npad_id); | ||
| 400 | } | ||
| 401 | |||
| 402 | SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) { | ||
| 403 | if (!IsNpadIdValid(npad_id)) { | ||
| 404 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 405 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 406 | } | ||
| 407 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 408 | return controller_data[npad_index]; | ||
| 409 | } | ||
| 410 | |||
| 411 | const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType( | ||
| 412 | Core::HID::NpadIdType npad_id) const { | ||
| 413 | if (!IsNpadIdValid(npad_id)) { | ||
| 414 | LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); | ||
| 415 | npad_id = Core::HID::NpadIdType::Player1; | ||
| 416 | } | ||
| 417 | const auto npad_index = NpadIdTypeToIndex(npad_id); | ||
| 418 | return controller_data[npad_index]; | ||
| 419 | } | ||
| 420 | |||
| 421 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/six_axis.h b/src/core/hle/service/hid/controllers/six_axis.h deleted file mode 100644 index 4c4f5dc7b..000000000 --- a/src/core/hle/service/hid/controllers/six_axis.h +++ /dev/null | |||
| @@ -1,111 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 9 | #include "core/hle/service/hid/ring_lifo.h" | ||
| 10 | |||
| 11 | namespace Core::HID { | ||
| 12 | class EmulatedController; | ||
| 13 | } // namespace Core::HID | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | class NPad; | ||
| 17 | |||
| 18 | class SixAxis final : public ControllerBase { | ||
| 19 | public: | ||
| 20 | explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_); | ||
| 21 | ~SixAxis() override; | ||
| 22 | |||
| 23 | // Called when the controller is initialized | ||
| 24 | void OnInit() override; | ||
| 25 | |||
| 26 | // When the controller is released | ||
| 27 | void OnRelease() override; | ||
| 28 | |||
| 29 | // When the controller is requesting an update for the shared memory | ||
| 30 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 31 | |||
| 32 | Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 33 | Core::HID::GyroscopeZeroDriftMode drift_mode); | ||
| 34 | Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 35 | Core::HID::GyroscopeZeroDriftMode& drift_mode) const; | ||
| 36 | Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 37 | bool& is_at_rest) const; | ||
| 38 | Result EnableSixAxisSensorUnalteredPassthrough( | ||
| 39 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled); | ||
| 40 | Result IsSixAxisSensorUnalteredPassthroughEnabled( | ||
| 41 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const; | ||
| 42 | Result LoadSixAxisSensorCalibrationParameter( | ||
| 43 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 44 | Core::HID::SixAxisSensorCalibrationParameter& calibration) const; | ||
| 45 | Result GetSixAxisSensorIcInformation( | ||
| 46 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 47 | Core::HID::SixAxisSensorIcInformation& ic_information) const; | ||
| 48 | Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 49 | bool sixaxis_status); | ||
| 50 | Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 51 | bool& is_fusion_enabled) const; | ||
| 52 | Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 53 | bool is_fusion_enabled); | ||
| 54 | Result SetSixAxisFusionParameters( | ||
| 55 | const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 56 | Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); | ||
| 57 | Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle, | ||
| 58 | Core::HID::SixAxisSensorFusionParameters& parameters) const; | ||
| 59 | |||
| 60 | private: | ||
| 61 | static constexpr std::size_t NPAD_COUNT = 10; | ||
| 62 | |||
| 63 | struct SixaxisParameters { | ||
| 64 | bool is_fusion_enabled{true}; | ||
| 65 | bool unaltered_passtrough{false}; | ||
| 66 | Core::HID::SixAxisSensorFusionParameters fusion{}; | ||
| 67 | Core::HID::SixAxisSensorCalibrationParameter calibration{}; | ||
| 68 | Core::HID::SixAxisSensorIcInformation ic_information{}; | ||
| 69 | Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{ | ||
| 70 | Core::HID::GyroscopeZeroDriftMode::Standard}; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct NpadControllerData { | ||
| 74 | Core::HID::EmulatedController* device = nullptr; | ||
| 75 | |||
| 76 | // Motion parameters | ||
| 77 | bool sixaxis_at_rest{true}; | ||
| 78 | bool sixaxis_sensor_enabled{true}; | ||
| 79 | SixaxisParameters sixaxis_fullkey{}; | ||
| 80 | SixaxisParameters sixaxis_handheld{}; | ||
| 81 | SixaxisParameters sixaxis_dual_left{}; | ||
| 82 | SixaxisParameters sixaxis_dual_right{}; | ||
| 83 | SixaxisParameters sixaxis_left{}; | ||
| 84 | SixaxisParameters sixaxis_right{}; | ||
| 85 | SixaxisParameters sixaxis_unknown{}; | ||
| 86 | |||
| 87 | // Current pad state | ||
| 88 | Core::HID::SixAxisSensorState sixaxis_fullkey_state{}; | ||
| 89 | Core::HID::SixAxisSensorState sixaxis_handheld_state{}; | ||
| 90 | Core::HID::SixAxisSensorState sixaxis_dual_left_state{}; | ||
| 91 | Core::HID::SixAxisSensorState sixaxis_dual_right_state{}; | ||
| 92 | Core::HID::SixAxisSensorState sixaxis_left_lifo_state{}; | ||
| 93 | Core::HID::SixAxisSensorState sixaxis_right_lifo_state{}; | ||
| 94 | int callback_key{}; | ||
| 95 | }; | ||
| 96 | |||
| 97 | SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 98 | const SixaxisParameters& GetSixaxisState( | ||
| 99 | const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 100 | |||
| 101 | NpadControllerData& GetControllerFromHandle( | ||
| 102 | const Core::HID::SixAxisSensorHandle& device_handle); | ||
| 103 | const NpadControllerData& GetControllerFromHandle( | ||
| 104 | const Core::HID::SixAxisSensorHandle& device_handle) const; | ||
| 105 | NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); | ||
| 106 | const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; | ||
| 107 | |||
| 108 | std::shared_ptr<NPad> npad; | ||
| 109 | std::array<NpadControllerData, NPAD_COUNT> controller_data{}; | ||
| 110 | }; | ||
| 111 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/sleep_button.cpp b/src/core/hle/service/hid/controllers/sleep_button.cpp deleted file mode 100644 index d44b1f4cc..000000000 --- a/src/core/hle/service/hid/controllers/sleep_button.cpp +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/sleep_button.h" | ||
| 7 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | SleepButton::SleepButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | SleepButton::~SleepButton() = default; | ||
| 14 | |||
| 15 | void SleepButton::OnInit() {} | ||
| 16 | |||
| 17 | void SleepButton::OnRelease() {} | ||
| 18 | |||
| 19 | void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | std::scoped_lock shared_lock{*shared_mutex}; | ||
| 25 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 26 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 27 | |||
| 28 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | auto& header = data->shared_memory_format->capture_button.header; | ||
| 33 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 34 | header.total_entry_count = 17; | ||
| 35 | header.entry_count = 0; | ||
| 36 | header.last_entry_index = 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/sleep_button.h b/src/core/hle/service/hid/controllers/sleep_button.h deleted file mode 100644 index 59964bf63..000000000 --- a/src/core/hle/service/hid/controllers/sleep_button.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class SleepButton final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit SleepButton(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~SleepButton() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp deleted file mode 100644 index b585a5829..000000000 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ /dev/null | |||
| @@ -1,132 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "common/settings.h" | ||
| 7 | #include "core/core_timing.h" | ||
| 8 | #include "core/frontend/emu_window.h" | ||
| 9 | #include "core/hid/emulated_console.h" | ||
| 10 | #include "core/hid/hid_core.h" | ||
| 11 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 12 | #include "core/hle/service/hid/controllers/touchscreen.h" | ||
| 13 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | |||
| 17 | TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_) | ||
| 18 | : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width), | ||
| 19 | touchscreen_height(Layout::ScreenUndocked::Height) { | ||
| 20 | console = hid_core.GetEmulatedConsole(); | ||
| 21 | } | ||
| 22 | |||
| 23 | TouchScreen::~TouchScreen() = default; | ||
| 24 | |||
| 25 | void TouchScreen::OnInit() {} | ||
| 26 | |||
| 27 | void TouchScreen::OnRelease() {} | ||
| 28 | |||
| 29 | void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 30 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 31 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 32 | |||
| 33 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | |||
| 37 | TouchScreenSharedMemoryFormat& shared_memory = data->shared_memory_format->touch_screen; | ||
| 38 | shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 39 | |||
| 40 | if (!IsControllerActivated()) { | ||
| 41 | shared_memory.touch_screen_lifo.buffer_count = 0; | ||
| 42 | shared_memory.touch_screen_lifo.buffer_tail = 0; | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | const auto touch_status = console->GetTouch(); | ||
| 47 | for (std::size_t id = 0; id < MAX_FINGERS; id++) { | ||
| 48 | const auto& current_touch = touch_status[id]; | ||
| 49 | auto& finger = fingers[id]; | ||
| 50 | finger.id = current_touch.id; | ||
| 51 | |||
| 52 | if (finger.attribute.start_touch) { | ||
| 53 | finger.attribute.raw = 0; | ||
| 54 | continue; | ||
| 55 | } | ||
| 56 | |||
| 57 | if (finger.attribute.end_touch) { | ||
| 58 | finger.attribute.raw = 0; | ||
| 59 | finger.pressed = false; | ||
| 60 | continue; | ||
| 61 | } | ||
| 62 | |||
| 63 | if (!finger.pressed && current_touch.pressed) { | ||
| 64 | // Ignore all touch fingers if disabled | ||
| 65 | if (!Settings::values.touchscreen.enabled) { | ||
| 66 | continue; | ||
| 67 | } | ||
| 68 | |||
| 69 | finger.attribute.start_touch.Assign(1); | ||
| 70 | finger.pressed = true; | ||
| 71 | finger.position = current_touch.position; | ||
| 72 | continue; | ||
| 73 | } | ||
| 74 | |||
| 75 | if (finger.pressed && !current_touch.pressed) { | ||
| 76 | finger.attribute.raw = 0; | ||
| 77 | finger.attribute.end_touch.Assign(1); | ||
| 78 | continue; | ||
| 79 | } | ||
| 80 | |||
| 81 | // Only update position if touch is not on a special frame | ||
| 82 | finger.position = current_touch.position; | ||
| 83 | } | ||
| 84 | |||
| 85 | std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers; | ||
| 86 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | ||
| 87 | [](const auto& finger) { return finger.pressed; }); | ||
| 88 | const auto active_fingers_count = | ||
| 89 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); | ||
| 90 | |||
| 91 | const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count()); | ||
| 92 | const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state; | ||
| 93 | |||
| 94 | next_state.sampling_number = last_entry.sampling_number + 1; | ||
| 95 | next_state.entry_count = static_cast<s32>(active_fingers_count); | ||
| 96 | |||
| 97 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { | ||
| 98 | auto& touch_entry = next_state.states[id]; | ||
| 99 | if (id < active_fingers_count) { | ||
| 100 | const auto& [active_x, active_y] = active_fingers[id].position; | ||
| 101 | touch_entry.position = { | ||
| 102 | .x = static_cast<u16>(active_x * static_cast<float>(touchscreen_width)), | ||
| 103 | .y = static_cast<u16>(active_y * static_cast<float>(touchscreen_height)), | ||
| 104 | }; | ||
| 105 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; | ||
| 106 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | ||
| 107 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | ||
| 108 | touch_entry.delta_time = timestamp - active_fingers[id].last_touch; | ||
| 109 | fingers[active_fingers[id].id].last_touch = timestamp; | ||
| 110 | touch_entry.finger = active_fingers[id].id; | ||
| 111 | touch_entry.attribute.raw = active_fingers[id].attribute.raw; | ||
| 112 | } else { | ||
| 113 | // Clear touch entry | ||
| 114 | touch_entry.attribute.raw = 0; | ||
| 115 | touch_entry.position = {}; | ||
| 116 | touch_entry.diameter_x = 0; | ||
| 117 | touch_entry.diameter_y = 0; | ||
| 118 | touch_entry.rotation_angle = 0; | ||
| 119 | touch_entry.delta_time = 0; | ||
| 120 | touch_entry.finger = 0; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | shared_memory.touch_screen_lifo.WriteNextEntry(next_state); | ||
| 125 | } | ||
| 126 | |||
| 127 | void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) { | ||
| 128 | touchscreen_width = width; | ||
| 129 | touchscreen_height = height; | ||
| 130 | } | ||
| 131 | |||
| 132 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h deleted file mode 100644 index 945d359be..000000000 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ /dev/null | |||
| @@ -1,43 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 10 | #include "core/hle/service/hid/controllers/types/touch_types.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class EmulatedConsole; | ||
| 14 | } // namespace Core::HID | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | struct TouchScreenSharedMemoryFormat; | ||
| 18 | |||
| 19 | class TouchScreen final : public ControllerBase { | ||
| 20 | public: | ||
| 21 | explicit TouchScreen(Core::HID::HIDCore& hid_core_); | ||
| 22 | ~TouchScreen() override; | ||
| 23 | |||
| 24 | // Called when the controller is initialized | ||
| 25 | void OnInit() override; | ||
| 26 | |||
| 27 | // When the controller is released | ||
| 28 | void OnRelease() override; | ||
| 29 | |||
| 30 | // When the controller is requesting an update for the shared memory | ||
| 31 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 32 | |||
| 33 | void SetTouchscreenDimensions(u32 width, u32 height); | ||
| 34 | |||
| 35 | private: | ||
| 36 | TouchScreenState next_state{}; | ||
| 37 | Core::HID::EmulatedConsole* console = nullptr; | ||
| 38 | |||
| 39 | std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{}; | ||
| 40 | u32 touchscreen_width; | ||
| 41 | u32 touchscreen_height; | ||
| 42 | }; | ||
| 43 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/debug_pad_types.h b/src/core/hle/service/hid/controllers/types/debug_pad_types.h deleted file mode 100644 index a96171b62..000000000 --- a/src/core/hle/service/hid/controllers/types/debug_pad_types.h +++ /dev/null | |||
| @@ -1,31 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | // This is nn::hid::DebugPadAttribute | ||
| 13 | struct DebugPadAttribute { | ||
| 14 | union { | ||
| 15 | u32 raw{}; | ||
| 16 | BitField<0, 1, u32> connected; | ||
| 17 | }; | ||
| 18 | }; | ||
| 19 | static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size"); | ||
| 20 | |||
| 21 | // This is nn::hid::DebugPadState | ||
| 22 | struct DebugPadState { | ||
| 23 | s64 sampling_number{}; | ||
| 24 | DebugPadAttribute attribute{}; | ||
| 25 | Core::HID::DebugPadButton pad_state{}; | ||
| 26 | Core::HID::AnalogStickState r_stick{}; | ||
| 27 | Core::HID::AnalogStickState l_stick{}; | ||
| 28 | }; | ||
| 29 | static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); | ||
| 30 | |||
| 31 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/gesture_types.h b/src/core/hle/service/hid/controllers/types/gesture_types.h deleted file mode 100644 index b4f034cd3..000000000 --- a/src/core/hle/service/hid/controllers/types/gesture_types.h +++ /dev/null | |||
| @@ -1,77 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include "common/bit_field.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "common/point.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | static constexpr size_t MAX_FINGERS = 16; | ||
| 13 | static constexpr size_t MAX_POINTS = 4; | ||
| 14 | |||
| 15 | // This is nn::hid::GestureType | ||
| 16 | enum class GestureType : u32 { | ||
| 17 | Idle, // Nothing touching the screen | ||
| 18 | Complete, // Set at the end of a touch event | ||
| 19 | Cancel, // Set when the number of fingers change | ||
| 20 | Touch, // A finger just touched the screen | ||
| 21 | Press, // Set if last type is touch and the finger hasn't moved | ||
| 22 | Tap, // Fast press then release | ||
| 23 | Pan, // All points moving together across the screen | ||
| 24 | Swipe, // Fast press movement and release of a single point | ||
| 25 | Pinch, // All points moving away/closer to the midpoint | ||
| 26 | Rotate, // All points rotating from the midpoint | ||
| 27 | }; | ||
| 28 | |||
| 29 | // This is nn::hid::GestureDirection | ||
| 30 | enum class GestureDirection : u32 { | ||
| 31 | None, | ||
| 32 | Left, | ||
| 33 | Up, | ||
| 34 | Right, | ||
| 35 | Down, | ||
| 36 | }; | ||
| 37 | |||
| 38 | // This is nn::hid::GestureAttribute | ||
| 39 | struct GestureAttribute { | ||
| 40 | union { | ||
| 41 | u32 raw{}; | ||
| 42 | |||
| 43 | BitField<4, 1, u32> is_new_touch; | ||
| 44 | BitField<8, 1, u32> is_double_tap; | ||
| 45 | }; | ||
| 46 | }; | ||
| 47 | static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); | ||
| 48 | |||
| 49 | // This is nn::hid::GestureState | ||
| 50 | struct GestureState { | ||
| 51 | s64 sampling_number{}; | ||
| 52 | s64 detection_count{}; | ||
| 53 | GestureType type{GestureType::Idle}; | ||
| 54 | GestureDirection direction{GestureDirection::None}; | ||
| 55 | Common::Point<s32> pos{}; | ||
| 56 | Common::Point<s32> delta{}; | ||
| 57 | f32 vel_x{}; | ||
| 58 | f32 vel_y{}; | ||
| 59 | GestureAttribute attributes{}; | ||
| 60 | f32 scale{}; | ||
| 61 | f32 rotation_angle{}; | ||
| 62 | s32 point_count{}; | ||
| 63 | std::array<Common::Point<s32>, 4> points{}; | ||
| 64 | }; | ||
| 65 | static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); | ||
| 66 | |||
| 67 | struct GestureProperties { | ||
| 68 | std::array<Common::Point<s32>, MAX_POINTS> points{}; | ||
| 69 | std::size_t active_points{}; | ||
| 70 | Common::Point<s32> mid_point{}; | ||
| 71 | s64 detection_count{}; | ||
| 72 | u64 delta_time{}; | ||
| 73 | f32 average_distance{}; | ||
| 74 | f32 angle{}; | ||
| 75 | }; | ||
| 76 | |||
| 77 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/keyboard_types.h b/src/core/hle/service/hid/controllers/types/keyboard_types.h deleted file mode 100644 index f44a536b9..000000000 --- a/src/core/hle/service/hid/controllers/types/keyboard_types.h +++ /dev/null | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | // This is nn::hid::detail::KeyboardState | ||
| 12 | struct KeyboardState { | ||
| 13 | s64 sampling_number{}; | ||
| 14 | Core::HID::KeyboardModifier modifier{}; | ||
| 15 | Core::HID::KeyboardAttribute attribute{}; | ||
| 16 | Core::HID::KeyboardKey key{}; | ||
| 17 | }; | ||
| 18 | static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); | ||
| 19 | |||
| 20 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/mouse_types.h b/src/core/hle/service/hid/controllers/types/mouse_types.h deleted file mode 100644 index 8bd6e167c..000000000 --- a/src/core/hle/service/hid/controllers/types/mouse_types.h +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | |||
| 8 | namespace Service::HID {} // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/npad_types.h b/src/core/hle/service/hid/controllers/types/npad_types.h deleted file mode 100644 index 419c33a8c..000000000 --- a/src/core/hle/service/hid/controllers/types/npad_types.h +++ /dev/null | |||
| @@ -1,255 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_funcs.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hid/hid_types.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | static constexpr std::size_t MaxSupportedNpadIdTypes = 10; | ||
| 13 | static constexpr std::size_t StyleIndexCount = 7; | ||
| 14 | |||
| 15 | // This is nn::hid::NpadJoyHoldType | ||
| 16 | enum class NpadJoyHoldType : u64 { | ||
| 17 | Vertical = 0, | ||
| 18 | Horizontal = 1, | ||
| 19 | }; | ||
| 20 | |||
| 21 | // This is nn::hid::NpadJoyAssignmentMode | ||
| 22 | enum class NpadJoyAssignmentMode : u32 { | ||
| 23 | Dual = 0, | ||
| 24 | Single = 1, | ||
| 25 | }; | ||
| 26 | |||
| 27 | // This is nn::hid::NpadJoyDeviceType | ||
| 28 | enum class NpadJoyDeviceType : s64 { | ||
| 29 | Left = 0, | ||
| 30 | Right = 1, | ||
| 31 | }; | ||
| 32 | |||
| 33 | // This is nn::hid::NpadHandheldActivationMode | ||
| 34 | enum class NpadHandheldActivationMode : u64 { | ||
| 35 | Dual = 0, | ||
| 36 | Single = 1, | ||
| 37 | None = 2, | ||
| 38 | MaxActivationMode = 3, | ||
| 39 | }; | ||
| 40 | |||
| 41 | // This is nn::hid::system::AppletFooterUiAttributesSet | ||
| 42 | struct AppletFooterUiAttributes { | ||
| 43 | INSERT_PADDING_BYTES(0x4); | ||
| 44 | }; | ||
| 45 | |||
| 46 | // This is nn::hid::system::AppletFooterUiType | ||
| 47 | enum class AppletFooterUiType : u8 { | ||
| 48 | None = 0, | ||
| 49 | HandheldNone = 1, | ||
| 50 | HandheldJoyConLeftOnly = 2, | ||
| 51 | HandheldJoyConRightOnly = 3, | ||
| 52 | HandheldJoyConLeftJoyConRight = 4, | ||
| 53 | JoyDual = 5, | ||
| 54 | JoyDualLeftOnly = 6, | ||
| 55 | JoyDualRightOnly = 7, | ||
| 56 | JoyLeftHorizontal = 8, | ||
| 57 | JoyLeftVertical = 9, | ||
| 58 | JoyRightHorizontal = 10, | ||
| 59 | JoyRightVertical = 11, | ||
| 60 | SwitchProController = 12, | ||
| 61 | CompatibleProController = 13, | ||
| 62 | CompatibleJoyCon = 14, | ||
| 63 | LarkHvc1 = 15, | ||
| 64 | LarkHvc2 = 16, | ||
| 65 | LarkNesLeft = 17, | ||
| 66 | LarkNesRight = 18, | ||
| 67 | Lucia = 19, | ||
| 68 | Verification = 20, | ||
| 69 | Lagon = 21, | ||
| 70 | }; | ||
| 71 | |||
| 72 | using AppletFooterUiVariant = u8; | ||
| 73 | |||
| 74 | // This is "nn::hid::system::AppletDetailedUiType". | ||
| 75 | struct AppletDetailedUiType { | ||
| 76 | AppletFooterUiVariant ui_variant; | ||
| 77 | INSERT_PADDING_BYTES(0x2); | ||
| 78 | AppletFooterUiType footer; | ||
| 79 | }; | ||
| 80 | static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); | ||
| 81 | // This is nn::hid::NpadCommunicationMode | ||
| 82 | enum class NpadCommunicationMode : u64 { | ||
| 83 | Mode_5ms = 0, | ||
| 84 | Mode_10ms = 1, | ||
| 85 | Mode_15ms = 2, | ||
| 86 | Default = 3, | ||
| 87 | }; | ||
| 88 | |||
| 89 | enum class NpadRevision : u32 { | ||
| 90 | Revision0 = 0, | ||
| 91 | Revision1 = 1, | ||
| 92 | Revision2 = 2, | ||
| 93 | Revision3 = 3, | ||
| 94 | }; | ||
| 95 | |||
| 96 | // This is nn::hid::detail::ColorAttribute | ||
| 97 | enum class ColorAttribute : u32 { | ||
| 98 | Ok = 0, | ||
| 99 | ReadError = 1, | ||
| 100 | NoController = 2, | ||
| 101 | }; | ||
| 102 | static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); | ||
| 103 | |||
| 104 | // This is nn::hid::detail::NpadFullKeyColorState | ||
| 105 | struct NpadFullKeyColorState { | ||
| 106 | ColorAttribute attribute{ColorAttribute::NoController}; | ||
| 107 | Core::HID::NpadControllerColor fullkey{}; | ||
| 108 | }; | ||
| 109 | static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size"); | ||
| 110 | |||
| 111 | // This is nn::hid::detail::NpadJoyColorState | ||
| 112 | struct NpadJoyColorState { | ||
| 113 | ColorAttribute attribute{ColorAttribute::NoController}; | ||
| 114 | Core::HID::NpadControllerColor left{}; | ||
| 115 | Core::HID::NpadControllerColor right{}; | ||
| 116 | }; | ||
| 117 | static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size"); | ||
| 118 | |||
| 119 | // This is nn::hid::NpadAttribute | ||
| 120 | struct NpadAttribute { | ||
| 121 | union { | ||
| 122 | u32 raw{}; | ||
| 123 | BitField<0, 1, u32> is_connected; | ||
| 124 | BitField<1, 1, u32> is_wired; | ||
| 125 | BitField<2, 1, u32> is_left_connected; | ||
| 126 | BitField<3, 1, u32> is_left_wired; | ||
| 127 | BitField<4, 1, u32> is_right_connected; | ||
| 128 | BitField<5, 1, u32> is_right_wired; | ||
| 129 | }; | ||
| 130 | }; | ||
| 131 | static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size"); | ||
| 132 | |||
| 133 | // This is nn::hid::NpadFullKeyState | ||
| 134 | // This is nn::hid::NpadHandheldState | ||
| 135 | // This is nn::hid::NpadJoyDualState | ||
| 136 | // This is nn::hid::NpadJoyLeftState | ||
| 137 | // This is nn::hid::NpadJoyRightState | ||
| 138 | // This is nn::hid::NpadPalmaState | ||
| 139 | // This is nn::hid::NpadSystemExtState | ||
| 140 | struct NPadGenericState { | ||
| 141 | s64_le sampling_number{}; | ||
| 142 | Core::HID::NpadButtonState npad_buttons{}; | ||
| 143 | Core::HID::AnalogStickState l_stick{}; | ||
| 144 | Core::HID::AnalogStickState r_stick{}; | ||
| 145 | NpadAttribute connection_status{}; | ||
| 146 | INSERT_PADDING_BYTES(4); // Reserved | ||
| 147 | }; | ||
| 148 | static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); | ||
| 149 | |||
| 150 | // This is nn::hid::server::NpadGcTriggerState | ||
| 151 | struct NpadGcTriggerState { | ||
| 152 | s64 sampling_number{}; | ||
| 153 | s32 l_analog{}; | ||
| 154 | s32 r_analog{}; | ||
| 155 | }; | ||
| 156 | static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); | ||
| 157 | |||
| 158 | // This is nn::hid::NpadSystemProperties | ||
| 159 | struct NPadSystemProperties { | ||
| 160 | union { | ||
| 161 | s64 raw{}; | ||
| 162 | BitField<0, 1, s64> is_charging_joy_dual; | ||
| 163 | BitField<1, 1, s64> is_charging_joy_left; | ||
| 164 | BitField<2, 1, s64> is_charging_joy_right; | ||
| 165 | BitField<3, 1, s64> is_powered_joy_dual; | ||
| 166 | BitField<4, 1, s64> is_powered_joy_left; | ||
| 167 | BitField<5, 1, s64> is_powered_joy_right; | ||
| 168 | BitField<9, 1, s64> is_system_unsupported_button; | ||
| 169 | BitField<10, 1, s64> is_system_ext_unsupported_button; | ||
| 170 | BitField<11, 1, s64> is_vertical; | ||
| 171 | BitField<12, 1, s64> is_horizontal; | ||
| 172 | BitField<13, 1, s64> use_plus; | ||
| 173 | BitField<14, 1, s64> use_minus; | ||
| 174 | BitField<15, 1, s64> use_directional_buttons; | ||
| 175 | }; | ||
| 176 | }; | ||
| 177 | static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); | ||
| 178 | |||
| 179 | // This is nn::hid::NpadSystemButtonProperties | ||
| 180 | struct NpadSystemButtonProperties { | ||
| 181 | union { | ||
| 182 | s32 raw{}; | ||
| 183 | BitField<0, 1, s32> is_home_button_protection_enabled; | ||
| 184 | }; | ||
| 185 | }; | ||
| 186 | static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size"); | ||
| 187 | |||
| 188 | // This is nn::hid::system::DeviceType | ||
| 189 | struct DeviceType { | ||
| 190 | union { | ||
| 191 | u32 raw{}; | ||
| 192 | BitField<0, 1, s32> fullkey; | ||
| 193 | BitField<1, 1, s32> debug_pad; | ||
| 194 | BitField<2, 1, s32> handheld_left; | ||
| 195 | BitField<3, 1, s32> handheld_right; | ||
| 196 | BitField<4, 1, s32> joycon_left; | ||
| 197 | BitField<5, 1, s32> joycon_right; | ||
| 198 | BitField<6, 1, s32> palma; | ||
| 199 | BitField<7, 1, s32> lark_hvc_left; | ||
| 200 | BitField<8, 1, s32> lark_hvc_right; | ||
| 201 | BitField<9, 1, s32> lark_nes_left; | ||
| 202 | BitField<10, 1, s32> lark_nes_right; | ||
| 203 | BitField<11, 1, s32> handheld_lark_hvc_left; | ||
| 204 | BitField<12, 1, s32> handheld_lark_hvc_right; | ||
| 205 | BitField<13, 1, s32> handheld_lark_nes_left; | ||
| 206 | BitField<14, 1, s32> handheld_lark_nes_right; | ||
| 207 | BitField<15, 1, s32> lucia; | ||
| 208 | BitField<16, 1, s32> lagon; | ||
| 209 | BitField<17, 1, s32> lager; | ||
| 210 | BitField<31, 1, s32> system; | ||
| 211 | }; | ||
| 212 | }; | ||
| 213 | |||
| 214 | // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl | ||
| 215 | struct NfcXcdDeviceHandleStateImpl { | ||
| 216 | u64 handle{}; | ||
| 217 | bool is_available{}; | ||
| 218 | bool is_activated{}; | ||
| 219 | INSERT_PADDING_BYTES(0x6); // Reserved | ||
| 220 | u64 sampling_number{}; | ||
| 221 | }; | ||
| 222 | static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, | ||
| 223 | "NfcXcdDeviceHandleStateImpl is an invalid size"); | ||
| 224 | |||
| 225 | // This is nn::hid::NpadLarkType | ||
| 226 | enum class NpadLarkType : u32 { | ||
| 227 | Invalid, | ||
| 228 | H1, | ||
| 229 | H2, | ||
| 230 | NL, | ||
| 231 | NR, | ||
| 232 | }; | ||
| 233 | |||
| 234 | // This is nn::hid::NpadLuciaType | ||
| 235 | enum class NpadLuciaType : u32 { | ||
| 236 | Invalid, | ||
| 237 | J, | ||
| 238 | E, | ||
| 239 | U, | ||
| 240 | }; | ||
| 241 | |||
| 242 | // This is nn::hid::NpadLagonType | ||
| 243 | enum class NpadLagonType : u32 { | ||
| 244 | Invalid, | ||
| 245 | }; | ||
| 246 | |||
| 247 | // This is nn::hid::NpadLagerType | ||
| 248 | enum class NpadLagerType : u32 { | ||
| 249 | Invalid, | ||
| 250 | J, | ||
| 251 | E, | ||
| 252 | U, | ||
| 253 | }; | ||
| 254 | |||
| 255 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/shared_memory_format.h b/src/core/hle/service/hid/controllers/types/shared_memory_format.h deleted file mode 100644 index 976043b9c..000000000 --- a/src/core/hle/service/hid/controllers/types/shared_memory_format.h +++ /dev/null | |||
| @@ -1,240 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_funcs.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/vector_math.h" | ||
| 9 | #include "core/hid/hid_types.h" | ||
| 10 | #include "core/hle/service/hid//controllers/types/debug_pad_types.h" | ||
| 11 | #include "core/hle/service/hid//controllers/types/keyboard_types.h" | ||
| 12 | #include "core/hle/service/hid//controllers/types/mouse_types.h" | ||
| 13 | #include "core/hle/service/hid//controllers/types/npad_types.h" | ||
| 14 | #include "core/hle/service/hid//controllers/types/touch_types.h" | ||
| 15 | #include "core/hle/service/hid/ring_lifo.h" | ||
| 16 | |||
| 17 | namespace Service::HID { | ||
| 18 | static const std::size_t HidEntryCount = 17; | ||
| 19 | |||
| 20 | struct CommonHeader { | ||
| 21 | s64 timestamp{}; | ||
| 22 | s64 total_entry_count{}; | ||
| 23 | s64 last_entry_index{}; | ||
| 24 | s64 entry_count{}; | ||
| 25 | }; | ||
| 26 | static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); | ||
| 27 | |||
| 28 | // This is nn::hid::detail::DebugPadSharedMemoryFormat | ||
| 29 | struct DebugPadSharedMemoryFormat { | ||
| 30 | // This is nn::hid::detail::DebugPadLifo | ||
| 31 | Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{}; | ||
| 32 | static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); | ||
| 33 | INSERT_PADDING_WORDS(0x4E); | ||
| 34 | }; | ||
| 35 | static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400, | ||
| 36 | "DebugPadSharedMemoryFormat is an invalid size"); | ||
| 37 | |||
| 38 | // This is nn::hid::detail::TouchScreenSharedMemoryFormat | ||
| 39 | struct TouchScreenSharedMemoryFormat { | ||
| 40 | // This is nn::hid::detail::TouchScreenLifo | ||
| 41 | Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{}; | ||
| 42 | static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); | ||
| 43 | INSERT_PADDING_WORDS(0xF2); | ||
| 44 | }; | ||
| 45 | static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000, | ||
| 46 | "TouchScreenSharedMemoryFormat is an invalid size"); | ||
| 47 | |||
| 48 | // This is nn::hid::detail::MouseSharedMemoryFormat | ||
| 49 | struct MouseSharedMemoryFormat { | ||
| 50 | // This is nn::hid::detail::MouseLifo | ||
| 51 | Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{}; | ||
| 52 | static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); | ||
| 53 | INSERT_PADDING_WORDS(0x2C); | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(MouseSharedMemoryFormat) == 0x400, | ||
| 56 | "MouseSharedMemoryFormat is an invalid size"); | ||
| 57 | |||
| 58 | // This is nn::hid::detail::KeyboardSharedMemoryFormat | ||
| 59 | struct KeyboardSharedMemoryFormat { | ||
| 60 | // This is nn::hid::detail::KeyboardLifo | ||
| 61 | Lifo<KeyboardState, HidEntryCount> keyboard_lifo{}; | ||
| 62 | static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); | ||
| 63 | INSERT_PADDING_WORDS(0xA); | ||
| 64 | }; | ||
| 65 | static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400, | ||
| 66 | "KeyboardSharedMemoryFormat is an invalid size"); | ||
| 67 | |||
| 68 | // This is nn::hid::detail::DigitizerSharedMemoryFormat | ||
| 69 | struct DigitizerSharedMemoryFormat { | ||
| 70 | CommonHeader header; | ||
| 71 | INSERT_PADDING_BYTES(0xFE0); | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000, | ||
| 74 | "DigitizerSharedMemoryFormat is an invalid size"); | ||
| 75 | |||
| 76 | // This is nn::hid::detail::HomeButtonSharedMemoryFormat | ||
| 77 | struct HomeButtonSharedMemoryFormat { | ||
| 78 | CommonHeader header; | ||
| 79 | INSERT_PADDING_BYTES(0x1E0); | ||
| 80 | }; | ||
| 81 | static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, | ||
| 82 | "HomeButtonSharedMemoryFormat is an invalid size"); | ||
| 83 | |||
| 84 | // This is nn::hid::detail::SleepButtonSharedMemoryFormat | ||
| 85 | struct SleepButtonSharedMemoryFormat { | ||
| 86 | CommonHeader header; | ||
| 87 | INSERT_PADDING_BYTES(0x1E0); | ||
| 88 | }; | ||
| 89 | static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, | ||
| 90 | "SleepButtonSharedMemoryFormat is an invalid size"); | ||
| 91 | |||
| 92 | // This is nn::hid::detail::CaptureButtonSharedMemoryFormat | ||
| 93 | struct CaptureButtonSharedMemoryFormat { | ||
| 94 | CommonHeader header; | ||
| 95 | INSERT_PADDING_BYTES(0x1E0); | ||
| 96 | }; | ||
| 97 | static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, | ||
| 98 | "CaptureButtonSharedMemoryFormat is an invalid size"); | ||
| 99 | |||
| 100 | // This is nn::hid::detail::InputDetectorSharedMemoryFormat | ||
| 101 | struct InputDetectorSharedMemoryFormat { | ||
| 102 | CommonHeader header; | ||
| 103 | INSERT_PADDING_BYTES(0x7E0); | ||
| 104 | }; | ||
| 105 | static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800, | ||
| 106 | "InputDetectorSharedMemoryFormat is an invalid size"); | ||
| 107 | |||
| 108 | // This is nn::hid::detail::UniquePadSharedMemoryFormat | ||
| 109 | struct UniquePadSharedMemoryFormat { | ||
| 110 | CommonHeader header; | ||
| 111 | INSERT_PADDING_BYTES(0x3FE0); | ||
| 112 | }; | ||
| 113 | static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000, | ||
| 114 | "UniquePadSharedMemoryFormat is an invalid size"); | ||
| 115 | |||
| 116 | // This is nn::hid::detail::NpadSixAxisSensorLifo | ||
| 117 | struct NpadSixAxisSensorLifo { | ||
| 118 | Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo; | ||
| 119 | }; | ||
| 120 | |||
| 121 | // This is nn::hid::detail::NpadInternalState | ||
| 122 | struct NpadInternalState { | ||
| 123 | Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; | ||
| 124 | NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual}; | ||
| 125 | NpadFullKeyColorState fullkey_color{}; | ||
| 126 | NpadJoyColorState joycon_color{}; | ||
| 127 | Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{}; | ||
| 128 | Lifo<NPadGenericState, HidEntryCount> handheld_lifo{}; | ||
| 129 | Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{}; | ||
| 130 | Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{}; | ||
| 131 | Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{}; | ||
| 132 | Lifo<NPadGenericState, HidEntryCount> palma_lifo{}; | ||
| 133 | Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{}; | ||
| 134 | NpadSixAxisSensorLifo sixaxis_fullkey_lifo{}; | ||
| 135 | NpadSixAxisSensorLifo sixaxis_handheld_lifo{}; | ||
| 136 | NpadSixAxisSensorLifo sixaxis_dual_left_lifo{}; | ||
| 137 | NpadSixAxisSensorLifo sixaxis_dual_right_lifo{}; | ||
| 138 | NpadSixAxisSensorLifo sixaxis_left_lifo{}; | ||
| 139 | NpadSixAxisSensorLifo sixaxis_right_lifo{}; | ||
| 140 | DeviceType device_type{}; | ||
| 141 | INSERT_PADDING_BYTES(0x4); // Reserved | ||
| 142 | NPadSystemProperties system_properties{}; | ||
| 143 | NpadSystemButtonProperties button_properties{}; | ||
| 144 | Core::HID::NpadBatteryLevel battery_level_dual{}; | ||
| 145 | Core::HID::NpadBatteryLevel battery_level_left{}; | ||
| 146 | Core::HID::NpadBatteryLevel battery_level_right{}; | ||
| 147 | AppletFooterUiAttributes applet_footer_attributes{}; | ||
| 148 | AppletFooterUiType applet_footer_type{AppletFooterUiType::None}; | ||
| 149 | INSERT_PADDING_BYTES(0x5B); // Reserved | ||
| 150 | INSERT_PADDING_BYTES(0x20); // Unknown | ||
| 151 | Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{}; | ||
| 152 | NpadLarkType lark_type_l_and_main{}; | ||
| 153 | NpadLarkType lark_type_r{}; | ||
| 154 | NpadLuciaType lucia_type{}; | ||
| 155 | NpadLagerType lager_type{}; | ||
| 156 | Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties; | ||
| 157 | Core::HID::SixAxisSensorProperties sixaxis_handheld_properties; | ||
| 158 | Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties; | ||
| 159 | Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties; | ||
| 160 | Core::HID::SixAxisSensorProperties sixaxis_left_properties; | ||
| 161 | Core::HID::SixAxisSensorProperties sixaxis_right_properties; | ||
| 162 | }; | ||
| 163 | static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size"); | ||
| 164 | |||
| 165 | // This is nn::hid::detail::NpadSharedMemoryEntry | ||
| 166 | struct NpadSharedMemoryEntry { | ||
| 167 | NpadInternalState internal_state; | ||
| 168 | INSERT_PADDING_BYTES(0xC08); | ||
| 169 | }; | ||
| 170 | static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size"); | ||
| 171 | |||
| 172 | // This is nn::hid::detail::NpadSharedMemoryFormat | ||
| 173 | struct NpadSharedMemoryFormat { | ||
| 174 | std::array<NpadSharedMemoryEntry, MaxSupportedNpadIdTypes> npad_entry; | ||
| 175 | }; | ||
| 176 | static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000, | ||
| 177 | "NpadSharedMemoryFormat is an invalid size"); | ||
| 178 | |||
| 179 | // This is nn::hid::detail::GestureSharedMemoryFormat | ||
| 180 | struct GestureSharedMemoryFormat { | ||
| 181 | // This is nn::hid::detail::GestureLifo | ||
| 182 | Lifo<GestureState, HidEntryCount> gesture_lifo{}; | ||
| 183 | static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); | ||
| 184 | INSERT_PADDING_WORDS(0x3E); | ||
| 185 | }; | ||
| 186 | static_assert(sizeof(GestureSharedMemoryFormat) == 0x800, | ||
| 187 | "GestureSharedMemoryFormat is an invalid size"); | ||
| 188 | |||
| 189 | // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat | ||
| 190 | struct ConsoleSixAxisSensorSharedMemoryFormat { | ||
| 191 | u64 sampling_number{}; | ||
| 192 | bool is_seven_six_axis_sensor_at_rest{}; | ||
| 193 | INSERT_PADDING_BYTES(3); // padding | ||
| 194 | f32 verticalization_error{}; | ||
| 195 | Common::Vec3f gyro_bias{}; | ||
| 196 | INSERT_PADDING_BYTES(4); // padding | ||
| 197 | }; | ||
| 198 | static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20, | ||
| 199 | "ConsoleSixAxisSensorSharedMemoryFormat is an invalid size"); | ||
| 200 | |||
| 201 | // This is nn::hid::detail::SharedMemoryFormat | ||
| 202 | struct SharedMemoryFormat { | ||
| 203 | void Initialize() {} | ||
| 204 | |||
| 205 | DebugPadSharedMemoryFormat debug_pad; | ||
| 206 | TouchScreenSharedMemoryFormat touch_screen; | ||
| 207 | MouseSharedMemoryFormat mouse; | ||
| 208 | KeyboardSharedMemoryFormat keyboard; | ||
| 209 | DigitizerSharedMemoryFormat digitizer; | ||
| 210 | HomeButtonSharedMemoryFormat home_button; | ||
| 211 | SleepButtonSharedMemoryFormat sleep_button; | ||
| 212 | CaptureButtonSharedMemoryFormat capture_button; | ||
| 213 | InputDetectorSharedMemoryFormat input_detector; | ||
| 214 | UniquePadSharedMemoryFormat unique_pad; | ||
| 215 | NpadSharedMemoryFormat npad; | ||
| 216 | GestureSharedMemoryFormat gesture; | ||
| 217 | ConsoleSixAxisSensorSharedMemoryFormat console; | ||
| 218 | INSERT_PADDING_BYTES(0x19E0); | ||
| 219 | MouseSharedMemoryFormat debug_mouse; | ||
| 220 | INSERT_PADDING_BYTES(0x2000); | ||
| 221 | }; | ||
| 222 | static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset"); | ||
| 223 | static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset"); | ||
| 224 | static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset"); | ||
| 225 | static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset"); | ||
| 226 | static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset"); | ||
| 227 | static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset"); | ||
| 228 | static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00, | ||
| 229 | "sleep_button has wrong offset"); | ||
| 230 | static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000, | ||
| 231 | "capture_button has wrong offset"); | ||
| 232 | static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200, | ||
| 233 | "input_detector has wrong offset"); | ||
| 234 | static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset"); | ||
| 235 | static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset"); | ||
| 236 | static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset"); | ||
| 237 | static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset"); | ||
| 238 | static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size"); | ||
| 239 | |||
| 240 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/types/touch_types.h b/src/core/hle/service/hid/controllers/types/touch_types.h deleted file mode 100644 index efeaa796d..000000000 --- a/src/core/hle/service/hid/controllers/types/touch_types.h +++ /dev/null | |||
| @@ -1,90 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include <array> | ||
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "common/point.h" | ||
| 13 | #include "core/hid/hid_types.h" | ||
| 14 | |||
| 15 | namespace Service::HID { | ||
| 16 | static constexpr std::size_t MAX_FINGERS = 16; | ||
| 17 | static constexpr size_t MAX_POINTS = 4; | ||
| 18 | |||
| 19 | // This is nn::hid::GestureType | ||
| 20 | enum class GestureType : u32 { | ||
| 21 | Idle, // Nothing touching the screen | ||
| 22 | Complete, // Set at the end of a touch event | ||
| 23 | Cancel, // Set when the number of fingers change | ||
| 24 | Touch, // A finger just touched the screen | ||
| 25 | Press, // Set if last type is touch and the finger hasn't moved | ||
| 26 | Tap, // Fast press then release | ||
| 27 | Pan, // All points moving together across the screen | ||
| 28 | Swipe, // Fast press movement and release of a single point | ||
| 29 | Pinch, // All points moving away/closer to the midpoint | ||
| 30 | Rotate, // All points rotating from the midpoint | ||
| 31 | }; | ||
| 32 | |||
| 33 | // This is nn::hid::GestureDirection | ||
| 34 | enum class GestureDirection : u32 { | ||
| 35 | None, | ||
| 36 | Left, | ||
| 37 | Up, | ||
| 38 | Right, | ||
| 39 | Down, | ||
| 40 | }; | ||
| 41 | |||
| 42 | // This is nn::hid::GestureAttribute | ||
| 43 | struct GestureAttribute { | ||
| 44 | union { | ||
| 45 | u32 raw{}; | ||
| 46 | |||
| 47 | BitField<4, 1, u32> is_new_touch; | ||
| 48 | BitField<8, 1, u32> is_double_tap; | ||
| 49 | }; | ||
| 50 | }; | ||
| 51 | static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); | ||
| 52 | |||
| 53 | // This is nn::hid::GestureState | ||
| 54 | struct GestureState { | ||
| 55 | s64 sampling_number{}; | ||
| 56 | s64 detection_count{}; | ||
| 57 | GestureType type{GestureType::Idle}; | ||
| 58 | GestureDirection direction{GestureDirection::None}; | ||
| 59 | Common::Point<s32> pos{}; | ||
| 60 | Common::Point<s32> delta{}; | ||
| 61 | f32 vel_x{}; | ||
| 62 | f32 vel_y{}; | ||
| 63 | GestureAttribute attributes{}; | ||
| 64 | f32 scale{}; | ||
| 65 | f32 rotation_angle{}; | ||
| 66 | s32 point_count{}; | ||
| 67 | std::array<Common::Point<s32>, 4> points{}; | ||
| 68 | }; | ||
| 69 | static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); | ||
| 70 | |||
| 71 | struct GestureProperties { | ||
| 72 | std::array<Common::Point<s32>, MAX_POINTS> points{}; | ||
| 73 | std::size_t active_points{}; | ||
| 74 | Common::Point<s32> mid_point{}; | ||
| 75 | s64 detection_count{}; | ||
| 76 | u64 delta_time{}; | ||
| 77 | f32 average_distance{}; | ||
| 78 | f32 angle{}; | ||
| 79 | }; | ||
| 80 | |||
| 81 | // This is nn::hid::TouchScreenState | ||
| 82 | struct TouchScreenState { | ||
| 83 | s64 sampling_number{}; | ||
| 84 | s32 entry_count{}; | ||
| 85 | INSERT_PADDING_BYTES(4); // Reserved | ||
| 86 | std::array<Core::HID::TouchState, MAX_FINGERS> states{}; | ||
| 87 | }; | ||
| 88 | static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); | ||
| 89 | |||
| 90 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/unique_pad.cpp b/src/core/hle/service/hid/controllers/unique_pad.cpp deleted file mode 100644 index 6c543031d..000000000 --- a/src/core/hle/service/hid/controllers/unique_pad.cpp +++ /dev/null | |||
| @@ -1,38 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core_timing.h" | ||
| 5 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 6 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 7 | #include "core/hle/service/hid/controllers/unique_pad.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | UniquePad::UniquePad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} | ||
| 12 | |||
| 13 | UniquePad::~UniquePad() = default; | ||
| 14 | |||
| 15 | void UniquePad::OnInit() {} | ||
| 16 | |||
| 17 | void UniquePad::OnRelease() {} | ||
| 18 | |||
| 19 | void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | ||
| 20 | if (!smart_update) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | |||
| 24 | const u64 aruid = applet_resource->GetActiveAruid(); | ||
| 25 | auto* data = applet_resource->GetAruidData(aruid); | ||
| 26 | |||
| 27 | if (data == nullptr || !data->flag.is_assigned) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | auto& header = data->shared_memory_format->capture_button.header; | ||
| 32 | header.timestamp = core_timing.GetGlobalTimeNs().count(); | ||
| 33 | header.total_entry_count = 17; | ||
| 34 | header.entry_count = 0; | ||
| 35 | header.last_entry_index = 0; | ||
| 36 | } | ||
| 37 | |||
| 38 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/controllers/unique_pad.h b/src/core/hle/service/hid/controllers/unique_pad.h deleted file mode 100644 index 966368264..000000000 --- a/src/core/hle/service/hid/controllers/unique_pad.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/hid/controllers/controller_base.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | class UniquePad final : public ControllerBase { | ||
| 11 | public: | ||
| 12 | explicit UniquePad(Core::HID::HIDCore& hid_core_); | ||
| 13 | ~UniquePad() override; | ||
| 14 | |||
| 15 | // Called when the controller is initialized | ||
| 16 | void OnInit() override; | ||
| 17 | |||
| 18 | // When the controller is released | ||
| 19 | void OnRelease() override; | ||
| 20 | |||
| 21 | // When the controller is requesting an update for the shared memory | ||
| 22 | void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; | ||
| 23 | |||
| 24 | private: | ||
| 25 | bool smart_update{}; | ||
| 26 | }; | ||
| 27 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h deleted file mode 100644 index bb14aa61e..000000000 --- a/src/core/hle/service/hid/errors.h +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/result.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | constexpr Result PalmaResultSuccess{ErrorModule::HID, 0}; | ||
| 11 | constexpr Result NpadInvalidHandle{ErrorModule::HID, 100}; | ||
| 12 | constexpr Result NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; | ||
| 13 | |||
| 14 | constexpr Result ResultVibrationNotInitialized{ErrorModule::HID, 121}; | ||
| 15 | constexpr Result ResultVibrationInvalidStyleIndex{ErrorModule::HID, 122}; | ||
| 16 | constexpr Result ResultVibrationInvalidNpadId{ErrorModule::HID, 123}; | ||
| 17 | constexpr Result ResultVibrationDeviceIndexOutOfRange{ErrorModule::HID, 124}; | ||
| 18 | constexpr Result ResultVibrationStrenghtOutOfRange{ErrorModule::HID, 126}; | ||
| 19 | constexpr Result ResultVibrationArraySizeMismatch{ErrorModule::HID, 131}; | ||
| 20 | |||
| 21 | constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423}; | ||
| 22 | |||
| 23 | constexpr Result ResultNfcIsNotReady{ErrorModule::HID, 461}; | ||
| 24 | constexpr Result ResultNfcXcdHandleIsNotInitialized{ErrorModule::HID, 464}; | ||
| 25 | constexpr Result ResultIrSensorIsNotReady{ErrorModule::HID, 501}; | ||
| 26 | constexpr Result ResultMcuIsNotReady{ErrorModule::HID, 541}; | ||
| 27 | |||
| 28 | constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601}; | ||
| 29 | constexpr Result NpadIsSameType{ErrorModule::HID, 602}; | ||
| 30 | constexpr Result ResultNpadIsNotProController{ErrorModule::HID, 604}; | ||
| 31 | |||
| 32 | constexpr Result ResultInvalidNpadId{ErrorModule::HID, 709}; | ||
| 33 | constexpr Result ResultNpadNotConnected{ErrorModule::HID, 710}; | ||
| 34 | constexpr Result ResultNpadHandlerOverflow{ErrorModule::HID, 711}; | ||
| 35 | constexpr Result ResultNpadHandlerNotInitialized{ErrorModule::HID, 712}; | ||
| 36 | constexpr Result ResultInvalidArraySize{ErrorModule::HID, 715}; | ||
| 37 | constexpr Result ResultUndefinedStyleset{ErrorModule::HID, 716}; | ||
| 38 | constexpr Result ResultMultipleStyleSetSelected{ErrorModule::HID, 717}; | ||
| 39 | |||
| 40 | constexpr Result ResultAppletResourceOverflow{ErrorModule::HID, 1041}; | ||
| 41 | constexpr Result ResultAppletResourceNotInitialized{ErrorModule::HID, 1042}; | ||
| 42 | constexpr Result ResultSharedMemoryNotInitialized{ErrorModule::HID, 1043}; | ||
| 43 | constexpr Result ResultAruidNoAvailableEntries{ErrorModule::HID, 1044}; | ||
| 44 | constexpr Result ResultAruidAlreadyRegistered{ErrorModule::HID, 1046}; | ||
| 45 | constexpr Result ResultAruidNotRegistered{ErrorModule::HID, 1047}; | ||
| 46 | |||
| 47 | constexpr Result ResultNpadResourceOverflow{ErrorModule::HID, 2001}; | ||
| 48 | constexpr Result ResultNpadResourceNotInitialized{ErrorModule::HID, 2002}; | ||
| 49 | |||
| 50 | constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302}; | ||
| 51 | |||
| 52 | } // namespace Service::HID | ||
| 53 | |||
| 54 | namespace Service::IRS { | ||
| 55 | |||
| 56 | constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78}; | ||
| 57 | constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204}; | ||
| 58 | |||
| 59 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index bd2873181..fc8a3ab66 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -5,14 +5,14 @@ | |||
| 5 | #include "core/hle/kernel/kernel.h" | 5 | #include "core/hle/kernel/kernel.h" |
| 6 | #include "core/hle/service/hid/hid.h" | 6 | #include "core/hle/service/hid/hid.h" |
| 7 | #include "core/hle/service/hid/hid_debug_server.h" | 7 | #include "core/hle/service/hid/hid_debug_server.h" |
| 8 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 9 | #include "core/hle/service/hid/hid_server.h" | 8 | #include "core/hle/service/hid/hid_server.h" |
| 10 | #include "core/hle/service/hid/hid_system_server.h" | 9 | #include "core/hle/service/hid/hid_system_server.h" |
| 11 | #include "core/hle/service/hid/hidbus.h" | 10 | #include "core/hle/service/hid/hidbus.h" |
| 12 | #include "core/hle/service/hid/irs.h" | 11 | #include "core/hle/service/hid/irs.h" |
| 13 | #include "core/hle/service/hid/resource_manager.h" | ||
| 14 | #include "core/hle/service/hid/xcd.h" | 12 | #include "core/hle/service/hid/xcd.h" |
| 15 | #include "core/hle/service/server_manager.h" | 13 | #include "core/hle/service/server_manager.h" |
| 14 | #include "hid_core/resource_manager.h" | ||
| 15 | #include "hid_core/resources/hid_firmware_settings.h" | ||
| 16 | 16 | ||
| 17 | namespace Service::HID { | 17 | namespace Service::HID { |
| 18 | 18 | ||
diff --git a/src/core/hle/service/hid/hid_debug_server.cpp b/src/core/hle/service/hid/hid_debug_server.cpp index 6294f3dfb..f2a767d37 100644 --- a/src/core/hle/service/hid/hid_debug_server.cpp +++ b/src/core/hle/service/hid/hid_debug_server.cpp | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hle/service/hid/hid_debug_server.h" | 4 | #include "core/hle/service/hid/hid_debug_server.h" |
| 5 | #include "core/hle/service/hid/resource_manager.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | 5 | #include "core/hle/service/ipc_helpers.h" |
| 6 | #include "hid_core/resource_manager.h" | ||
| 7 | 7 | ||
| 8 | namespace Service::HID { | 8 | namespace Service::HID { |
| 9 | 9 | ||
diff --git a/src/core/hle/service/hid/hid_firmware_settings.cpp b/src/core/hle/service/hid/hid_firmware_settings.cpp deleted file mode 100644 index 59bd6825c..000000000 --- a/src/core/hle/service/hid/hid_firmware_settings.cpp +++ /dev/null | |||
| @@ -1,99 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | |||
| 8 | HidFirmwareSettings::HidFirmwareSettings() { | ||
| 9 | LoadSettings(true); | ||
| 10 | } | ||
| 11 | |||
| 12 | void HidFirmwareSettings::Reload() { | ||
| 13 | LoadSettings(true); | ||
| 14 | } | ||
| 15 | |||
| 16 | void HidFirmwareSettings::LoadSettings(bool reload_config) { | ||
| 17 | if (is_initalized && !reload_config) { | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | |||
| 21 | // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values | ||
| 22 | |||
| 23 | is_debug_pad_enabled = true; | ||
| 24 | is_device_managed = true; | ||
| 25 | is_touch_i2c_managed = is_device_managed; | ||
| 26 | is_future_devices_emulated = false; | ||
| 27 | is_mcu_hardware_error_emulated = false; | ||
| 28 | is_rail_enabled = true; | ||
| 29 | is_firmware_update_failure_emulated = false; | ||
| 30 | is_firmware_update_failure = {}; | ||
| 31 | is_ble_disabled = false; | ||
| 32 | is_dscale_disabled = false; | ||
| 33 | is_handheld_forced = true; | ||
| 34 | features_per_id_disabled = {}; | ||
| 35 | is_touch_firmware_auto_update_disabled = false; | ||
| 36 | is_initalized = true; | ||
| 37 | } | ||
| 38 | |||
| 39 | bool HidFirmwareSettings::IsDebugPadEnabled() { | ||
| 40 | LoadSettings(false); | ||
| 41 | return is_debug_pad_enabled; | ||
| 42 | } | ||
| 43 | |||
| 44 | bool HidFirmwareSettings::IsDeviceManaged() { | ||
| 45 | LoadSettings(false); | ||
| 46 | return is_device_managed; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool HidFirmwareSettings::IsEmulateFutureDevice() { | ||
| 50 | LoadSettings(false); | ||
| 51 | return is_future_devices_emulated; | ||
| 52 | } | ||
| 53 | |||
| 54 | bool HidFirmwareSettings::IsTouchI2cManaged() { | ||
| 55 | LoadSettings(false); | ||
| 56 | return is_touch_i2c_managed; | ||
| 57 | } | ||
| 58 | |||
| 59 | bool HidFirmwareSettings::IsHandheldForced() { | ||
| 60 | LoadSettings(false); | ||
| 61 | return is_handheld_forced; | ||
| 62 | } | ||
| 63 | |||
| 64 | bool HidFirmwareSettings::IsRailEnabled() { | ||
| 65 | LoadSettings(false); | ||
| 66 | return is_rail_enabled; | ||
| 67 | } | ||
| 68 | |||
| 69 | bool HidFirmwareSettings::IsHardwareErrorEmulated() { | ||
| 70 | LoadSettings(false); | ||
| 71 | return is_mcu_hardware_error_emulated; | ||
| 72 | } | ||
| 73 | |||
| 74 | bool HidFirmwareSettings::IsBleDisabled() { | ||
| 75 | LoadSettings(false); | ||
| 76 | return is_ble_disabled; | ||
| 77 | } | ||
| 78 | |||
| 79 | bool HidFirmwareSettings::IsDscaleDisabled() { | ||
| 80 | LoadSettings(false); | ||
| 81 | return is_dscale_disabled; | ||
| 82 | } | ||
| 83 | |||
| 84 | bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() { | ||
| 85 | LoadSettings(false); | ||
| 86 | return is_touch_firmware_auto_update_disabled; | ||
| 87 | } | ||
| 88 | |||
| 89 | HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() { | ||
| 90 | LoadSettings(false); | ||
| 91 | return is_firmware_update_failure; | ||
| 92 | } | ||
| 93 | |||
| 94 | HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() { | ||
| 95 | LoadSettings(false); | ||
| 96 | return features_per_id_disabled; | ||
| 97 | } | ||
| 98 | |||
| 99 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hid_firmware_settings.h b/src/core/hle/service/hid/hid_firmware_settings.h deleted file mode 100644 index 6c10c440b..000000000 --- a/src/core/hle/service/hid/hid_firmware_settings.h +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | |||
| 10 | /// Loads firmware config from nn::settings::fwdbg | ||
| 11 | class HidFirmwareSettings { | ||
| 12 | public: | ||
| 13 | using FirmwareSetting = std::array<u8, 4>; | ||
| 14 | using FeaturesPerId = std::array<bool, 0xA8>; | ||
| 15 | |||
| 16 | HidFirmwareSettings(); | ||
| 17 | |||
| 18 | void Reload(); | ||
| 19 | void LoadSettings(bool reload_config); | ||
| 20 | |||
| 21 | bool IsDebugPadEnabled(); | ||
| 22 | bool IsDeviceManaged(); | ||
| 23 | bool IsEmulateFutureDevice(); | ||
| 24 | bool IsTouchI2cManaged(); | ||
| 25 | bool IsHandheldForced(); | ||
| 26 | bool IsRailEnabled(); | ||
| 27 | bool IsHardwareErrorEmulated(); | ||
| 28 | bool IsBleDisabled(); | ||
| 29 | bool IsDscaleDisabled(); | ||
| 30 | bool IsTouchAutoUpdateDisabled(); | ||
| 31 | |||
| 32 | FirmwareSetting GetFirmwareUpdateFailure(); | ||
| 33 | FeaturesPerId FeaturesDisabledPerId(); | ||
| 34 | |||
| 35 | private: | ||
| 36 | bool is_initalized{}; | ||
| 37 | |||
| 38 | // Debug settings | ||
| 39 | bool is_debug_pad_enabled{}; | ||
| 40 | bool is_device_managed{}; | ||
| 41 | bool is_touch_i2c_managed{}; | ||
| 42 | bool is_future_devices_emulated{}; | ||
| 43 | bool is_mcu_hardware_error_emulated{}; | ||
| 44 | bool is_rail_enabled{}; | ||
| 45 | bool is_firmware_update_failure_emulated{}; | ||
| 46 | bool is_ble_disabled{}; | ||
| 47 | bool is_dscale_disabled{}; | ||
| 48 | bool is_handheld_forced{}; | ||
| 49 | bool is_touch_firmware_auto_update_disabled{}; | ||
| 50 | FirmwareSetting is_firmware_update_failure{}; | ||
| 51 | FeaturesPerId features_per_id_disabled{}; | ||
| 52 | }; | ||
| 53 | |||
| 54 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index a953c92b3..2ff00d30d 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -5,30 +5,29 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "core/hid/hid_core.h" | ||
| 9 | #include "core/hle/kernel/k_shared_memory.h" | 8 | #include "core/hle/kernel/k_shared_memory.h" |
| 10 | #include "core/hle/kernel/k_transfer_memory.h" | 9 | #include "core/hle/kernel/k_transfer_memory.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/service/hid/errors.h" | ||
| 13 | #include "core/hle/service/hid/hid_firmware_settings.h" | ||
| 14 | #include "core/hle/service/hid/hid_server.h" | 11 | #include "core/hle/service/hid/hid_server.h" |
| 15 | #include "core/hle/service/hid/hid_util.h" | ||
| 16 | #include "core/hle/service/hid/resource_manager.h" | ||
| 17 | #include "core/hle/service/ipc_helpers.h" | 12 | #include "core/hle/service/ipc_helpers.h" |
| 18 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 19 | 14 | #include "hid_core/hid_result.h" | |
| 20 | #include "core/hle/service/hid/controllers/console_six_axis.h" | 15 | #include "hid_core/hid_util.h" |
| 21 | #include "core/hle/service/hid/controllers/controller_base.h" | 16 | #include "hid_core/resource_manager.h" |
| 22 | #include "core/hle/service/hid/controllers/debug_pad.h" | 17 | #include "hid_core/resources/hid_firmware_settings.h" |
| 23 | #include "core/hle/service/hid/controllers/gesture.h" | 18 | |
| 24 | #include "core/hle/service/hid/controllers/keyboard.h" | 19 | #include "hid_core/resources/controller_base.h" |
| 25 | #include "core/hle/service/hid/controllers/mouse.h" | 20 | #include "hid_core/resources/debug_pad/debug_pad.h" |
| 26 | #include "core/hle/service/hid/controllers/npad.h" | 21 | #include "hid_core/resources/keyboard/keyboard.h" |
| 27 | #include "core/hle/service/hid/controllers/palma.h" | 22 | #include "hid_core/resources/mouse/mouse.h" |
| 28 | #include "core/hle/service/hid/controllers/seven_six_axis.h" | 23 | #include "hid_core/resources/npad/npad.h" |
| 29 | #include "core/hle/service/hid/controllers/six_axis.h" | 24 | #include "hid_core/resources/npad/npad_types.h" |
| 30 | #include "core/hle/service/hid/controllers/touchscreen.h" | 25 | #include "hid_core/resources/palma/palma.h" |
| 31 | #include "core/hle/service/hid/controllers/types/npad_types.h" | 26 | #include "hid_core/resources/six_axis/console_six_axis.h" |
| 27 | #include "hid_core/resources/six_axis/seven_six_axis.h" | ||
| 28 | #include "hid_core/resources/six_axis/six_axis.h" | ||
| 29 | #include "hid_core/resources/touch_screen/gesture.h" | ||
| 30 | #include "hid_core/resources/touch_screen/touch_screen.h" | ||
| 32 | 31 | ||
| 33 | namespace Service::HID { | 32 | namespace Service::HID { |
| 34 | 33 | ||
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 4823de743..027c56025 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp | |||
| @@ -1,15 +1,14 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hid/hid_core.h" | ||
| 5 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 6 | #include "core/hle/service/hid/controllers/palma.h" | ||
| 7 | #include "core/hle/service/hid/controllers/touchscreen.h" | ||
| 8 | #include "core/hle/service/hid/controllers/types/npad_types.h" | ||
| 9 | #include "core/hle/service/hid/errors.h" | ||
| 10 | #include "core/hle/service/hid/hid_system_server.h" | 4 | #include "core/hle/service/hid/hid_system_server.h" |
| 11 | #include "core/hle/service/hid/resource_manager.h" | ||
| 12 | #include "core/hle/service/ipc_helpers.h" | 5 | #include "core/hle/service/ipc_helpers.h" |
| 6 | #include "hid_core/hid_result.h" | ||
| 7 | #include "hid_core/resource_manager.h" | ||
| 8 | #include "hid_core/resources/npad/npad.h" | ||
| 9 | #include "hid_core/resources/npad/npad_types.h" | ||
| 10 | #include "hid_core/resources/palma/palma.h" | ||
| 11 | #include "hid_core/resources/touch_screen/touch_screen.h" | ||
| 13 | 12 | ||
| 14 | namespace Service::HID { | 13 | namespace Service::HID { |
| 15 | 14 | ||
| @@ -270,7 +269,7 @@ void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) { | |||
| 270 | 269 | ||
| 271 | IPC::ResponseBuilder rb{ctx, 3}; | 270 | IPC::ResponseBuilder rb{ctx, 3}; |
| 272 | rb.Push(ResultSuccess); | 271 | rb.Push(ResultSuccess); |
| 273 | rb.PushEnum(system.HIDCore().GetLastActiveController()); | 272 | rb.Push(0); // Dont forget to fix this |
| 274 | } | 273 | } |
| 275 | 274 | ||
| 276 | void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { | 275 | void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/hid/hid_util.h b/src/core/hle/service/hid/hid_util.h deleted file mode 100644 index 6a2ed287a..000000000 --- a/src/core/hle/service/hid/hid_util.h +++ /dev/null | |||
| @@ -1,146 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hid/hid_types.h" | ||
| 7 | #include "core/hle/service/hid/errors.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | |||
| 11 | constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) { | ||
| 12 | switch (npad_id) { | ||
| 13 | case Core::HID::NpadIdType::Player1: | ||
| 14 | case Core::HID::NpadIdType::Player2: | ||
| 15 | case Core::HID::NpadIdType::Player3: | ||
| 16 | case Core::HID::NpadIdType::Player4: | ||
| 17 | case Core::HID::NpadIdType::Player5: | ||
| 18 | case Core::HID::NpadIdType::Player6: | ||
| 19 | case Core::HID::NpadIdType::Player7: | ||
| 20 | case Core::HID::NpadIdType::Player8: | ||
| 21 | case Core::HID::NpadIdType::Other: | ||
| 22 | case Core::HID::NpadIdType::Handheld: | ||
| 23 | return true; | ||
| 24 | default: | ||
| 25 | return false; | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) { | ||
| 30 | const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 31 | const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; | ||
| 32 | |||
| 33 | if (!npad_id) { | ||
| 34 | return ResultInvalidNpadId; | ||
| 35 | } | ||
| 36 | if (!device_index) { | ||
| 37 | return NpadDeviceIndexOutOfRange; | ||
| 38 | } | ||
| 39 | |||
| 40 | return ResultSuccess; | ||
| 41 | } | ||
| 42 | |||
| 43 | constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 44 | switch (handle.npad_type) { | ||
| 45 | case Core::HID::NpadStyleIndex::ProController: | ||
| 46 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 47 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 48 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 49 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 50 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 51 | case Core::HID::NpadStyleIndex::N64: | ||
| 52 | case Core::HID::NpadStyleIndex::SystemExt: | ||
| 53 | case Core::HID::NpadStyleIndex::System: | ||
| 54 | // These support vibration | ||
| 55 | break; | ||
| 56 | default: | ||
| 57 | return ResultVibrationInvalidStyleIndex; | ||
| 58 | } | ||
| 59 | |||
| 60 | if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) { | ||
| 61 | return ResultVibrationInvalidNpadId; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) { | ||
| 65 | return ResultVibrationDeviceIndexOutOfRange; | ||
| 66 | } | ||
| 67 | |||
| 68 | return ResultSuccess; | ||
| 69 | } | ||
| 70 | |||
| 71 | /// Converts a Core::HID::NpadIdType to an array index. | ||
| 72 | constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) { | ||
| 73 | switch (npad_id_type) { | ||
| 74 | case Core::HID::NpadIdType::Player1: | ||
| 75 | return 0; | ||
| 76 | case Core::HID::NpadIdType::Player2: | ||
| 77 | return 1; | ||
| 78 | case Core::HID::NpadIdType::Player3: | ||
| 79 | return 2; | ||
| 80 | case Core::HID::NpadIdType::Player4: | ||
| 81 | return 3; | ||
| 82 | case Core::HID::NpadIdType::Player5: | ||
| 83 | return 4; | ||
| 84 | case Core::HID::NpadIdType::Player6: | ||
| 85 | return 5; | ||
| 86 | case Core::HID::NpadIdType::Player7: | ||
| 87 | return 6; | ||
| 88 | case Core::HID::NpadIdType::Player8: | ||
| 89 | return 7; | ||
| 90 | case Core::HID::NpadIdType::Handheld: | ||
| 91 | return 8; | ||
| 92 | case Core::HID::NpadIdType::Other: | ||
| 93 | return 9; | ||
| 94 | default: | ||
| 95 | return 8; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | /// Converts an array index to a Core::HID::NpadIdType | ||
| 100 | constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) { | ||
| 101 | switch (index) { | ||
| 102 | case 0: | ||
| 103 | return Core::HID::NpadIdType::Player1; | ||
| 104 | case 1: | ||
| 105 | return Core::HID::NpadIdType::Player2; | ||
| 106 | case 2: | ||
| 107 | return Core::HID::NpadIdType::Player3; | ||
| 108 | case 3: | ||
| 109 | return Core::HID::NpadIdType::Player4; | ||
| 110 | case 4: | ||
| 111 | return Core::HID::NpadIdType::Player5; | ||
| 112 | case 5: | ||
| 113 | return Core::HID::NpadIdType::Player6; | ||
| 114 | case 6: | ||
| 115 | return Core::HID::NpadIdType::Player7; | ||
| 116 | case 7: | ||
| 117 | return Core::HID::NpadIdType::Player8; | ||
| 118 | case 8: | ||
| 119 | return Core::HID::NpadIdType::Handheld; | ||
| 120 | case 9: | ||
| 121 | return Core::HID::NpadIdType::Other; | ||
| 122 | default: | ||
| 123 | return Core::HID::NpadIdType::Invalid; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) { | ||
| 128 | switch (index) { | ||
| 129 | case 0: | ||
| 130 | return Core::HID::NpadStyleSet::Fullkey; | ||
| 131 | case 1: | ||
| 132 | return Core::HID::NpadStyleSet::Handheld; | ||
| 133 | case 2: | ||
| 134 | return Core::HID::NpadStyleSet::JoyDual; | ||
| 135 | case 3: | ||
| 136 | return Core::HID::NpadStyleSet::JoyLeft; | ||
| 137 | case 4: | ||
| 138 | return Core::HID::NpadStyleSet::JoyRight; | ||
| 139 | case 5: | ||
| 140 | return Core::HID::NpadStyleSet::Palma; | ||
| 141 | default: | ||
| 142 | return Core::HID::NpadStyleSet::None; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index ffa7e144d..46f503d38 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp | |||
| @@ -5,18 +5,18 @@ | |||
| 5 | #include "common/settings.h" | 5 | #include "common/settings.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| 10 | #include "core/hle/kernel/k_readable_event.h" | 9 | #include "core/hle/kernel/k_readable_event.h" |
| 11 | #include "core/hle/kernel/k_shared_memory.h" | 10 | #include "core/hle/kernel/k_shared_memory.h" |
| 12 | #include "core/hle/kernel/k_transfer_memory.h" | 11 | #include "core/hle/kernel/k_transfer_memory.h" |
| 13 | #include "core/hle/service/hid/hidbus.h" | 12 | #include "core/hle/service/hid/hidbus.h" |
| 14 | #include "core/hle/service/hid/hidbus/ringcon.h" | ||
| 15 | #include "core/hle/service/hid/hidbus/starlink.h" | ||
| 16 | #include "core/hle/service/hid/hidbus/stubbed.h" | ||
| 17 | #include "core/hle/service/ipc_helpers.h" | 13 | #include "core/hle/service/ipc_helpers.h" |
| 18 | #include "core/hle/service/service.h" | 14 | #include "core/hle/service/service.h" |
| 19 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 16 | #include "hid_core/hid_types.h" | ||
| 17 | #include "hid_core/hidbus/ringcon.h" | ||
| 18 | #include "hid_core/hidbus/starlink.h" | ||
| 19 | #include "hid_core/hidbus/stubbed.h" | ||
| 20 | 20 | ||
| 21 | namespace Service::HID { | 21 | namespace Service::HID { |
| 22 | // (15ms, 66Hz) | 22 | // (15ms, 66Hz) |
diff --git a/src/core/hle/service/hid/hidbus.h b/src/core/hle/service/hid/hidbus.h index 85a1df133..05f62f634 100644 --- a/src/core/hle/service/hid/hidbus.h +++ b/src/core/hle/service/hid/hidbus.h | |||
| @@ -5,9 +5,9 @@ | |||
| 5 | 5 | ||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | 7 | ||
| 8 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 9 | #include "core/hle/service/kernel_helpers.h" | 8 | #include "core/hle/service/kernel_helpers.h" |
| 10 | #include "core/hle/service/service.h" | 9 | #include "core/hle/service/service.h" |
| 10 | #include "hid_core/hidbus/hidbus_base.h" | ||
| 11 | 11 | ||
| 12 | namespace Core::Timing { | 12 | namespace Core::Timing { |
| 13 | struct EventType; | 13 | struct EventType; |
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.cpp b/src/core/hle/service/hid/hidbus/hidbus_base.cpp deleted file mode 100644 index 8c44f93e8..000000000 --- a/src/core/hle/service/hid/hidbus/hidbus_base.cpp +++ /dev/null | |||
| @@ -1,73 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hid/hid_core.h" | ||
| 5 | #include "core/hle/kernel/k_event.h" | ||
| 6 | #include "core/hle/kernel/k_readable_event.h" | ||
| 7 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 8 | #include "core/hle/service/kernel_helpers.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | HidbusBase::HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_) | ||
| 13 | : system(system_), service_context(service_context_) { | ||
| 14 | send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent"); | ||
| 15 | } | ||
| 16 | |||
| 17 | HidbusBase::~HidbusBase() { | ||
| 18 | service_context.CloseEvent(send_command_async_event); | ||
| 19 | }; | ||
| 20 | |||
| 21 | void HidbusBase::ActivateDevice() { | ||
| 22 | if (is_activated) { | ||
| 23 | return; | ||
| 24 | } | ||
| 25 | is_activated = true; | ||
| 26 | OnInit(); | ||
| 27 | } | ||
| 28 | |||
| 29 | void HidbusBase::DeactivateDevice() { | ||
| 30 | if (is_activated) { | ||
| 31 | OnRelease(); | ||
| 32 | } | ||
| 33 | is_activated = false; | ||
| 34 | } | ||
| 35 | |||
| 36 | bool HidbusBase::IsDeviceActivated() const { | ||
| 37 | return is_activated; | ||
| 38 | } | ||
| 39 | |||
| 40 | void HidbusBase::Enable(bool enable) { | ||
| 41 | device_enabled = enable; | ||
| 42 | } | ||
| 43 | |||
| 44 | bool HidbusBase::IsEnabled() const { | ||
| 45 | return device_enabled; | ||
| 46 | } | ||
| 47 | |||
| 48 | bool HidbusBase::IsPollingMode() const { | ||
| 49 | return polling_mode_enabled; | ||
| 50 | } | ||
| 51 | |||
| 52 | JoyPollingMode HidbusBase::GetPollingMode() const { | ||
| 53 | return polling_mode; | ||
| 54 | } | ||
| 55 | |||
| 56 | void HidbusBase::SetPollingMode(JoyPollingMode mode) { | ||
| 57 | polling_mode = mode; | ||
| 58 | polling_mode_enabled = true; | ||
| 59 | } | ||
| 60 | |||
| 61 | void HidbusBase::DisablePollingMode() { | ||
| 62 | polling_mode_enabled = false; | ||
| 63 | } | ||
| 64 | |||
| 65 | void HidbusBase::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { | ||
| 66 | transfer_memory = t_mem; | ||
| 67 | } | ||
| 68 | |||
| 69 | Kernel::KReadableEvent& HidbusBase::GetSendCommandAsycEvent() const { | ||
| 70 | return send_command_async_event->GetReadableEvent(); | ||
| 71 | } | ||
| 72 | |||
| 73 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h deleted file mode 100644 index ec41684e1..000000000 --- a/src/core/hle/service/hid/hidbus/hidbus_base.h +++ /dev/null | |||
| @@ -1,183 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <span> | ||
| 8 | #include "common/typed_address.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | |||
| 11 | namespace Core { | ||
| 12 | class System; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Kernel { | ||
| 16 | class KEvent; | ||
| 17 | class KReadableEvent; | ||
| 18 | } // namespace Kernel | ||
| 19 | |||
| 20 | namespace Service::KernelHelpers { | ||
| 21 | class ServiceContext; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace Service::HID { | ||
| 25 | |||
| 26 | // This is nn::hidbus::JoyPollingMode | ||
| 27 | enum class JoyPollingMode : u32 { | ||
| 28 | SixAxisSensorDisable, | ||
| 29 | SixAxisSensorEnable, | ||
| 30 | ButtonOnly, | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct DataAccessorHeader { | ||
| 34 | Result result{ResultUnknown}; | ||
| 35 | INSERT_PADDING_WORDS(0x1); | ||
| 36 | std::array<u8, 0x18> unused{}; | ||
| 37 | u64 latest_entry{}; | ||
| 38 | u64 total_entries{}; | ||
| 39 | }; | ||
| 40 | static_assert(sizeof(DataAccessorHeader) == 0x30, "DataAccessorHeader is an invalid size"); | ||
| 41 | |||
| 42 | struct JoyDisableSixAxisPollingData { | ||
| 43 | std::array<u8, 0x26> data; | ||
| 44 | u8 out_size; | ||
| 45 | INSERT_PADDING_BYTES(0x1); | ||
| 46 | u64 sampling_number; | ||
| 47 | }; | ||
| 48 | static_assert(sizeof(JoyDisableSixAxisPollingData) == 0x30, | ||
| 49 | "JoyDisableSixAxisPollingData is an invalid size"); | ||
| 50 | |||
| 51 | struct JoyEnableSixAxisPollingData { | ||
| 52 | std::array<u8, 0x8> data; | ||
| 53 | u8 out_size; | ||
| 54 | INSERT_PADDING_BYTES(0x7); | ||
| 55 | u64 sampling_number; | ||
| 56 | }; | ||
| 57 | static_assert(sizeof(JoyEnableSixAxisPollingData) == 0x18, | ||
| 58 | "JoyEnableSixAxisPollingData is an invalid size"); | ||
| 59 | |||
| 60 | struct JoyButtonOnlyPollingData { | ||
| 61 | std::array<u8, 0x2c> data; | ||
| 62 | u8 out_size; | ||
| 63 | INSERT_PADDING_BYTES(0x3); | ||
| 64 | u64 sampling_number; | ||
| 65 | }; | ||
| 66 | static_assert(sizeof(JoyButtonOnlyPollingData) == 0x38, | ||
| 67 | "JoyButtonOnlyPollingData is an invalid size"); | ||
| 68 | |||
| 69 | struct JoyDisableSixAxisPollingEntry { | ||
| 70 | u64 sampling_number; | ||
| 71 | JoyDisableSixAxisPollingData polling_data; | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(JoyDisableSixAxisPollingEntry) == 0x38, | ||
| 74 | "JoyDisableSixAxisPollingEntry is an invalid size"); | ||
| 75 | |||
| 76 | struct JoyEnableSixAxisPollingEntry { | ||
| 77 | u64 sampling_number; | ||
| 78 | JoyEnableSixAxisPollingData polling_data; | ||
| 79 | }; | ||
| 80 | static_assert(sizeof(JoyEnableSixAxisPollingEntry) == 0x20, | ||
| 81 | "JoyEnableSixAxisPollingEntry is an invalid size"); | ||
| 82 | |||
| 83 | struct JoyButtonOnlyPollingEntry { | ||
| 84 | u64 sampling_number; | ||
| 85 | JoyButtonOnlyPollingData polling_data; | ||
| 86 | }; | ||
| 87 | static_assert(sizeof(JoyButtonOnlyPollingEntry) == 0x40, | ||
| 88 | "JoyButtonOnlyPollingEntry is an invalid size"); | ||
| 89 | |||
| 90 | struct JoyDisableSixAxisDataAccessor { | ||
| 91 | DataAccessorHeader header{}; | ||
| 92 | std::array<JoyDisableSixAxisPollingEntry, 0xb> entries{}; | ||
| 93 | }; | ||
| 94 | static_assert(sizeof(JoyDisableSixAxisDataAccessor) == 0x298, | ||
| 95 | "JoyDisableSixAxisDataAccessor is an invalid size"); | ||
| 96 | |||
| 97 | struct JoyEnableSixAxisDataAccessor { | ||
| 98 | DataAccessorHeader header{}; | ||
| 99 | std::array<JoyEnableSixAxisPollingEntry, 0xb> entries{}; | ||
| 100 | }; | ||
| 101 | static_assert(sizeof(JoyEnableSixAxisDataAccessor) == 0x190, | ||
| 102 | "JoyEnableSixAxisDataAccessor is an invalid size"); | ||
| 103 | |||
| 104 | struct ButtonOnlyPollingDataAccessor { | ||
| 105 | DataAccessorHeader header; | ||
| 106 | std::array<JoyButtonOnlyPollingEntry, 0xb> entries; | ||
| 107 | }; | ||
| 108 | static_assert(sizeof(ButtonOnlyPollingDataAccessor) == 0x2F0, | ||
| 109 | "ButtonOnlyPollingDataAccessor is an invalid size"); | ||
| 110 | |||
| 111 | class HidbusBase { | ||
| 112 | public: | ||
| 113 | explicit HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 114 | virtual ~HidbusBase(); | ||
| 115 | |||
| 116 | void ActivateDevice(); | ||
| 117 | |||
| 118 | void DeactivateDevice(); | ||
| 119 | |||
| 120 | bool IsDeviceActivated() const; | ||
| 121 | |||
| 122 | // Enables/disables the device | ||
| 123 | void Enable(bool enable); | ||
| 124 | |||
| 125 | // returns true if device is enabled | ||
| 126 | bool IsEnabled() const; | ||
| 127 | |||
| 128 | // returns true if polling mode is enabled | ||
| 129 | bool IsPollingMode() const; | ||
| 130 | |||
| 131 | // returns polling mode | ||
| 132 | JoyPollingMode GetPollingMode() const; | ||
| 133 | |||
| 134 | // Sets and enables JoyPollingMode | ||
| 135 | void SetPollingMode(JoyPollingMode mode); | ||
| 136 | |||
| 137 | // Disables JoyPollingMode | ||
| 138 | void DisablePollingMode(); | ||
| 139 | |||
| 140 | // Called on EnableJoyPollingReceiveMode | ||
| 141 | void SetTransferMemoryAddress(Common::ProcessAddress t_mem); | ||
| 142 | |||
| 143 | Kernel::KReadableEvent& GetSendCommandAsycEvent() const; | ||
| 144 | |||
| 145 | virtual void OnInit() {} | ||
| 146 | |||
| 147 | virtual void OnRelease() {} | ||
| 148 | |||
| 149 | // Updates device transfer memory | ||
| 150 | virtual void OnUpdate() {} | ||
| 151 | |||
| 152 | // Returns the device ID of the joycon | ||
| 153 | virtual u8 GetDeviceId() const { | ||
| 154 | return {}; | ||
| 155 | } | ||
| 156 | |||
| 157 | // Assigns a command from data | ||
| 158 | virtual bool SetCommand(std::span<const u8> data) { | ||
| 159 | return {}; | ||
| 160 | } | ||
| 161 | |||
| 162 | // Returns a reply from a command | ||
| 163 | virtual std::vector<u8> GetReply() const { | ||
| 164 | return {}; | ||
| 165 | } | ||
| 166 | |||
| 167 | protected: | ||
| 168 | bool is_activated{}; | ||
| 169 | bool device_enabled{}; | ||
| 170 | bool polling_mode_enabled{}; | ||
| 171 | JoyPollingMode polling_mode = {}; | ||
| 172 | // TODO(German77): All data accessors need to be replaced with a ring lifo object | ||
| 173 | JoyDisableSixAxisDataAccessor disable_sixaxis_data{}; | ||
| 174 | JoyEnableSixAxisDataAccessor enable_sixaxis_data{}; | ||
| 175 | ButtonOnlyPollingDataAccessor button_only_data{}; | ||
| 176 | |||
| 177 | Common::ProcessAddress transfer_memory{}; | ||
| 178 | |||
| 179 | Core::System& system; | ||
| 180 | Kernel::KEvent* send_command_async_event; | ||
| 181 | KernelHelpers::ServiceContext& service_context; | ||
| 182 | }; | ||
| 183 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp deleted file mode 100644 index 378108012..000000000 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ /dev/null | |||
| @@ -1,292 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hid/emulated_controller.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 8 | #include "core/hle/kernel/k_readable_event.h" | ||
| 9 | #include "core/hle/service/hid/hidbus/ringcon.h" | ||
| 10 | #include "core/memory.h" | ||
| 11 | |||
| 12 | namespace Service::HID { | ||
| 13 | |||
| 14 | RingController::RingController(Core::System& system_, | ||
| 15 | KernelHelpers::ServiceContext& service_context_) | ||
| 16 | : HidbusBase(system_, service_context_) { | ||
| 17 | input = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); | ||
| 18 | } | ||
| 19 | |||
| 20 | RingController::~RingController() = default; | ||
| 21 | |||
| 22 | void RingController::OnInit() { | ||
| 23 | input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, | ||
| 24 | Common::Input::PollingMode::Ring); | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | |||
| 28 | void RingController::OnRelease() { | ||
| 29 | input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, | ||
| 30 | Common::Input::PollingMode::Active); | ||
| 31 | return; | ||
| 32 | }; | ||
| 33 | |||
| 34 | void RingController::OnUpdate() { | ||
| 35 | if (!is_activated) { | ||
| 36 | return; | ||
| 37 | } | ||
| 38 | |||
| 39 | if (!device_enabled) { | ||
| 40 | return; | ||
| 41 | } | ||
| 42 | |||
| 43 | if (!polling_mode_enabled || transfer_memory == 0) { | ||
| 44 | return; | ||
| 45 | } | ||
| 46 | |||
| 47 | // TODO: Increment multitasking counters from motion and sensor data | ||
| 48 | |||
| 49 | switch (polling_mode) { | ||
| 50 | case JoyPollingMode::SixAxisSensorEnable: { | ||
| 51 | enable_sixaxis_data.header.total_entries = 10; | ||
| 52 | enable_sixaxis_data.header.result = ResultSuccess; | ||
| 53 | const auto& last_entry = | ||
| 54 | enable_sixaxis_data.entries[enable_sixaxis_data.header.latest_entry]; | ||
| 55 | |||
| 56 | enable_sixaxis_data.header.latest_entry = | ||
| 57 | (enable_sixaxis_data.header.latest_entry + 1) % 10; | ||
| 58 | auto& curr_entry = enable_sixaxis_data.entries[enable_sixaxis_data.header.latest_entry]; | ||
| 59 | |||
| 60 | curr_entry.sampling_number = last_entry.sampling_number + 1; | ||
| 61 | curr_entry.polling_data.sampling_number = curr_entry.sampling_number; | ||
| 62 | |||
| 63 | const RingConData ringcon_value = GetSensorValue(); | ||
| 64 | curr_entry.polling_data.out_size = sizeof(ringcon_value); | ||
| 65 | std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value)); | ||
| 66 | |||
| 67 | system.ApplicationMemory().WriteBlock(transfer_memory, &enable_sixaxis_data, | ||
| 68 | sizeof(enable_sixaxis_data)); | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | default: | ||
| 72 | LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | RingController::RingConData RingController::GetSensorValue() const { | ||
| 78 | RingConData ringcon_sensor_value{ | ||
| 79 | .status = DataValid::Valid, | ||
| 80 | .data = 0, | ||
| 81 | }; | ||
| 82 | |||
| 83 | const f32 force_value = input->GetRingSensorForce().force * range; | ||
| 84 | ringcon_sensor_value.data = static_cast<s16>(force_value) + idle_value; | ||
| 85 | |||
| 86 | return ringcon_sensor_value; | ||
| 87 | } | ||
| 88 | |||
| 89 | u8 RingController::GetDeviceId() const { | ||
| 90 | return device_id; | ||
| 91 | } | ||
| 92 | |||
| 93 | std::vector<u8> RingController::GetReply() const { | ||
| 94 | const RingConCommands current_command = command; | ||
| 95 | |||
| 96 | switch (current_command) { | ||
| 97 | case RingConCommands::GetFirmwareVersion: | ||
| 98 | return GetFirmwareVersionReply(); | ||
| 99 | case RingConCommands::ReadId: | ||
| 100 | return GetReadIdReply(); | ||
| 101 | case RingConCommands::c20105: | ||
| 102 | return GetC020105Reply(); | ||
| 103 | case RingConCommands::ReadUnkCal: | ||
| 104 | return GetReadUnkCalReply(); | ||
| 105 | case RingConCommands::ReadFactoryCal: | ||
| 106 | return GetReadFactoryCalReply(); | ||
| 107 | case RingConCommands::ReadUserCal: | ||
| 108 | return GetReadUserCalReply(); | ||
| 109 | case RingConCommands::ReadRepCount: | ||
| 110 | return GetReadRepCountReply(); | ||
| 111 | case RingConCommands::ReadTotalPushCount: | ||
| 112 | return GetReadTotalPushCountReply(); | ||
| 113 | case RingConCommands::ResetRepCount: | ||
| 114 | return GetResetRepCountReply(); | ||
| 115 | case RingConCommands::SaveCalData: | ||
| 116 | return GetSaveDataReply(); | ||
| 117 | default: | ||
| 118 | return GetErrorReply(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | bool RingController::SetCommand(std::span<const u8> data) { | ||
| 123 | if (data.size() < 4) { | ||
| 124 | LOG_ERROR(Service_HID, "Command size not supported {}", data.size()); | ||
| 125 | command = RingConCommands::Error; | ||
| 126 | return false; | ||
| 127 | } | ||
| 128 | |||
| 129 | std::memcpy(&command, data.data(), sizeof(RingConCommands)); | ||
| 130 | |||
| 131 | switch (command) { | ||
| 132 | case RingConCommands::GetFirmwareVersion: | ||
| 133 | case RingConCommands::ReadId: | ||
| 134 | case RingConCommands::c20105: | ||
| 135 | case RingConCommands::ReadUnkCal: | ||
| 136 | case RingConCommands::ReadFactoryCal: | ||
| 137 | case RingConCommands::ReadUserCal: | ||
| 138 | case RingConCommands::ReadRepCount: | ||
| 139 | case RingConCommands::ReadTotalPushCount: | ||
| 140 | ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); | ||
| 141 | send_command_async_event->Signal(); | ||
| 142 | return true; | ||
| 143 | case RingConCommands::ResetRepCount: | ||
| 144 | ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); | ||
| 145 | total_rep_count = 0; | ||
| 146 | send_command_async_event->Signal(); | ||
| 147 | return true; | ||
| 148 | case RingConCommands::SaveCalData: { | ||
| 149 | ASSERT_MSG(data.size() == 0x14, "data.size is not 0x14 bytes"); | ||
| 150 | |||
| 151 | SaveCalData save_info{}; | ||
| 152 | std::memcpy(&save_info, data.data(), sizeof(SaveCalData)); | ||
| 153 | user_calibration = save_info.calibration; | ||
| 154 | send_command_async_event->Signal(); | ||
| 155 | return true; | ||
| 156 | } | ||
| 157 | default: | ||
| 158 | LOG_ERROR(Service_HID, "Command not implemented {}", command); | ||
| 159 | command = RingConCommands::Error; | ||
| 160 | // Signal a reply to avoid softlocking the game | ||
| 161 | send_command_async_event->Signal(); | ||
| 162 | return false; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | std::vector<u8> RingController::GetFirmwareVersionReply() const { | ||
| 167 | const FirmwareVersionReply reply{ | ||
| 168 | .status = DataValid::Valid, | ||
| 169 | .firmware = version, | ||
| 170 | }; | ||
| 171 | |||
| 172 | return GetDataVector(reply); | ||
| 173 | } | ||
| 174 | |||
| 175 | std::vector<u8> RingController::GetReadIdReply() const { | ||
| 176 | // The values are hardcoded from a real joycon | ||
| 177 | const ReadIdReply reply{ | ||
| 178 | .status = DataValid::Valid, | ||
| 179 | .id_l_x0 = 8, | ||
| 180 | .id_l_x0_2 = 41, | ||
| 181 | .id_l_x4 = 22294, | ||
| 182 | .id_h_x0 = 19777, | ||
| 183 | .id_h_x0_2 = 13621, | ||
| 184 | .id_h_x4 = 8245, | ||
| 185 | }; | ||
| 186 | |||
| 187 | return GetDataVector(reply); | ||
| 188 | } | ||
| 189 | |||
| 190 | std::vector<u8> RingController::GetC020105Reply() const { | ||
| 191 | const Cmd020105Reply reply{ | ||
| 192 | .status = DataValid::Valid, | ||
| 193 | .data = 1, | ||
| 194 | }; | ||
| 195 | |||
| 196 | return GetDataVector(reply); | ||
| 197 | } | ||
| 198 | |||
| 199 | std::vector<u8> RingController::GetReadUnkCalReply() const { | ||
| 200 | const ReadUnkCalReply reply{ | ||
| 201 | .status = DataValid::Valid, | ||
| 202 | .data = 0, | ||
| 203 | }; | ||
| 204 | |||
| 205 | return GetDataVector(reply); | ||
| 206 | } | ||
| 207 | |||
| 208 | std::vector<u8> RingController::GetReadFactoryCalReply() const { | ||
| 209 | const ReadFactoryCalReply reply{ | ||
| 210 | .status = DataValid::Valid, | ||
| 211 | .calibration = factory_calibration, | ||
| 212 | }; | ||
| 213 | |||
| 214 | return GetDataVector(reply); | ||
| 215 | } | ||
| 216 | |||
| 217 | std::vector<u8> RingController::GetReadUserCalReply() const { | ||
| 218 | const ReadUserCalReply reply{ | ||
| 219 | .status = DataValid::Valid, | ||
| 220 | .calibration = user_calibration, | ||
| 221 | }; | ||
| 222 | |||
| 223 | return GetDataVector(reply); | ||
| 224 | } | ||
| 225 | |||
| 226 | std::vector<u8> RingController::GetReadRepCountReply() const { | ||
| 227 | const GetThreeByteReply reply{ | ||
| 228 | .status = DataValid::Valid, | ||
| 229 | .data = {total_rep_count, 0, 0}, | ||
| 230 | .crc = GetCrcValue({total_rep_count, 0, 0, 0}), | ||
| 231 | }; | ||
| 232 | |||
| 233 | return GetDataVector(reply); | ||
| 234 | } | ||
| 235 | |||
| 236 | std::vector<u8> RingController::GetReadTotalPushCountReply() const { | ||
| 237 | const GetThreeByteReply reply{ | ||
| 238 | .status = DataValid::Valid, | ||
| 239 | .data = {total_push_count, 0, 0}, | ||
| 240 | .crc = GetCrcValue({total_push_count, 0, 0, 0}), | ||
| 241 | }; | ||
| 242 | |||
| 243 | return GetDataVector(reply); | ||
| 244 | } | ||
| 245 | |||
| 246 | std::vector<u8> RingController::GetResetRepCountReply() const { | ||
| 247 | return GetReadRepCountReply(); | ||
| 248 | } | ||
| 249 | |||
| 250 | std::vector<u8> RingController::GetSaveDataReply() const { | ||
| 251 | const StatusReply reply{ | ||
| 252 | .status = DataValid::Valid, | ||
| 253 | }; | ||
| 254 | |||
| 255 | return GetDataVector(reply); | ||
| 256 | } | ||
| 257 | |||
| 258 | std::vector<u8> RingController::GetErrorReply() const { | ||
| 259 | const ErrorReply reply{ | ||
| 260 | .status = DataValid::BadCRC, | ||
| 261 | }; | ||
| 262 | |||
| 263 | return GetDataVector(reply); | ||
| 264 | } | ||
| 265 | |||
| 266 | u8 RingController::GetCrcValue(const std::vector<u8>& data) const { | ||
| 267 | u8 crc = 0; | ||
| 268 | for (std::size_t index = 0; index < data.size(); index++) { | ||
| 269 | for (u8 i = 0x80; i > 0; i >>= 1) { | ||
| 270 | bool bit = (crc & 0x80) != 0; | ||
| 271 | if ((data[index] & i) != 0) { | ||
| 272 | bit = !bit; | ||
| 273 | } | ||
| 274 | crc <<= 1; | ||
| 275 | if (bit) { | ||
| 276 | crc ^= 0x8d; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | } | ||
| 280 | return crc; | ||
| 281 | } | ||
| 282 | |||
| 283 | template <typename T> | ||
| 284 | std::vector<u8> RingController::GetDataVector(const T& reply) const { | ||
| 285 | static_assert(std::is_trivially_copyable_v<T>); | ||
| 286 | std::vector<u8> data; | ||
| 287 | data.resize(sizeof(reply)); | ||
| 288 | std::memcpy(data.data(), &reply, sizeof(reply)); | ||
| 289 | return data; | ||
| 290 | } | ||
| 291 | |||
| 292 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/ringcon.h b/src/core/hle/service/hid/hidbus/ringcon.h deleted file mode 100644 index f42f3ea41..000000000 --- a/src/core/hle/service/hid/hidbus/ringcon.h +++ /dev/null | |||
| @@ -1,253 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <span> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 11 | |||
| 12 | namespace Core::HID { | ||
| 13 | class EmulatedController; | ||
| 14 | } // namespace Core::HID | ||
| 15 | |||
| 16 | namespace Service::HID { | ||
| 17 | |||
| 18 | class RingController final : public HidbusBase { | ||
| 19 | public: | ||
| 20 | explicit RingController(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 21 | ~RingController() override; | ||
| 22 | |||
| 23 | void OnInit() override; | ||
| 24 | |||
| 25 | void OnRelease() override; | ||
| 26 | |||
| 27 | // Updates ringcon transfer memory | ||
| 28 | void OnUpdate() override; | ||
| 29 | |||
| 30 | // Returns the device ID of the joycon | ||
| 31 | u8 GetDeviceId() const override; | ||
| 32 | |||
| 33 | // Assigns a command from data | ||
| 34 | bool SetCommand(std::span<const u8> data) override; | ||
| 35 | |||
| 36 | // Returns a reply from a command | ||
| 37 | std::vector<u8> GetReply() const override; | ||
| 38 | |||
| 39 | private: | ||
| 40 | // These values are obtained from a real ring controller | ||
| 41 | static constexpr s16 idle_value = 2280; | ||
| 42 | static constexpr s16 idle_deadzone = 120; | ||
| 43 | static constexpr s16 range = 2500; | ||
| 44 | |||
| 45 | // Most missing command names are leftovers from other firmware versions | ||
| 46 | enum class RingConCommands : u32 { | ||
| 47 | GetFirmwareVersion = 0x00020000, | ||
| 48 | ReadId = 0x00020100, | ||
| 49 | JoyPolling = 0x00020101, | ||
| 50 | Unknown1 = 0x00020104, | ||
| 51 | c20105 = 0x00020105, | ||
| 52 | Unknown2 = 0x00020204, | ||
| 53 | Unknown3 = 0x00020304, | ||
| 54 | Unknown4 = 0x00020404, | ||
| 55 | ReadUnkCal = 0x00020504, | ||
| 56 | ReadFactoryCal = 0x00020A04, | ||
| 57 | Unknown5 = 0x00021104, | ||
| 58 | Unknown6 = 0x00021204, | ||
| 59 | Unknown7 = 0x00021304, | ||
| 60 | ReadUserCal = 0x00021A04, | ||
| 61 | ReadRepCount = 0x00023104, | ||
| 62 | ReadTotalPushCount = 0x00023204, | ||
| 63 | ResetRepCount = 0x04013104, | ||
| 64 | Unknown8 = 0x04011104, | ||
| 65 | Unknown9 = 0x04011204, | ||
| 66 | Unknown10 = 0x04011304, | ||
| 67 | SaveCalData = 0x10011A04, | ||
| 68 | Error = 0xFFFFFFFF, | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum class DataValid : u32 { | ||
| 72 | Valid, | ||
| 73 | BadCRC, | ||
| 74 | Cal, | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct FirmwareVersion { | ||
| 78 | u8 sub; | ||
| 79 | u8 main; | ||
| 80 | }; | ||
| 81 | static_assert(sizeof(FirmwareVersion) == 0x2, "FirmwareVersion is an invalid size"); | ||
| 82 | |||
| 83 | struct FactoryCalibration { | ||
| 84 | s32_le os_max; | ||
| 85 | s32_le hk_max; | ||
| 86 | s32_le zero_min; | ||
| 87 | s32_le zero_max; | ||
| 88 | }; | ||
| 89 | static_assert(sizeof(FactoryCalibration) == 0x10, "FactoryCalibration is an invalid size"); | ||
| 90 | |||
| 91 | struct CalibrationValue { | ||
| 92 | s16 value; | ||
| 93 | u16 crc; | ||
| 94 | }; | ||
| 95 | static_assert(sizeof(CalibrationValue) == 0x4, "CalibrationValue is an invalid size"); | ||
| 96 | |||
| 97 | struct UserCalibration { | ||
| 98 | CalibrationValue os_max; | ||
| 99 | CalibrationValue hk_max; | ||
| 100 | CalibrationValue zero; | ||
| 101 | }; | ||
| 102 | static_assert(sizeof(UserCalibration) == 0xC, "UserCalibration is an invalid size"); | ||
| 103 | |||
| 104 | struct SaveCalData { | ||
| 105 | RingConCommands command; | ||
| 106 | UserCalibration calibration; | ||
| 107 | INSERT_PADDING_BYTES_NOINIT(4); | ||
| 108 | }; | ||
| 109 | static_assert(sizeof(SaveCalData) == 0x14, "SaveCalData is an invalid size"); | ||
| 110 | static_assert(std::is_trivially_copyable_v<SaveCalData>, | ||
| 111 | "SaveCalData must be trivially copyable"); | ||
| 112 | |||
| 113 | struct FirmwareVersionReply { | ||
| 114 | DataValid status; | ||
| 115 | FirmwareVersion firmware; | ||
| 116 | INSERT_PADDING_BYTES(0x2); | ||
| 117 | }; | ||
| 118 | static_assert(sizeof(FirmwareVersionReply) == 0x8, "FirmwareVersionReply is an invalid size"); | ||
| 119 | |||
| 120 | struct Cmd020105Reply { | ||
| 121 | DataValid status; | ||
| 122 | u8 data; | ||
| 123 | INSERT_PADDING_BYTES(0x3); | ||
| 124 | }; | ||
| 125 | static_assert(sizeof(Cmd020105Reply) == 0x8, "Cmd020105Reply is an invalid size"); | ||
| 126 | |||
| 127 | struct StatusReply { | ||
| 128 | DataValid status; | ||
| 129 | }; | ||
| 130 | static_assert(sizeof(StatusReply) == 0x4, "StatusReply is an invalid size"); | ||
| 131 | |||
| 132 | struct GetThreeByteReply { | ||
| 133 | DataValid status; | ||
| 134 | std::array<u8, 3> data; | ||
| 135 | u8 crc; | ||
| 136 | }; | ||
| 137 | static_assert(sizeof(GetThreeByteReply) == 0x8, "GetThreeByteReply is an invalid size"); | ||
| 138 | |||
| 139 | struct ReadUnkCalReply { | ||
| 140 | DataValid status; | ||
| 141 | u16 data; | ||
| 142 | INSERT_PADDING_BYTES(0x2); | ||
| 143 | }; | ||
| 144 | static_assert(sizeof(ReadUnkCalReply) == 0x8, "ReadUnkCalReply is an invalid size"); | ||
| 145 | |||
| 146 | struct ReadFactoryCalReply { | ||
| 147 | DataValid status; | ||
| 148 | FactoryCalibration calibration; | ||
| 149 | }; | ||
| 150 | static_assert(sizeof(ReadFactoryCalReply) == 0x14, "ReadFactoryCalReply is an invalid size"); | ||
| 151 | |||
| 152 | struct ReadUserCalReply { | ||
| 153 | DataValid status; | ||
| 154 | UserCalibration calibration; | ||
| 155 | INSERT_PADDING_BYTES(0x4); | ||
| 156 | }; | ||
| 157 | static_assert(sizeof(ReadUserCalReply) == 0x14, "ReadUserCalReply is an invalid size"); | ||
| 158 | |||
| 159 | struct ReadIdReply { | ||
| 160 | DataValid status; | ||
| 161 | u16 id_l_x0; | ||
| 162 | u16 id_l_x0_2; | ||
| 163 | u16 id_l_x4; | ||
| 164 | u16 id_h_x0; | ||
| 165 | u16 id_h_x0_2; | ||
| 166 | u16 id_h_x4; | ||
| 167 | }; | ||
| 168 | static_assert(sizeof(ReadIdReply) == 0x10, "ReadIdReply is an invalid size"); | ||
| 169 | |||
| 170 | struct ErrorReply { | ||
| 171 | DataValid status; | ||
| 172 | INSERT_PADDING_BYTES(0x3); | ||
| 173 | }; | ||
| 174 | static_assert(sizeof(ErrorReply) == 0x8, "ErrorReply is an invalid size"); | ||
| 175 | |||
| 176 | struct RingConData { | ||
| 177 | DataValid status; | ||
| 178 | s16_le data; | ||
| 179 | INSERT_PADDING_BYTES(0x2); | ||
| 180 | }; | ||
| 181 | static_assert(sizeof(RingConData) == 0x8, "RingConData is an invalid size"); | ||
| 182 | |||
| 183 | // Returns RingConData struct with pressure sensor values | ||
| 184 | RingConData GetSensorValue() const; | ||
| 185 | |||
| 186 | // Returns 8 byte reply with firmware version | ||
| 187 | std::vector<u8> GetFirmwareVersionReply() const; | ||
| 188 | |||
| 189 | // Returns 16 byte reply with ID values | ||
| 190 | std::vector<u8> GetReadIdReply() const; | ||
| 191 | |||
| 192 | // (STUBBED) Returns 8 byte reply | ||
| 193 | std::vector<u8> GetC020105Reply() const; | ||
| 194 | |||
| 195 | // (STUBBED) Returns 8 byte empty reply | ||
| 196 | std::vector<u8> GetReadUnkCalReply() const; | ||
| 197 | |||
| 198 | // Returns 20 byte reply with factory calibration values | ||
| 199 | std::vector<u8> GetReadFactoryCalReply() const; | ||
| 200 | |||
| 201 | // Returns 20 byte reply with user calibration values | ||
| 202 | std::vector<u8> GetReadUserCalReply() const; | ||
| 203 | |||
| 204 | // Returns 8 byte reply | ||
| 205 | std::vector<u8> GetReadRepCountReply() const; | ||
| 206 | |||
| 207 | // Returns 8 byte reply | ||
| 208 | std::vector<u8> GetReadTotalPushCountReply() const; | ||
| 209 | |||
| 210 | // Returns 8 byte reply | ||
| 211 | std::vector<u8> GetResetRepCountReply() const; | ||
| 212 | |||
| 213 | // Returns 4 byte save data reply | ||
| 214 | std::vector<u8> GetSaveDataReply() const; | ||
| 215 | |||
| 216 | // Returns 8 byte error reply | ||
| 217 | std::vector<u8> GetErrorReply() const; | ||
| 218 | |||
| 219 | // Returns 8 bit redundancy check from provided data | ||
| 220 | u8 GetCrcValue(const std::vector<u8>& data) const; | ||
| 221 | |||
| 222 | // Converts structs to an u8 vector equivalent | ||
| 223 | template <typename T> | ||
| 224 | std::vector<u8> GetDataVector(const T& reply) const; | ||
| 225 | |||
| 226 | RingConCommands command{RingConCommands::Error}; | ||
| 227 | |||
| 228 | // These counters are used in multitasking mode while the switch is sleeping | ||
| 229 | // Total steps taken | ||
| 230 | u8 total_rep_count = 0; | ||
| 231 | // Total times the ring was pushed | ||
| 232 | u8 total_push_count = 0; | ||
| 233 | |||
| 234 | const u8 device_id = 0x20; | ||
| 235 | const FirmwareVersion version = { | ||
| 236 | .sub = 0x0, | ||
| 237 | .main = 0x2c, | ||
| 238 | }; | ||
| 239 | const FactoryCalibration factory_calibration = { | ||
| 240 | .os_max = idle_value + range + idle_deadzone, | ||
| 241 | .hk_max = idle_value - range - idle_deadzone, | ||
| 242 | .zero_min = idle_value - idle_deadzone, | ||
| 243 | .zero_max = idle_value + idle_deadzone, | ||
| 244 | }; | ||
| 245 | UserCalibration user_calibration = { | ||
| 246 | .os_max = {.value = range, .crc = 228}, | ||
| 247 | .hk_max = {.value = -range, .crc = 239}, | ||
| 248 | .zero = {.value = idle_value, .crc = 225}, | ||
| 249 | }; | ||
| 250 | |||
| 251 | Core::HID::EmulatedController* input; | ||
| 252 | }; | ||
| 253 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/starlink.cpp b/src/core/hle/service/hid/hidbus/starlink.cpp deleted file mode 100644 index 36573274e..000000000 --- a/src/core/hle/service/hid/hidbus/starlink.cpp +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hid/emulated_controller.h" | ||
| 5 | #include "core/hid/hid_core.h" | ||
| 6 | #include "core/hle/service/hid/hidbus/starlink.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | constexpr u8 DEVICE_ID = 0x28; | ||
| 10 | |||
| 11 | Starlink::Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_) | ||
| 12 | : HidbusBase(system_, service_context_) {} | ||
| 13 | Starlink::~Starlink() = default; | ||
| 14 | |||
| 15 | void Starlink::OnInit() { | ||
| 16 | return; | ||
| 17 | } | ||
| 18 | |||
| 19 | void Starlink::OnRelease() { | ||
| 20 | return; | ||
| 21 | }; | ||
| 22 | |||
| 23 | void Starlink::OnUpdate() { | ||
| 24 | if (!is_activated) { | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | if (!device_enabled) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | if (!polling_mode_enabled || transfer_memory == 0) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | |||
| 34 | LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); | ||
| 35 | } | ||
| 36 | |||
| 37 | u8 Starlink::GetDeviceId() const { | ||
| 38 | return DEVICE_ID; | ||
| 39 | } | ||
| 40 | |||
| 41 | std::vector<u8> Starlink::GetReply() const { | ||
| 42 | return {}; | ||
| 43 | } | ||
| 44 | |||
| 45 | bool Starlink::SetCommand(std::span<const u8> data) { | ||
| 46 | LOG_ERROR(Service_HID, "Command not implemented"); | ||
| 47 | return false; | ||
| 48 | } | ||
| 49 | |||
| 50 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/starlink.h b/src/core/hle/service/hid/hidbus/starlink.h deleted file mode 100644 index a276aa88f..000000000 --- a/src/core/hle/service/hid/hidbus/starlink.h +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 8 | |||
| 9 | namespace Core::HID { | ||
| 10 | class EmulatedController; | ||
| 11 | } // namespace Core::HID | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | class Starlink final : public HidbusBase { | ||
| 16 | public: | ||
| 17 | explicit Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 18 | ~Starlink() override; | ||
| 19 | |||
| 20 | void OnInit() override; | ||
| 21 | |||
| 22 | void OnRelease() override; | ||
| 23 | |||
| 24 | // Updates ringcon transfer memory | ||
| 25 | void OnUpdate() override; | ||
| 26 | |||
| 27 | // Returns the device ID of the joycon | ||
| 28 | u8 GetDeviceId() const override; | ||
| 29 | |||
| 30 | // Assigns a command from data | ||
| 31 | bool SetCommand(std::span<const u8> data) override; | ||
| 32 | |||
| 33 | // Returns a reply from a command | ||
| 34 | std::vector<u8> GetReply() const override; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/stubbed.cpp b/src/core/hle/service/hid/hidbus/stubbed.cpp deleted file mode 100644 index 8160b7218..000000000 --- a/src/core/hle/service/hid/hidbus/stubbed.cpp +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hid/emulated_controller.h" | ||
| 5 | #include "core/hid/hid_core.h" | ||
| 6 | #include "core/hle/service/hid/hidbus/stubbed.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | constexpr u8 DEVICE_ID = 0xFF; | ||
| 10 | |||
| 11 | HidbusStubbed::HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_) | ||
| 12 | : HidbusBase(system_, service_context_) {} | ||
| 13 | HidbusStubbed::~HidbusStubbed() = default; | ||
| 14 | |||
| 15 | void HidbusStubbed::OnInit() { | ||
| 16 | return; | ||
| 17 | } | ||
| 18 | |||
| 19 | void HidbusStubbed::OnRelease() { | ||
| 20 | return; | ||
| 21 | }; | ||
| 22 | |||
| 23 | void HidbusStubbed::OnUpdate() { | ||
| 24 | if (!is_activated) { | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | if (!device_enabled) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | if (!polling_mode_enabled || transfer_memory == 0) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | |||
| 34 | LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); | ||
| 35 | } | ||
| 36 | |||
| 37 | u8 HidbusStubbed::GetDeviceId() const { | ||
| 38 | return DEVICE_ID; | ||
| 39 | } | ||
| 40 | |||
| 41 | std::vector<u8> HidbusStubbed::GetReply() const { | ||
| 42 | return {}; | ||
| 43 | } | ||
| 44 | |||
| 45 | bool HidbusStubbed::SetCommand(std::span<const u8> data) { | ||
| 46 | LOG_ERROR(Service_HID, "Command not implemented"); | ||
| 47 | return false; | ||
| 48 | } | ||
| 49 | |||
| 50 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/hidbus/stubbed.h b/src/core/hle/service/hid/hidbus/stubbed.h deleted file mode 100644 index 2e58d42fc..000000000 --- a/src/core/hle/service/hid/hidbus/stubbed.h +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hle/service/hid/hidbus/hidbus_base.h" | ||
| 8 | |||
| 9 | namespace Core::HID { | ||
| 10 | class EmulatedController; | ||
| 11 | } // namespace Core::HID | ||
| 12 | |||
| 13 | namespace Service::HID { | ||
| 14 | |||
| 15 | class HidbusStubbed final : public HidbusBase { | ||
| 16 | public: | ||
| 17 | explicit HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_); | ||
| 18 | ~HidbusStubbed() override; | ||
| 19 | |||
| 20 | void OnInit() override; | ||
| 21 | |||
| 22 | void OnRelease() override; | ||
| 23 | |||
| 24 | // Updates ringcon transfer memory | ||
| 25 | void OnUpdate() override; | ||
| 26 | |||
| 27 | // Returns the device ID of the joycon | ||
| 28 | u8 GetDeviceId() const override; | ||
| 29 | |||
| 30 | // Assigns a command from data | ||
| 31 | bool SetCommand(std::span<const u8> data) override; | ||
| 32 | |||
| 33 | // Returns a reply from a command | ||
| 34 | std::vector<u8> GetReply() const override; | ||
| 35 | }; | ||
| 36 | |||
| 37 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 05ed31273..18e544f2f 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp | |||
| @@ -6,22 +6,22 @@ | |||
| 6 | 6 | ||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/hid/emulated_controller.h" | ||
| 10 | #include "core/hid/hid_core.h" | ||
| 11 | #include "core/hle/kernel/k_shared_memory.h" | 9 | #include "core/hle/kernel/k_shared_memory.h" |
| 12 | #include "core/hle/kernel/k_transfer_memory.h" | 10 | #include "core/hle/kernel/k_transfer_memory.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/service/hid/errors.h" | ||
| 15 | #include "core/hle/service/hid/hid_util.h" | ||
| 16 | #include "core/hle/service/hid/irs.h" | 12 | #include "core/hle/service/hid/irs.h" |
| 17 | #include "core/hle/service/hid/irsensor/clustering_processor.h" | ||
| 18 | #include "core/hle/service/hid/irsensor/image_transfer_processor.h" | ||
| 19 | #include "core/hle/service/hid/irsensor/ir_led_processor.h" | ||
| 20 | #include "core/hle/service/hid/irsensor/moment_processor.h" | ||
| 21 | #include "core/hle/service/hid/irsensor/pointing_processor.h" | ||
| 22 | #include "core/hle/service/hid/irsensor/tera_plugin_processor.h" | ||
| 23 | #include "core/hle/service/ipc_helpers.h" | 13 | #include "core/hle/service/ipc_helpers.h" |
| 24 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| 15 | #include "hid_core/frontend/emulated_controller.h" | ||
| 16 | #include "hid_core/hid_core.h" | ||
| 17 | #include "hid_core/hid_result.h" | ||
| 18 | #include "hid_core/hid_util.h" | ||
| 19 | #include "hid_core/irsensor/clustering_processor.h" | ||
| 20 | #include "hid_core/irsensor/image_transfer_processor.h" | ||
| 21 | #include "hid_core/irsensor/ir_led_processor.h" | ||
| 22 | #include "hid_core/irsensor/moment_processor.h" | ||
| 23 | #include "hid_core/irsensor/pointing_processor.h" | ||
| 24 | #include "hid_core/irsensor/tera_plugin_processor.h" | ||
| 25 | 25 | ||
| 26 | namespace Service::IRS { | 26 | namespace Service::IRS { |
| 27 | 27 | ||
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index c8e6dab17..06b7279ee 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hid/hid_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | #include "hid_core/hid_types.h" | ||
| 9 | #include "hid_core/irsensor/irs_types.h" | ||
| 10 | #include "hid_core/irsensor/processor_base.h" | ||
| 11 | 11 | ||
| 12 | namespace Core::HID { | 12 | namespace Core::HID { |
| 13 | class EmulatedController; | 13 | class EmulatedController; |
diff --git a/src/core/hle/service/hid/irs_ring_lifo.h b/src/core/hle/service/hid/irs_ring_lifo.h deleted file mode 100644 index 255d1d296..000000000 --- a/src/core/hle/service/hid/irs_ring_lifo.h +++ /dev/null | |||
| @@ -1,47 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | |||
| 12 | template <typename State, std::size_t max_buffer_size> | ||
| 13 | struct Lifo { | ||
| 14 | s64 sampling_number{}; | ||
| 15 | s64 buffer_count{}; | ||
| 16 | std::array<State, max_buffer_size> entries{}; | ||
| 17 | |||
| 18 | const State& ReadCurrentEntry() const { | ||
| 19 | return entries[GetBufferTail()]; | ||
| 20 | } | ||
| 21 | |||
| 22 | const State& ReadPreviousEntry() const { | ||
| 23 | return entries[GetPreviousEntryIndex()]; | ||
| 24 | } | ||
| 25 | |||
| 26 | s64 GetBufferTail() const { | ||
| 27 | return sampling_number % max_buffer_size; | ||
| 28 | } | ||
| 29 | |||
| 30 | std::size_t GetPreviousEntryIndex() const { | ||
| 31 | return static_cast<size_t>((GetBufferTail() + max_buffer_size - 1) % max_buffer_size); | ||
| 32 | } | ||
| 33 | |||
| 34 | std::size_t GetNextEntryIndex() const { | ||
| 35 | return static_cast<size_t>((GetBufferTail() + 1) % max_buffer_size); | ||
| 36 | } | ||
| 37 | |||
| 38 | void WriteNextEntry(const State& new_state) { | ||
| 39 | if (buffer_count < static_cast<s64>(max_buffer_size)) { | ||
| 40 | buffer_count++; | ||
| 41 | } | ||
| 42 | sampling_number++; | ||
| 43 | entries[GetBufferTail()] = new_state; | ||
| 44 | } | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.cpp b/src/core/hle/service/hid/irsensor/clustering_processor.cpp deleted file mode 100644 index c559eb0d5..000000000 --- a/src/core/hle/service/hid/irsensor/clustering_processor.cpp +++ /dev/null | |||
| @@ -1,267 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <queue> | ||
| 5 | |||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/core_timing.h" | ||
| 8 | #include "core/hid/emulated_controller.h" | ||
| 9 | #include "core/hid/hid_core.h" | ||
| 10 | #include "core/hle/service/hid/irsensor/clustering_processor.h" | ||
| 11 | |||
| 12 | namespace Service::IRS { | ||
| 13 | ClusteringProcessor::ClusteringProcessor(Core::System& system_, | ||
| 14 | Core::IrSensor::DeviceFormat& device_format, | ||
| 15 | std::size_t npad_index) | ||
| 16 | : device{device_format}, system{system_} { | ||
| 17 | npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); | ||
| 18 | |||
| 19 | device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; | ||
| 20 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 21 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 22 | SetDefaultConfig(); | ||
| 23 | |||
| 24 | shared_memory = std::construct_at( | ||
| 25 | reinterpret_cast<ClusteringSharedMemory*>(&device_format.state.processor_raw_data)); | ||
| 26 | |||
| 27 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 28 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 29 | .is_npad_service = true, | ||
| 30 | }; | ||
| 31 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 32 | } | ||
| 33 | |||
| 34 | ClusteringProcessor::~ClusteringProcessor() { | ||
| 35 | npad_device->DeleteCallback(callback_key); | ||
| 36 | }; | ||
| 37 | |||
| 38 | void ClusteringProcessor::StartProcessor() { | ||
| 39 | device.camera_status = Core::IrSensor::IrCameraStatus::Available; | ||
| 40 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; | ||
| 41 | } | ||
| 42 | |||
| 43 | void ClusteringProcessor::SuspendProcessor() {} | ||
| 44 | |||
| 45 | void ClusteringProcessor::StopProcessor() {} | ||
| 46 | |||
| 47 | void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { | ||
| 48 | if (type != Core::HID::ControllerTriggerType::IrSensor) { | ||
| 49 | return; | ||
| 50 | } | ||
| 51 | |||
| 52 | next_state = {}; | ||
| 53 | const auto& camera_data = npad_device->GetCamera(); | ||
| 54 | auto filtered_image = camera_data.data; | ||
| 55 | |||
| 56 | RemoveLowIntensityData(filtered_image); | ||
| 57 | |||
| 58 | const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x); | ||
| 59 | const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y); | ||
| 60 | const auto window_end_x = | ||
| 61 | window_start_x + static_cast<std::size_t>(current_config.window_of_interest.width); | ||
| 62 | const auto window_end_y = | ||
| 63 | window_start_y + static_cast<std::size_t>(current_config.window_of_interest.height); | ||
| 64 | |||
| 65 | for (std::size_t y = window_start_y; y < window_end_y; y++) { | ||
| 66 | for (std::size_t x = window_start_x; x < window_end_x; x++) { | ||
| 67 | u8 pixel = GetPixel(filtered_image, x, y); | ||
| 68 | if (pixel == 0) { | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | const auto cluster = GetClusterProperties(filtered_image, x, y); | ||
| 72 | if (cluster.pixel_count > current_config.pixel_count_max) { | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | if (cluster.pixel_count < current_config.pixel_count_min) { | ||
| 76 | continue; | ||
| 77 | } | ||
| 78 | // Cluster object limit reached | ||
| 79 | if (next_state.object_count >= next_state.data.size()) { | ||
| 80 | continue; | ||
| 81 | } | ||
| 82 | next_state.data[next_state.object_count] = cluster; | ||
| 83 | next_state.object_count++; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | next_state.sampling_number = camera_data.sample; | ||
| 88 | next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); | ||
| 89 | next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 90 | shared_memory->clustering_lifo.WriteNextEntry(next_state); | ||
| 91 | |||
| 92 | if (!IsProcessorActive()) { | ||
| 93 | StartProcessor(); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | void ClusteringProcessor::RemoveLowIntensityData(std::vector<u8>& data) { | ||
| 98 | for (u8& pixel : data) { | ||
| 99 | if (pixel < current_config.pixel_count_min) { | ||
| 100 | pixel = 0; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | ClusteringProcessor::ClusteringData ClusteringProcessor::GetClusterProperties(std::vector<u8>& data, | ||
| 106 | std::size_t x, | ||
| 107 | std::size_t y) { | ||
| 108 | using DataPoint = Common::Point<std::size_t>; | ||
| 109 | std::queue<DataPoint> search_points{}; | ||
| 110 | ClusteringData current_cluster = GetPixelProperties(data, x, y); | ||
| 111 | SetPixel(data, x, y, 0); | ||
| 112 | search_points.emplace<DataPoint>({x, y}); | ||
| 113 | |||
| 114 | while (!search_points.empty()) { | ||
| 115 | const auto point = search_points.front(); | ||
| 116 | search_points.pop(); | ||
| 117 | |||
| 118 | // Avoid negative numbers | ||
| 119 | if (point.x == 0 || point.y == 0) { | ||
| 120 | continue; | ||
| 121 | } | ||
| 122 | |||
| 123 | std::array<DataPoint, 4> new_points{ | ||
| 124 | DataPoint{point.x - 1, point.y}, | ||
| 125 | {point.x, point.y - 1}, | ||
| 126 | {point.x + 1, point.y}, | ||
| 127 | {point.x, point.y + 1}, | ||
| 128 | }; | ||
| 129 | |||
| 130 | for (const auto new_point : new_points) { | ||
| 131 | if (new_point.x >= width) { | ||
| 132 | continue; | ||
| 133 | } | ||
| 134 | if (new_point.y >= height) { | ||
| 135 | continue; | ||
| 136 | } | ||
| 137 | if (GetPixel(data, new_point.x, new_point.y) < current_config.object_intensity_min) { | ||
| 138 | continue; | ||
| 139 | } | ||
| 140 | const ClusteringData cluster = GetPixelProperties(data, new_point.x, new_point.y); | ||
| 141 | current_cluster = MergeCluster(current_cluster, cluster); | ||
| 142 | SetPixel(data, new_point.x, new_point.y, 0); | ||
| 143 | search_points.emplace<DataPoint>({new_point.x, new_point.y}); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | return current_cluster; | ||
| 148 | } | ||
| 149 | |||
| 150 | ClusteringProcessor::ClusteringData ClusteringProcessor::GetPixelProperties( | ||
| 151 | const std::vector<u8>& data, std::size_t x, std::size_t y) const { | ||
| 152 | return { | ||
| 153 | .average_intensity = GetPixel(data, x, y) / 255.0f, | ||
| 154 | .centroid = | ||
| 155 | { | ||
| 156 | .x = static_cast<f32>(x), | ||
| 157 | .y = static_cast<f32>(y), | ||
| 158 | |||
| 159 | }, | ||
| 160 | .pixel_count = 1, | ||
| 161 | .bound = | ||
| 162 | { | ||
| 163 | .x = static_cast<s16>(x), | ||
| 164 | .y = static_cast<s16>(y), | ||
| 165 | .width = 1, | ||
| 166 | .height = 1, | ||
| 167 | }, | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | |||
| 171 | ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster( | ||
| 172 | const ClusteringData a, const ClusteringData b) const { | ||
| 173 | const f32 a_pixel_count = static_cast<f32>(a.pixel_count); | ||
| 174 | const f32 b_pixel_count = static_cast<f32>(b.pixel_count); | ||
| 175 | const f32 pixel_count = a_pixel_count + b_pixel_count; | ||
| 176 | const f32 average_intensity = | ||
| 177 | (a.average_intensity * a_pixel_count + b.average_intensity * b_pixel_count) / pixel_count; | ||
| 178 | const Core::IrSensor::IrsCentroid centroid = { | ||
| 179 | .x = (a.centroid.x * a_pixel_count + b.centroid.x * b_pixel_count) / pixel_count, | ||
| 180 | .y = (a.centroid.y * a_pixel_count + b.centroid.y * b_pixel_count) / pixel_count, | ||
| 181 | }; | ||
| 182 | s16 bound_start_x = a.bound.x < b.bound.x ? a.bound.x : b.bound.x; | ||
| 183 | s16 bound_start_y = a.bound.y < b.bound.y ? a.bound.y : b.bound.y; | ||
| 184 | s16 a_bound_end_x = a.bound.x + a.bound.width; | ||
| 185 | s16 a_bound_end_y = a.bound.y + a.bound.height; | ||
| 186 | s16 b_bound_end_x = b.bound.x + b.bound.width; | ||
| 187 | s16 b_bound_end_y = b.bound.y + b.bound.height; | ||
| 188 | |||
| 189 | const Core::IrSensor::IrsRect bound = { | ||
| 190 | .x = bound_start_x, | ||
| 191 | .y = bound_start_y, | ||
| 192 | .width = a_bound_end_x > b_bound_end_x ? static_cast<s16>(a_bound_end_x - bound_start_x) | ||
| 193 | : static_cast<s16>(b_bound_end_x - bound_start_x), | ||
| 194 | .height = a_bound_end_y > b_bound_end_y ? static_cast<s16>(a_bound_end_y - bound_start_y) | ||
| 195 | : static_cast<s16>(b_bound_end_y - bound_start_y), | ||
| 196 | }; | ||
| 197 | |||
| 198 | return { | ||
| 199 | .average_intensity = average_intensity, | ||
| 200 | .centroid = centroid, | ||
| 201 | .pixel_count = static_cast<u32>(pixel_count), | ||
| 202 | .bound = bound, | ||
| 203 | }; | ||
| 204 | } | ||
| 205 | |||
| 206 | u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { | ||
| 207 | if ((y * width) + x >= data.size()) { | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | return data[(y * width) + x]; | ||
| 211 | } | ||
| 212 | |||
| 213 | void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) { | ||
| 214 | if ((y * width) + x >= data.size()) { | ||
| 215 | return; | ||
| 216 | } | ||
| 217 | data[(y * width) + x] = value; | ||
| 218 | } | ||
| 219 | |||
| 220 | void ClusteringProcessor::SetDefaultConfig() { | ||
| 221 | using namespace std::literals::chrono_literals; | ||
| 222 | current_config.camera_config.exposure_time = std::chrono::microseconds(200ms).count(); | ||
| 223 | current_config.camera_config.gain = 2; | ||
| 224 | current_config.camera_config.is_negative_used = false; | ||
| 225 | current_config.camera_config.light_target = Core::IrSensor::CameraLightTarget::BrightLeds; | ||
| 226 | current_config.window_of_interest = { | ||
| 227 | .x = 0, | ||
| 228 | .y = 0, | ||
| 229 | .width = width, | ||
| 230 | .height = height, | ||
| 231 | }; | ||
| 232 | current_config.pixel_count_min = 3; | ||
| 233 | current_config.pixel_count_max = static_cast<u32>(GetDataSize(format)); | ||
| 234 | current_config.is_external_light_filter_enabled = true; | ||
| 235 | current_config.object_intensity_min = 150; | ||
| 236 | |||
| 237 | npad_device->SetCameraFormat(format); | ||
| 238 | } | ||
| 239 | |||
| 240 | void ClusteringProcessor::SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config) { | ||
| 241 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 242 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 243 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 244 | current_config.camera_config.light_target = | ||
| 245 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 246 | current_config.window_of_interest = config.window_of_interest; | ||
| 247 | current_config.pixel_count_min = config.pixel_count_min; | ||
| 248 | current_config.pixel_count_max = config.pixel_count_max; | ||
| 249 | current_config.is_external_light_filter_enabled = config.is_external_light_filter_enabled; | ||
| 250 | current_config.object_intensity_min = config.object_intensity_min; | ||
| 251 | |||
| 252 | LOG_INFO(Service_IRS, | ||
| 253 | "Processor config, exposure_time={}, gain={}, is_negative_used={}, " | ||
| 254 | "light_target={}, window_of_interest=({}, {}, {}, {}), pixel_count_min={}, " | ||
| 255 | "pixel_count_max={}, is_external_light_filter_enabled={}, object_intensity_min={}", | ||
| 256 | current_config.camera_config.exposure_time, current_config.camera_config.gain, | ||
| 257 | current_config.camera_config.is_negative_used, | ||
| 258 | current_config.camera_config.light_target, current_config.window_of_interest.x, | ||
| 259 | current_config.window_of_interest.y, current_config.window_of_interest.width, | ||
| 260 | current_config.window_of_interest.height, current_config.pixel_count_min, | ||
| 261 | current_config.pixel_count_max, current_config.is_external_light_filter_enabled, | ||
| 262 | current_config.object_intensity_min); | ||
| 263 | |||
| 264 | npad_device->SetCameraFormat(format); | ||
| 265 | } | ||
| 266 | |||
| 267 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.h b/src/core/hle/service/hid/irsensor/clustering_processor.h deleted file mode 100644 index 83f34734a..000000000 --- a/src/core/hle/service/hid/irsensor/clustering_processor.h +++ /dev/null | |||
| @@ -1,115 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irs_ring_lifo.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Core { | ||
| 12 | class System; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Core::HID { | ||
| 16 | class EmulatedController; | ||
| 17 | } // namespace Core::HID | ||
| 18 | |||
| 19 | namespace Service::IRS { | ||
| 20 | class ClusteringProcessor final : public ProcessorBase { | ||
| 21 | public: | ||
| 22 | explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, | ||
| 23 | std::size_t npad_index); | ||
| 24 | ~ClusteringProcessor() override; | ||
| 25 | |||
| 26 | // Called when the processor is initialized | ||
| 27 | void StartProcessor() override; | ||
| 28 | |||
| 29 | // Called when the processor is suspended | ||
| 30 | void SuspendProcessor() override; | ||
| 31 | |||
| 32 | // Called when the processor is stopped | ||
| 33 | void StopProcessor() override; | ||
| 34 | |||
| 35 | // Sets config parameters of the camera | ||
| 36 | void SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config); | ||
| 37 | |||
| 38 | private: | ||
| 39 | static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size320x240; | ||
| 40 | static constexpr std::size_t width = 320; | ||
| 41 | static constexpr std::size_t height = 240; | ||
| 42 | |||
| 43 | // This is nn::irsensor::ClusteringProcessorConfig | ||
| 44 | struct ClusteringProcessorConfig { | ||
| 45 | Core::IrSensor::CameraConfig camera_config; | ||
| 46 | Core::IrSensor::IrsRect window_of_interest; | ||
| 47 | u32 pixel_count_min; | ||
| 48 | u32 pixel_count_max; | ||
| 49 | u32 object_intensity_min; | ||
| 50 | bool is_external_light_filter_enabled; | ||
| 51 | INSERT_PADDING_BYTES(3); | ||
| 52 | }; | ||
| 53 | static_assert(sizeof(ClusteringProcessorConfig) == 0x30, | ||
| 54 | "ClusteringProcessorConfig is an invalid size"); | ||
| 55 | |||
| 56 | // This is nn::irsensor::AdaptiveClusteringProcessorConfig | ||
| 57 | struct AdaptiveClusteringProcessorConfig { | ||
| 58 | Core::IrSensor::AdaptiveClusteringMode mode; | ||
| 59 | Core::IrSensor::AdaptiveClusteringTargetDistance target_distance; | ||
| 60 | }; | ||
| 61 | static_assert(sizeof(AdaptiveClusteringProcessorConfig) == 0x8, | ||
| 62 | "AdaptiveClusteringProcessorConfig is an invalid size"); | ||
| 63 | |||
| 64 | // This is nn::irsensor::ClusteringData | ||
| 65 | struct ClusteringData { | ||
| 66 | f32 average_intensity; | ||
| 67 | Core::IrSensor::IrsCentroid centroid; | ||
| 68 | u32 pixel_count; | ||
| 69 | Core::IrSensor::IrsRect bound; | ||
| 70 | }; | ||
| 71 | static_assert(sizeof(ClusteringData) == 0x18, "ClusteringData is an invalid size"); | ||
| 72 | |||
| 73 | // This is nn::irsensor::ClusteringProcessorState | ||
| 74 | struct ClusteringProcessorState { | ||
| 75 | s64 sampling_number; | ||
| 76 | u64 timestamp; | ||
| 77 | u8 object_count; | ||
| 78 | INSERT_PADDING_BYTES(3); | ||
| 79 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 80 | std::array<ClusteringData, 0x10> data; | ||
| 81 | }; | ||
| 82 | static_assert(sizeof(ClusteringProcessorState) == 0x198, | ||
| 83 | "ClusteringProcessorState is an invalid size"); | ||
| 84 | |||
| 85 | struct ClusteringSharedMemory { | ||
| 86 | Service::IRS::Lifo<ClusteringProcessorState, 6> clustering_lifo; | ||
| 87 | static_assert(sizeof(clustering_lifo) == 0x9A0, "clustering_lifo is an invalid size"); | ||
| 88 | INSERT_PADDING_WORDS(0x11F); | ||
| 89 | }; | ||
| 90 | static_assert(sizeof(ClusteringSharedMemory) == 0xE20, | ||
| 91 | "ClusteringSharedMemory is an invalid size"); | ||
| 92 | |||
| 93 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 94 | void RemoveLowIntensityData(std::vector<u8>& data); | ||
| 95 | ClusteringData GetClusterProperties(std::vector<u8>& data, std::size_t x, std::size_t y); | ||
| 96 | ClusteringData GetPixelProperties(const std::vector<u8>& data, std::size_t x, | ||
| 97 | std::size_t y) const; | ||
| 98 | ClusteringData MergeCluster(const ClusteringData a, const ClusteringData b) const; | ||
| 99 | u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const; | ||
| 100 | void SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value); | ||
| 101 | |||
| 102 | // Sets config parameters of the camera | ||
| 103 | void SetDefaultConfig(); | ||
| 104 | |||
| 105 | ClusteringSharedMemory* shared_memory = nullptr; | ||
| 106 | ClusteringProcessorState next_state{}; | ||
| 107 | |||
| 108 | ClusteringProcessorConfig current_config{}; | ||
| 109 | Core::IrSensor::DeviceFormat& device; | ||
| 110 | Core::HID::EmulatedController* npad_device; | ||
| 111 | int callback_key{}; | ||
| 112 | |||
| 113 | Core::System& system; | ||
| 114 | }; | ||
| 115 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp deleted file mode 100644 index 22067a591..000000000 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp +++ /dev/null | |||
| @@ -1,155 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hid/emulated_controller.h" | ||
| 6 | #include "core/hid/hid_core.h" | ||
| 7 | #include "core/hle/service/hid/irsensor/image_transfer_processor.h" | ||
| 8 | #include "core/memory.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | ImageTransferProcessor::ImageTransferProcessor(Core::System& system_, | ||
| 12 | Core::IrSensor::DeviceFormat& device_format, | ||
| 13 | std::size_t npad_index) | ||
| 14 | : device{device_format}, system{system_} { | ||
| 15 | npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); | ||
| 16 | |||
| 17 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 18 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 19 | .is_npad_service = true, | ||
| 20 | }; | ||
| 21 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 22 | |||
| 23 | device.mode = Core::IrSensor::IrSensorMode::ImageTransferProcessor; | ||
| 24 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 25 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 26 | } | ||
| 27 | |||
| 28 | ImageTransferProcessor::~ImageTransferProcessor() { | ||
| 29 | npad_device->DeleteCallback(callback_key); | ||
| 30 | }; | ||
| 31 | |||
| 32 | void ImageTransferProcessor::StartProcessor() { | ||
| 33 | is_active = true; | ||
| 34 | device.camera_status = Core::IrSensor::IrCameraStatus::Available; | ||
| 35 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; | ||
| 36 | processor_state.sampling_number = 0; | ||
| 37 | processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 38 | } | ||
| 39 | |||
| 40 | void ImageTransferProcessor::SuspendProcessor() {} | ||
| 41 | |||
| 42 | void ImageTransferProcessor::StopProcessor() {} | ||
| 43 | |||
| 44 | void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { | ||
| 45 | if (type != Core::HID::ControllerTriggerType::IrSensor) { | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | if (transfer_memory == 0) { | ||
| 49 | return; | ||
| 50 | } | ||
| 51 | |||
| 52 | const auto& camera_data = npad_device->GetCamera(); | ||
| 53 | |||
| 54 | // This indicates how much ambient light is present | ||
| 55 | processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 56 | processor_state.sampling_number = camera_data.sample; | ||
| 57 | |||
| 58 | if (camera_data.format != current_config.origin_format) { | ||
| 59 | LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, | ||
| 60 | current_config.origin_format); | ||
| 61 | system.ApplicationMemory().ZeroBlock(transfer_memory, | ||
| 62 | GetDataSize(current_config.trimming_format)); | ||
| 63 | return; | ||
| 64 | } | ||
| 65 | |||
| 66 | if (current_config.origin_format > current_config.trimming_format) { | ||
| 67 | LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", | ||
| 68 | current_config.origin_format, current_config.trimming_format); | ||
| 69 | system.ApplicationMemory().ZeroBlock(transfer_memory, | ||
| 70 | GetDataSize(current_config.trimming_format)); | ||
| 71 | return; | ||
| 72 | } | ||
| 73 | |||
| 74 | std::vector<u8> window_data{}; | ||
| 75 | const auto origin_width = GetDataWidth(current_config.origin_format); | ||
| 76 | const auto origin_height = GetDataHeight(current_config.origin_format); | ||
| 77 | const auto trimming_width = GetDataWidth(current_config.trimming_format); | ||
| 78 | const auto trimming_height = GetDataHeight(current_config.trimming_format); | ||
| 79 | window_data.resize(GetDataSize(current_config.trimming_format)); | ||
| 80 | |||
| 81 | if (trimming_width + current_config.trimming_start_x > origin_width || | ||
| 82 | trimming_height + current_config.trimming_start_y > origin_height) { | ||
| 83 | LOG_WARNING(Service_IRS, | ||
| 84 | "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", | ||
| 85 | current_config.trimming_start_x, current_config.trimming_start_y, | ||
| 86 | trimming_width, trimming_height, origin_width, origin_height); | ||
| 87 | system.ApplicationMemory().ZeroBlock(transfer_memory, | ||
| 88 | GetDataSize(current_config.trimming_format)); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | for (std::size_t y = 0; y < trimming_height; y++) { | ||
| 93 | for (std::size_t x = 0; x < trimming_width; x++) { | ||
| 94 | const std::size_t window_index = (y * trimming_width) + x; | ||
| 95 | const std::size_t origin_index = | ||
| 96 | ((y + current_config.trimming_start_y) * origin_width) + x + | ||
| 97 | current_config.trimming_start_x; | ||
| 98 | window_data[window_index] = camera_data.data[origin_index]; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | system.ApplicationMemory().WriteBlock(transfer_memory, window_data.data(), | ||
| 103 | GetDataSize(current_config.trimming_format)); | ||
| 104 | |||
| 105 | if (!IsProcessorActive()) { | ||
| 106 | StartProcessor(); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | void ImageTransferProcessor::SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config) { | ||
| 111 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 112 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 113 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 114 | current_config.camera_config.light_target = | ||
| 115 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 116 | current_config.origin_format = | ||
| 117 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); | ||
| 118 | current_config.trimming_format = | ||
| 119 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); | ||
| 120 | current_config.trimming_start_x = 0; | ||
| 121 | current_config.trimming_start_y = 0; | ||
| 122 | |||
| 123 | npad_device->SetCameraFormat(current_config.origin_format); | ||
| 124 | } | ||
| 125 | |||
| 126 | void ImageTransferProcessor::SetConfig( | ||
| 127 | Core::IrSensor::PackedImageTransferProcessorExConfig config) { | ||
| 128 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 129 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 130 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 131 | current_config.camera_config.light_target = | ||
| 132 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 133 | current_config.origin_format = | ||
| 134 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.origin_format); | ||
| 135 | current_config.trimming_format = | ||
| 136 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.trimming_format); | ||
| 137 | current_config.trimming_start_x = config.trimming_start_x; | ||
| 138 | current_config.trimming_start_y = config.trimming_start_y; | ||
| 139 | |||
| 140 | npad_device->SetCameraFormat(current_config.origin_format); | ||
| 141 | } | ||
| 142 | |||
| 143 | void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { | ||
| 144 | transfer_memory = t_mem; | ||
| 145 | } | ||
| 146 | |||
| 147 | Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( | ||
| 148 | std::vector<u8>& data) const { | ||
| 149 | const auto size = GetDataSize(current_config.trimming_format); | ||
| 150 | data.resize(size); | ||
| 151 | system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size); | ||
| 152 | return processor_state; | ||
| 153 | } | ||
| 154 | |||
| 155 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.h b/src/core/hle/service/hid/irsensor/image_transfer_processor.h deleted file mode 100644 index 7f42d8453..000000000 --- a/src/core/hle/service/hid/irsensor/image_transfer_processor.h +++ /dev/null | |||
| @@ -1,77 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/typed_address.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 9 | |||
| 10 | namespace Core { | ||
| 11 | class System; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Core::HID { | ||
| 15 | class EmulatedController; | ||
| 16 | } // namespace Core::HID | ||
| 17 | |||
| 18 | namespace Service::IRS { | ||
| 19 | class ImageTransferProcessor final : public ProcessorBase { | ||
| 20 | public: | ||
| 21 | explicit ImageTransferProcessor(Core::System& system_, | ||
| 22 | Core::IrSensor::DeviceFormat& device_format, | ||
| 23 | std::size_t npad_index); | ||
| 24 | ~ImageTransferProcessor() override; | ||
| 25 | |||
| 26 | // Called when the processor is initialized | ||
| 27 | void StartProcessor() override; | ||
| 28 | |||
| 29 | // Called when the processor is suspended | ||
| 30 | void SuspendProcessor() override; | ||
| 31 | |||
| 32 | // Called when the processor is stopped | ||
| 33 | void StopProcessor() override; | ||
| 34 | |||
| 35 | // Sets config parameters of the camera | ||
| 36 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config); | ||
| 37 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); | ||
| 38 | |||
| 39 | // Transfer memory where the image data will be stored | ||
| 40 | void SetTransferMemoryAddress(Common::ProcessAddress t_mem); | ||
| 41 | |||
| 42 | Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; | ||
| 43 | |||
| 44 | private: | ||
| 45 | // This is nn::irsensor::ImageTransferProcessorConfig | ||
| 46 | struct ImageTransferProcessorConfig { | ||
| 47 | Core::IrSensor::CameraConfig camera_config; | ||
| 48 | Core::IrSensor::ImageTransferProcessorFormat format; | ||
| 49 | }; | ||
| 50 | static_assert(sizeof(ImageTransferProcessorConfig) == 0x20, | ||
| 51 | "ImageTransferProcessorConfig is an invalid size"); | ||
| 52 | |||
| 53 | // This is nn::irsensor::ImageTransferProcessorExConfig | ||
| 54 | struct ImageTransferProcessorExConfig { | ||
| 55 | Core::IrSensor::CameraConfig camera_config; | ||
| 56 | Core::IrSensor::ImageTransferProcessorFormat origin_format; | ||
| 57 | Core::IrSensor::ImageTransferProcessorFormat trimming_format; | ||
| 58 | u16 trimming_start_x; | ||
| 59 | u16 trimming_start_y; | ||
| 60 | bool is_external_light_filter_enabled; | ||
| 61 | INSERT_PADDING_BYTES(3); | ||
| 62 | }; | ||
| 63 | static_assert(sizeof(ImageTransferProcessorExConfig) == 0x28, | ||
| 64 | "ImageTransferProcessorExConfig is an invalid size"); | ||
| 65 | |||
| 66 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 67 | |||
| 68 | ImageTransferProcessorExConfig current_config{}; | ||
| 69 | Core::IrSensor::ImageTransferProcessorState processor_state{}; | ||
| 70 | Core::IrSensor::DeviceFormat& device; | ||
| 71 | Core::HID::EmulatedController* npad_device; | ||
| 72 | int callback_key{}; | ||
| 73 | |||
| 74 | Core::System& system; | ||
| 75 | Common::ProcessAddress transfer_memory{}; | ||
| 76 | }; | ||
| 77 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/ir_led_processor.cpp b/src/core/hle/service/hid/irsensor/ir_led_processor.cpp deleted file mode 100644 index 8e6dd99e4..000000000 --- a/src/core/hle/service/hid/irsensor/ir_led_processor.cpp +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/ir_led_processor.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | IrLedProcessor::IrLedProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::IrLedProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | IrLedProcessor::~IrLedProcessor() = default; | ||
| 15 | |||
| 16 | void IrLedProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void IrLedProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void IrLedProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void IrLedProcessor::SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config) { | ||
| 23 | current_config.light_target = | ||
| 24 | static_cast<Core::IrSensor::CameraLightTarget>(config.light_target); | ||
| 25 | } | ||
| 26 | |||
| 27 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/ir_led_processor.h b/src/core/hle/service/hid/irsensor/ir_led_processor.h deleted file mode 100644 index c3d8693c9..000000000 --- a/src/core/hle/service/hid/irsensor/ir_led_processor.h +++ /dev/null | |||
| @@ -1,47 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::IRS { | ||
| 12 | class IrLedProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit IrLedProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~IrLedProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::IrLedProcessorConfig | ||
| 31 | struct IrLedProcessorConfig { | ||
| 32 | Core::IrSensor::CameraLightTarget light_target; | ||
| 33 | }; | ||
| 34 | static_assert(sizeof(IrLedProcessorConfig) == 0x4, "IrLedProcessorConfig is an invalid size"); | ||
| 35 | |||
| 36 | struct IrLedProcessorState { | ||
| 37 | s64 sampling_number; | ||
| 38 | u64 timestamp; | ||
| 39 | std::array<u8, 0x8> data; | ||
| 40 | }; | ||
| 41 | static_assert(sizeof(IrLedProcessorState) == 0x18, "IrLedProcessorState is an invalid size"); | ||
| 42 | |||
| 43 | IrLedProcessorConfig current_config{}; | ||
| 44 | Core::IrSensor::DeviceFormat& device; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.cpp b/src/core/hle/service/hid/irsensor/moment_processor.cpp deleted file mode 100644 index cf045bda7..000000000 --- a/src/core/hle/service/hid/irsensor/moment_processor.cpp +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/core_timing.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/moment_processor.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30; | ||
| 12 | static constexpr std::size_t ImageWidth = 40; | ||
| 13 | static constexpr std::size_t ImageHeight = 30; | ||
| 14 | |||
| 15 | MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, | ||
| 16 | std::size_t npad_index) | ||
| 17 | : device(device_format), system{system_} { | ||
| 18 | npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); | ||
| 19 | |||
| 20 | device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; | ||
| 21 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 22 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 23 | |||
| 24 | shared_memory = std::construct_at( | ||
| 25 | reinterpret_cast<MomentSharedMemory*>(&device_format.state.processor_raw_data)); | ||
| 26 | |||
| 27 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 28 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 29 | .is_npad_service = true, | ||
| 30 | }; | ||
| 31 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 32 | } | ||
| 33 | |||
| 34 | MomentProcessor::~MomentProcessor() { | ||
| 35 | npad_device->DeleteCallback(callback_key); | ||
| 36 | }; | ||
| 37 | |||
| 38 | void MomentProcessor::StartProcessor() { | ||
| 39 | device.camera_status = Core::IrSensor::IrCameraStatus::Available; | ||
| 40 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; | ||
| 41 | } | ||
| 42 | |||
| 43 | void MomentProcessor::SuspendProcessor() {} | ||
| 44 | |||
| 45 | void MomentProcessor::StopProcessor() {} | ||
| 46 | |||
| 47 | void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { | ||
| 48 | if (type != Core::HID::ControllerTriggerType::IrSensor) { | ||
| 49 | return; | ||
| 50 | } | ||
| 51 | |||
| 52 | next_state = {}; | ||
| 53 | const auto& camera_data = npad_device->GetCamera(); | ||
| 54 | |||
| 55 | const auto window_width = static_cast<std::size_t>(current_config.window_of_interest.width); | ||
| 56 | const auto window_height = static_cast<std::size_t>(current_config.window_of_interest.height); | ||
| 57 | const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x); | ||
| 58 | const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y); | ||
| 59 | |||
| 60 | const std::size_t block_width = window_width / Columns; | ||
| 61 | const std::size_t block_height = window_height / Rows; | ||
| 62 | |||
| 63 | for (std::size_t row = 0; row < Rows; row++) { | ||
| 64 | for (std::size_t column = 0; column < Columns; column++) { | ||
| 65 | const size_t x_pos = (column * block_width) + window_start_x; | ||
| 66 | const size_t y_pos = (row * block_height) + window_start_y; | ||
| 67 | auto& statistic = next_state.statistic[column + (row * Columns)]; | ||
| 68 | statistic = GetStatistic(camera_data.data, x_pos, y_pos, block_width, block_height); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | next_state.sampling_number = camera_data.sample; | ||
| 73 | next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); | ||
| 74 | next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 75 | shared_memory->moment_lifo.WriteNextEntry(next_state); | ||
| 76 | |||
| 77 | if (!IsProcessorActive()) { | ||
| 78 | StartProcessor(); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { | ||
| 83 | if ((y * ImageWidth) + x >= data.size()) { | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | return data[(y * ImageWidth) + x]; | ||
| 87 | } | ||
| 88 | |||
| 89 | MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector<u8>& data, | ||
| 90 | std::size_t start_x, | ||
| 91 | std::size_t start_y, | ||
| 92 | std::size_t width, | ||
| 93 | std::size_t height) const { | ||
| 94 | // The actual implementation is always 320x240 | ||
| 95 | static constexpr std::size_t RealWidth = 320; | ||
| 96 | static constexpr std::size_t RealHeight = 240; | ||
| 97 | static constexpr std::size_t Threshold = 30; | ||
| 98 | MomentStatistic statistic{}; | ||
| 99 | std::size_t active_points{}; | ||
| 100 | |||
| 101 | // Sum all data points on the block that meet with the threshold | ||
| 102 | for (std::size_t y = 0; y < width; y++) { | ||
| 103 | for (std::size_t x = 0; x < height; x++) { | ||
| 104 | const size_t x_pos = x + start_x; | ||
| 105 | const size_t y_pos = y + start_y; | ||
| 106 | const auto pixel = | ||
| 107 | GetPixel(data, x_pos * ImageWidth / RealWidth, y_pos * ImageHeight / RealHeight); | ||
| 108 | |||
| 109 | if (pixel < Threshold) { | ||
| 110 | continue; | ||
| 111 | } | ||
| 112 | |||
| 113 | statistic.average_intensity += pixel; | ||
| 114 | |||
| 115 | statistic.centroid.x += static_cast<float>(x_pos); | ||
| 116 | statistic.centroid.y += static_cast<float>(y_pos); | ||
| 117 | |||
| 118 | active_points++; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | // Return an empty field if no points were available | ||
| 123 | if (active_points == 0) { | ||
| 124 | return {}; | ||
| 125 | } | ||
| 126 | |||
| 127 | // Finally calculate the actual centroid and average intensity | ||
| 128 | statistic.centroid.x /= static_cast<float>(active_points); | ||
| 129 | statistic.centroid.y /= static_cast<float>(active_points); | ||
| 130 | statistic.average_intensity /= static_cast<f32>(width * height); | ||
| 131 | |||
| 132 | return statistic; | ||
| 133 | } | ||
| 134 | |||
| 135 | void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) { | ||
| 136 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 137 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 138 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 139 | current_config.camera_config.light_target = | ||
| 140 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 141 | current_config.window_of_interest = config.window_of_interest; | ||
| 142 | current_config.preprocess = | ||
| 143 | static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); | ||
| 144 | current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; | ||
| 145 | |||
| 146 | npad_device->SetCameraFormat(format); | ||
| 147 | } | ||
| 148 | |||
| 149 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.h b/src/core/hle/service/hid/irsensor/moment_processor.h deleted file mode 100644 index 398cfbdc1..000000000 --- a/src/core/hle/service/hid/irsensor/moment_processor.h +++ /dev/null | |||
| @@ -1,91 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irs_ring_lifo.h" | ||
| 10 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Core::HID { | ||
| 17 | class EmulatedController; | ||
| 18 | } // namespace Core::HID | ||
| 19 | |||
| 20 | namespace Service::IRS { | ||
| 21 | class MomentProcessor final : public ProcessorBase { | ||
| 22 | public: | ||
| 23 | explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, | ||
| 24 | std::size_t npad_index); | ||
| 25 | ~MomentProcessor() override; | ||
| 26 | |||
| 27 | // Called when the processor is initialized | ||
| 28 | void StartProcessor() override; | ||
| 29 | |||
| 30 | // Called when the processor is suspended | ||
| 31 | void SuspendProcessor() override; | ||
| 32 | |||
| 33 | // Called when the processor is stopped | ||
| 34 | void StopProcessor() override; | ||
| 35 | |||
| 36 | // Sets config parameters of the camera | ||
| 37 | void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); | ||
| 38 | |||
| 39 | private: | ||
| 40 | static constexpr std::size_t Columns = 8; | ||
| 41 | static constexpr std::size_t Rows = 6; | ||
| 42 | |||
| 43 | // This is nn::irsensor::MomentProcessorConfig | ||
| 44 | struct MomentProcessorConfig { | ||
| 45 | Core::IrSensor::CameraConfig camera_config; | ||
| 46 | Core::IrSensor::IrsRect window_of_interest; | ||
| 47 | Core::IrSensor::MomentProcessorPreprocess preprocess; | ||
| 48 | u32 preprocess_intensity_threshold; | ||
| 49 | }; | ||
| 50 | static_assert(sizeof(MomentProcessorConfig) == 0x28, | ||
| 51 | "MomentProcessorConfig is an invalid size"); | ||
| 52 | |||
| 53 | // This is nn::irsensor::MomentStatistic | ||
| 54 | struct MomentStatistic { | ||
| 55 | f32 average_intensity; | ||
| 56 | Core::IrSensor::IrsCentroid centroid; | ||
| 57 | }; | ||
| 58 | static_assert(sizeof(MomentStatistic) == 0xC, "MomentStatistic is an invalid size"); | ||
| 59 | |||
| 60 | // This is nn::irsensor::MomentProcessorState | ||
| 61 | struct MomentProcessorState { | ||
| 62 | s64 sampling_number; | ||
| 63 | u64 timestamp; | ||
| 64 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 65 | INSERT_PADDING_BYTES(4); | ||
| 66 | std::array<MomentStatistic, Columns * Rows> statistic; | ||
| 67 | }; | ||
| 68 | static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); | ||
| 69 | |||
| 70 | struct MomentSharedMemory { | ||
| 71 | Service::IRS::Lifo<MomentProcessorState, 6> moment_lifo; | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(MomentSharedMemory) == 0xE20, "MomentSharedMemory is an invalid size"); | ||
| 74 | |||
| 75 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 76 | u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const; | ||
| 77 | MomentStatistic GetStatistic(const std::vector<u8>& data, std::size_t start_x, | ||
| 78 | std::size_t start_y, std::size_t width, std::size_t height) const; | ||
| 79 | |||
| 80 | MomentSharedMemory* shared_memory = nullptr; | ||
| 81 | MomentProcessorState next_state{}; | ||
| 82 | |||
| 83 | MomentProcessorConfig current_config{}; | ||
| 84 | Core::IrSensor::DeviceFormat& device; | ||
| 85 | Core::HID::EmulatedController* npad_device; | ||
| 86 | int callback_key{}; | ||
| 87 | |||
| 88 | Core::System& system; | ||
| 89 | }; | ||
| 90 | |||
| 91 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.cpp b/src/core/hle/service/hid/irsensor/pointing_processor.cpp deleted file mode 100644 index 929f177fc..000000000 --- a/src/core/hle/service/hid/irsensor/pointing_processor.cpp +++ /dev/null | |||
| @@ -1,26 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/pointing_processor.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | PointingProcessor::PointingProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::PointingProcessorMarker; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | PointingProcessor::~PointingProcessor() = default; | ||
| 15 | |||
| 16 | void PointingProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void PointingProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void PointingProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void PointingProcessor::SetConfig(Core::IrSensor::PackedPointingProcessorConfig config) { | ||
| 23 | current_config.window_of_interest = config.window_of_interest; | ||
| 24 | } | ||
| 25 | |||
| 26 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.h b/src/core/hle/service/hid/irsensor/pointing_processor.h deleted file mode 100644 index d63423aff..000000000 --- a/src/core/hle/service/hid/irsensor/pointing_processor.h +++ /dev/null | |||
| @@ -1,61 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 9 | |||
| 10 | namespace Service::IRS { | ||
| 11 | class PointingProcessor final : public ProcessorBase { | ||
| 12 | public: | ||
| 13 | explicit PointingProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 14 | ~PointingProcessor() override; | ||
| 15 | |||
| 16 | // Called when the processor is initialized | ||
| 17 | void StartProcessor() override; | ||
| 18 | |||
| 19 | // Called when the processor is suspended | ||
| 20 | void SuspendProcessor() override; | ||
| 21 | |||
| 22 | // Called when the processor is stopped | ||
| 23 | void StopProcessor() override; | ||
| 24 | |||
| 25 | // Sets config parameters of the camera | ||
| 26 | void SetConfig(Core::IrSensor::PackedPointingProcessorConfig config); | ||
| 27 | |||
| 28 | private: | ||
| 29 | // This is nn::irsensor::PointingProcessorConfig | ||
| 30 | struct PointingProcessorConfig { | ||
| 31 | Core::IrSensor::IrsRect window_of_interest; | ||
| 32 | }; | ||
| 33 | static_assert(sizeof(PointingProcessorConfig) == 0x8, | ||
| 34 | "PointingProcessorConfig is an invalid size"); | ||
| 35 | |||
| 36 | struct PointingProcessorMarkerData { | ||
| 37 | u8 pointing_status; | ||
| 38 | INSERT_PADDING_BYTES(3); | ||
| 39 | u32 unknown; | ||
| 40 | float unknown_float1; | ||
| 41 | float position_x; | ||
| 42 | float position_y; | ||
| 43 | float unknown_float2; | ||
| 44 | Core::IrSensor::IrsRect window_of_interest; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(PointingProcessorMarkerData) == 0x20, | ||
| 47 | "PointingProcessorMarkerData is an invalid size"); | ||
| 48 | |||
| 49 | struct PointingProcessorMarkerState { | ||
| 50 | s64 sampling_number; | ||
| 51 | u64 timestamp; | ||
| 52 | std::array<PointingProcessorMarkerData, 0x3> data; | ||
| 53 | }; | ||
| 54 | static_assert(sizeof(PointingProcessorMarkerState) == 0x70, | ||
| 55 | "PointingProcessorMarkerState is an invalid size"); | ||
| 56 | |||
| 57 | PointingProcessorConfig current_config{}; | ||
| 58 | Core::IrSensor::DeviceFormat& device; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/processor_base.cpp b/src/core/hle/service/hid/irsensor/processor_base.cpp deleted file mode 100644 index 4d43ca17a..000000000 --- a/src/core/hle/service/hid/irsensor/processor_base.cpp +++ /dev/null | |||
| @@ -1,67 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | |||
| 8 | ProcessorBase::ProcessorBase() {} | ||
| 9 | ProcessorBase::~ProcessorBase() = default; | ||
| 10 | |||
| 11 | bool ProcessorBase::IsProcessorActive() const { | ||
| 12 | return is_active; | ||
| 13 | } | ||
| 14 | |||
| 15 | std::size_t ProcessorBase::GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 16 | switch (format) { | ||
| 17 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 18 | return 320 * 240; | ||
| 19 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 20 | return 160 * 120; | ||
| 21 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 22 | return 80 * 60; | ||
| 23 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 24 | return 40 * 30; | ||
| 25 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 26 | return 20 * 15; | ||
| 27 | default: | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | std::size_t ProcessorBase::GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 33 | switch (format) { | ||
| 34 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 35 | return 320; | ||
| 36 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 37 | return 160; | ||
| 38 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 39 | return 80; | ||
| 40 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 41 | return 40; | ||
| 42 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 43 | return 20; | ||
| 44 | default: | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | std::size_t ProcessorBase::GetDataHeight( | ||
| 50 | Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 51 | switch (format) { | ||
| 52 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 53 | return 240; | ||
| 54 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 55 | return 120; | ||
| 56 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 57 | return 60; | ||
| 58 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 59 | return 30; | ||
| 60 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 61 | return 15; | ||
| 62 | default: | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/processor_base.h b/src/core/hle/service/hid/irsensor/processor_base.h deleted file mode 100644 index bc0d2977b..000000000 --- a/src/core/hle/service/hid/irsensor/processor_base.h +++ /dev/null | |||
| @@ -1,33 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | |||
| 9 | namespace Service::IRS { | ||
| 10 | class ProcessorBase { | ||
| 11 | public: | ||
| 12 | explicit ProcessorBase(); | ||
| 13 | virtual ~ProcessorBase(); | ||
| 14 | |||
| 15 | virtual void StartProcessor() = 0; | ||
| 16 | virtual void SuspendProcessor() = 0; | ||
| 17 | virtual void StopProcessor() = 0; | ||
| 18 | |||
| 19 | bool IsProcessorActive() const; | ||
| 20 | |||
| 21 | protected: | ||
| 22 | /// Returns the number of bytes the image uses | ||
| 23 | std::size_t GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 24 | |||
| 25 | /// Returns the width of the image | ||
| 26 | std::size_t GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 27 | |||
| 28 | /// Returns the height of the image | ||
| 29 | std::size_t GetDataHeight(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 30 | |||
| 31 | bool is_active{false}; | ||
| 32 | }; | ||
| 33 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp b/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp deleted file mode 100644 index e691c840a..000000000 --- a/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp +++ /dev/null | |||
| @@ -1,29 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/tera_plugin_processor.h" | ||
| 5 | |||
| 6 | namespace Service::IRS { | ||
| 7 | TeraPluginProcessor::TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::TeraPluginProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | TeraPluginProcessor::~TeraPluginProcessor() = default; | ||
| 15 | |||
| 16 | void TeraPluginProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void TeraPluginProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void TeraPluginProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void TeraPluginProcessor::SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config) { | ||
| 23 | current_config.mode = config.mode; | ||
| 24 | current_config.unknown_1 = config.unknown_1; | ||
| 25 | current_config.unknown_2 = config.unknown_2; | ||
| 26 | current_config.unknown_3 = config.unknown_3; | ||
| 27 | } | ||
| 28 | |||
| 29 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/irsensor/tera_plugin_processor.h b/src/core/hle/service/hid/irsensor/tera_plugin_processor.h deleted file mode 100644 index bbea7ed0b..000000000 --- a/src/core/hle/service/hid/irsensor/tera_plugin_processor.h +++ /dev/null | |||
| @@ -1,53 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::IRS { | ||
| 12 | class TeraPluginProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~TeraPluginProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::TeraPluginProcessorConfig | ||
| 31 | struct TeraPluginProcessorConfig { | ||
| 32 | u8 mode; | ||
| 33 | u8 unknown_1; | ||
| 34 | u8 unknown_2; | ||
| 35 | u8 unknown_3; | ||
| 36 | }; | ||
| 37 | static_assert(sizeof(TeraPluginProcessorConfig) == 0x4, | ||
| 38 | "TeraPluginProcessorConfig is an invalid size"); | ||
| 39 | |||
| 40 | struct TeraPluginProcessorState { | ||
| 41 | s64 sampling_number; | ||
| 42 | u64 timestamp; | ||
| 43 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 44 | std::array<u8, 0x12c> data; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(TeraPluginProcessorState) == 0x140, | ||
| 47 | "TeraPluginProcessorState is an invalid size"); | ||
| 48 | |||
| 49 | TeraPluginProcessorConfig current_config{}; | ||
| 50 | Core::IrSensor::DeviceFormat& device; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace Service::IRS | ||
diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp deleted file mode 100644 index 1f41e645d..000000000 --- a/src/core/hle/service/hid/resource_manager.cpp +++ /dev/null | |||
| @@ -1,362 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/core_timing.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 9 | #include "core/hle/service/hid/resource_manager.h" | ||
| 10 | #include "core/hle/service/ipc_helpers.h" | ||
| 11 | |||
| 12 | #include "core/hle/service/hid/controllers/applet_resource.h" | ||
| 13 | #include "core/hle/service/hid/controllers/capture_button.h" | ||
| 14 | #include "core/hle/service/hid/controllers/console_six_axis.h" | ||
| 15 | #include "core/hle/service/hid/controllers/debug_mouse.h" | ||
| 16 | #include "core/hle/service/hid/controllers/debug_pad.h" | ||
| 17 | #include "core/hle/service/hid/controllers/digitizer.h" | ||
| 18 | #include "core/hle/service/hid/controllers/gesture.h" | ||
| 19 | #include "core/hle/service/hid/controllers/home_button.h" | ||
| 20 | #include "core/hle/service/hid/controllers/keyboard.h" | ||
| 21 | #include "core/hle/service/hid/controllers/mouse.h" | ||
| 22 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 23 | #include "core/hle/service/hid/controllers/palma.h" | ||
| 24 | #include "core/hle/service/hid/controllers/seven_six_axis.h" | ||
| 25 | #include "core/hle/service/hid/controllers/six_axis.h" | ||
| 26 | #include "core/hle/service/hid/controllers/sleep_button.h" | ||
| 27 | #include "core/hle/service/hid/controllers/touchscreen.h" | ||
| 28 | #include "core/hle/service/hid/controllers/types/shared_memory_format.h" | ||
| 29 | #include "core/hle/service/hid/controllers/unique_pad.h" | ||
| 30 | |||
| 31 | namespace Service::HID { | ||
| 32 | |||
| 33 | // Updating period for each HID device. | ||
| 34 | // Period time is obtained by measuring the number of samples in a second on HW using a homebrew | ||
| 35 | // Correct npad_update_ns is 4ms this is overclocked to lower input lag | ||
| 36 | constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) | ||
| 37 | constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz) | ||
| 38 | constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) | ||
| 39 | constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) | ||
| 40 | |||
| 41 | ResourceManager::ResourceManager(Core::System& system_) | ||
| 42 | : system{system_}, service_context{system_, "hid"} { | ||
| 43 | applet_resource = std::make_shared<AppletResource>(system); | ||
| 44 | } | ||
| 45 | |||
| 46 | ResourceManager::~ResourceManager() = default; | ||
| 47 | |||
| 48 | void ResourceManager::Initialize() { | ||
| 49 | if (is_initialized) { | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | |||
| 53 | system.HIDCore().ReloadInputDevices(); | ||
| 54 | |||
| 55 | InitializeHidCommonSampler(); | ||
| 56 | InitializeTouchScreenSampler(); | ||
| 57 | InitializeConsoleSixAxisSampler(); | ||
| 58 | InitializeAHidSampler(); | ||
| 59 | |||
| 60 | is_initialized = true; | ||
| 61 | } | ||
| 62 | |||
| 63 | std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const { | ||
| 64 | return applet_resource; | ||
| 65 | } | ||
| 66 | |||
| 67 | std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const { | ||
| 68 | return capture_button; | ||
| 69 | } | ||
| 70 | |||
| 71 | std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const { | ||
| 72 | return console_six_axis; | ||
| 73 | } | ||
| 74 | |||
| 75 | std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const { | ||
| 76 | return debug_mouse; | ||
| 77 | } | ||
| 78 | |||
| 79 | std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const { | ||
| 80 | return debug_pad; | ||
| 81 | } | ||
| 82 | |||
| 83 | std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const { | ||
| 84 | return digitizer; | ||
| 85 | } | ||
| 86 | |||
| 87 | std::shared_ptr<Gesture> ResourceManager::GetGesture() const { | ||
| 88 | return gesture; | ||
| 89 | } | ||
| 90 | |||
| 91 | std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const { | ||
| 92 | return home_button; | ||
| 93 | } | ||
| 94 | |||
| 95 | std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const { | ||
| 96 | return keyboard; | ||
| 97 | } | ||
| 98 | |||
| 99 | std::shared_ptr<Mouse> ResourceManager::GetMouse() const { | ||
| 100 | return mouse; | ||
| 101 | } | ||
| 102 | |||
| 103 | std::shared_ptr<NPad> ResourceManager::GetNpad() const { | ||
| 104 | return npad; | ||
| 105 | } | ||
| 106 | |||
| 107 | std::shared_ptr<Palma> ResourceManager::GetPalma() const { | ||
| 108 | return palma; | ||
| 109 | } | ||
| 110 | |||
| 111 | std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const { | ||
| 112 | return seven_six_axis; | ||
| 113 | } | ||
| 114 | |||
| 115 | std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const { | ||
| 116 | return six_axis; | ||
| 117 | } | ||
| 118 | |||
| 119 | std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const { | ||
| 120 | return sleep_button; | ||
| 121 | } | ||
| 122 | |||
| 123 | std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const { | ||
| 124 | return touch_screen; | ||
| 125 | } | ||
| 126 | |||
| 127 | std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const { | ||
| 128 | return unique_pad; | ||
| 129 | } | ||
| 130 | |||
| 131 | Result ResourceManager::CreateAppletResource(u64 aruid) { | ||
| 132 | if (aruid == SystemAruid) { | ||
| 133 | const auto result = RegisterCoreAppletResource(); | ||
| 134 | if (result.IsError()) { | ||
| 135 | return result; | ||
| 136 | } | ||
| 137 | return GetNpad()->ActivateNpadResource(); | ||
| 138 | } | ||
| 139 | |||
| 140 | const auto result = CreateAppletResourceImpl(aruid); | ||
| 141 | if (result.IsError()) { | ||
| 142 | return result; | ||
| 143 | } | ||
| 144 | |||
| 145 | // Homebrew doesn't try to activate some controllers, so we activate them by default | ||
| 146 | npad->Activate(); | ||
| 147 | six_axis->Activate(); | ||
| 148 | touch_screen->Activate(); | ||
| 149 | |||
| 150 | return GetNpad()->ActivateNpadResource(aruid); | ||
| 151 | } | ||
| 152 | |||
| 153 | Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { | ||
| 154 | std::scoped_lock lock{shared_mutex}; | ||
| 155 | return applet_resource->CreateAppletResource(aruid); | ||
| 156 | } | ||
| 157 | |||
| 158 | void ResourceManager::InitializeHidCommonSampler() { | ||
| 159 | debug_pad = std::make_shared<DebugPad>(system.HIDCore()); | ||
| 160 | mouse = std::make_shared<Mouse>(system.HIDCore()); | ||
| 161 | debug_mouse = std::make_shared<DebugMouse>(system.HIDCore()); | ||
| 162 | keyboard = std::make_shared<Keyboard>(system.HIDCore()); | ||
| 163 | unique_pad = std::make_shared<UniquePad>(system.HIDCore()); | ||
| 164 | npad = std::make_shared<NPad>(system.HIDCore(), service_context); | ||
| 165 | gesture = std::make_shared<Gesture>(system.HIDCore()); | ||
| 166 | home_button = std::make_shared<HomeButton>(system.HIDCore()); | ||
| 167 | sleep_button = std::make_shared<SleepButton>(system.HIDCore()); | ||
| 168 | capture_button = std::make_shared<CaptureButton>(system.HIDCore()); | ||
| 169 | digitizer = std::make_shared<Digitizer>(system.HIDCore()); | ||
| 170 | |||
| 171 | palma = std::make_shared<Palma>(system.HIDCore(), service_context); | ||
| 172 | six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad); | ||
| 173 | |||
| 174 | debug_pad->SetAppletResource(applet_resource, &shared_mutex); | ||
| 175 | digitizer->SetAppletResource(applet_resource, &shared_mutex); | ||
| 176 | keyboard->SetAppletResource(applet_resource, &shared_mutex); | ||
| 177 | npad->SetNpadExternals(applet_resource, &shared_mutex); | ||
| 178 | six_axis->SetAppletResource(applet_resource, &shared_mutex); | ||
| 179 | mouse->SetAppletResource(applet_resource, &shared_mutex); | ||
| 180 | debug_mouse->SetAppletResource(applet_resource, &shared_mutex); | ||
| 181 | home_button->SetAppletResource(applet_resource, &shared_mutex); | ||
| 182 | sleep_button->SetAppletResource(applet_resource, &shared_mutex); | ||
| 183 | capture_button->SetAppletResource(applet_resource, &shared_mutex); | ||
| 184 | } | ||
| 185 | |||
| 186 | void ResourceManager::InitializeTouchScreenSampler() { | ||
| 187 | gesture = std::make_shared<Gesture>(system.HIDCore()); | ||
| 188 | touch_screen = std::make_shared<TouchScreen>(system.HIDCore()); | ||
| 189 | |||
| 190 | touch_screen->SetAppletResource(applet_resource, &shared_mutex); | ||
| 191 | gesture->SetAppletResource(applet_resource, &shared_mutex); | ||
| 192 | } | ||
| 193 | |||
| 194 | void ResourceManager::InitializeConsoleSixAxisSampler() { | ||
| 195 | console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore()); | ||
| 196 | seven_six_axis = std::make_shared<SevenSixAxis>(system); | ||
| 197 | |||
| 198 | console_six_axis->SetAppletResource(applet_resource, &shared_mutex); | ||
| 199 | } | ||
| 200 | |||
| 201 | void ResourceManager::InitializeAHidSampler() { | ||
| 202 | // TODO | ||
| 203 | } | ||
| 204 | |||
| 205 | Result ResourceManager::RegisterCoreAppletResource() { | ||
| 206 | std::scoped_lock lock{shared_mutex}; | ||
| 207 | return applet_resource->RegisterCoreAppletResource(); | ||
| 208 | } | ||
| 209 | |||
| 210 | Result ResourceManager::UnregisterCoreAppletResource() { | ||
| 211 | std::scoped_lock lock{shared_mutex}; | ||
| 212 | return applet_resource->UnregisterCoreAppletResource(); | ||
| 213 | } | ||
| 214 | |||
| 215 | Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) { | ||
| 216 | std::scoped_lock lock{shared_mutex}; | ||
| 217 | auto result = applet_resource->RegisterAppletResourceUserId(aruid, bool_value); | ||
| 218 | if (result.IsSuccess()) { | ||
| 219 | result = npad->RegisterAppletResourceUserId(aruid); | ||
| 220 | } | ||
| 221 | return result; | ||
| 222 | } | ||
| 223 | |||
| 224 | void ResourceManager::UnregisterAppletResourceUserId(u64 aruid) { | ||
| 225 | std::scoped_lock lock{shared_mutex}; | ||
| 226 | applet_resource->UnregisterAppletResourceUserId(aruid); | ||
| 227 | } | ||
| 228 | |||
| 229 | Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) { | ||
| 230 | std::scoped_lock lock{shared_mutex}; | ||
| 231 | return applet_resource->GetSharedMemoryHandle(out_handle, aruid); | ||
| 232 | } | ||
| 233 | |||
| 234 | void ResourceManager::FreeAppletResourceId(u64 aruid) { | ||
| 235 | std::scoped_lock lock{shared_mutex}; | ||
| 236 | applet_resource->FreeAppletResourceId(aruid); | ||
| 237 | } | ||
| 238 | |||
| 239 | void ResourceManager::EnableInput(u64 aruid, bool is_enabled) { | ||
| 240 | std::scoped_lock lock{shared_mutex}; | ||
| 241 | applet_resource->EnableInput(aruid, is_enabled); | ||
| 242 | } | ||
| 243 | |||
| 244 | void ResourceManager::EnableSixAxisSensor(u64 aruid, bool is_enabled) { | ||
| 245 | std::scoped_lock lock{shared_mutex}; | ||
| 246 | applet_resource->EnableSixAxisSensor(aruid, is_enabled); | ||
| 247 | } | ||
| 248 | |||
| 249 | void ResourceManager::EnablePadInput(u64 aruid, bool is_enabled) { | ||
| 250 | std::scoped_lock lock{shared_mutex}; | ||
| 251 | applet_resource->EnablePadInput(aruid, is_enabled); | ||
| 252 | } | ||
| 253 | |||
| 254 | void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) { | ||
| 255 | std::scoped_lock lock{shared_mutex}; | ||
| 256 | applet_resource->EnableTouchScreen(aruid, is_enabled); | ||
| 257 | } | ||
| 258 | |||
| 259 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { | ||
| 260 | auto& core_timing = system.CoreTiming(); | ||
| 261 | debug_pad->OnUpdate(core_timing); | ||
| 262 | digitizer->OnUpdate(core_timing); | ||
| 263 | unique_pad->OnUpdate(core_timing); | ||
| 264 | gesture->OnUpdate(core_timing); | ||
| 265 | touch_screen->OnUpdate(core_timing); | ||
| 266 | palma->OnUpdate(core_timing); | ||
| 267 | home_button->OnUpdate(core_timing); | ||
| 268 | sleep_button->OnUpdate(core_timing); | ||
| 269 | capture_button->OnUpdate(core_timing); | ||
| 270 | } | ||
| 271 | |||
| 272 | void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) { | ||
| 273 | auto& core_timing = system.CoreTiming(); | ||
| 274 | npad->OnUpdate(core_timing); | ||
| 275 | } | ||
| 276 | |||
| 277 | void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) { | ||
| 278 | auto& core_timing = system.CoreTiming(); | ||
| 279 | mouse->OnUpdate(core_timing); | ||
| 280 | debug_mouse->OnUpdate(core_timing); | ||
| 281 | keyboard->OnUpdate(core_timing); | ||
| 282 | } | ||
| 283 | |||
| 284 | void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) { | ||
| 285 | auto& core_timing = system.CoreTiming(); | ||
| 286 | six_axis->OnUpdate(core_timing); | ||
| 287 | seven_six_axis->OnUpdate(core_timing); | ||
| 288 | console_six_axis->OnUpdate(core_timing); | ||
| 289 | } | ||
| 290 | |||
| 291 | IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, | ||
| 292 | u64 applet_resource_user_id) | ||
| 293 | : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id}, | ||
| 294 | resource_manager{resource} { | ||
| 295 | static const FunctionInfo functions[] = { | ||
| 296 | {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, | ||
| 297 | }; | ||
| 298 | RegisterHandlers(functions); | ||
| 299 | |||
| 300 | // Register update callbacks | ||
| 301 | npad_update_event = Core::Timing::CreateEvent( | ||
| 302 | "HID::UpdatePadCallback", | ||
| 303 | [this, resource]( | ||
| 304 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 305 | const auto guard = LockService(); | ||
| 306 | resource->UpdateNpad(ns_late); | ||
| 307 | return std::nullopt; | ||
| 308 | }); | ||
| 309 | default_update_event = Core::Timing::CreateEvent( | ||
| 310 | "HID::UpdateDefaultCallback", | ||
| 311 | [this, resource]( | ||
| 312 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 313 | const auto guard = LockService(); | ||
| 314 | resource->UpdateControllers(ns_late); | ||
| 315 | return std::nullopt; | ||
| 316 | }); | ||
| 317 | mouse_keyboard_update_event = Core::Timing::CreateEvent( | ||
| 318 | "HID::UpdateMouseKeyboardCallback", | ||
| 319 | [this, resource]( | ||
| 320 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 321 | const auto guard = LockService(); | ||
| 322 | resource->UpdateMouseKeyboard(ns_late); | ||
| 323 | return std::nullopt; | ||
| 324 | }); | ||
| 325 | motion_update_event = Core::Timing::CreateEvent( | ||
| 326 | "HID::UpdateMotionCallback", | ||
| 327 | [this, resource]( | ||
| 328 | s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 329 | const auto guard = LockService(); | ||
| 330 | resource->UpdateMotion(ns_late); | ||
| 331 | return std::nullopt; | ||
| 332 | }); | ||
| 333 | |||
| 334 | system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event); | ||
| 335 | system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns, | ||
| 336 | default_update_event); | ||
| 337 | system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns, | ||
| 338 | mouse_keyboard_update_event); | ||
| 339 | system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns, | ||
| 340 | motion_update_event); | ||
| 341 | } | ||
| 342 | |||
| 343 | IAppletResource::~IAppletResource() { | ||
| 344 | system.CoreTiming().UnscheduleEvent(npad_update_event); | ||
| 345 | system.CoreTiming().UnscheduleEvent(default_update_event); | ||
| 346 | system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event); | ||
| 347 | system.CoreTiming().UnscheduleEvent(motion_update_event); | ||
| 348 | resource_manager->FreeAppletResourceId(aruid); | ||
| 349 | } | ||
| 350 | |||
| 351 | void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) { | ||
| 352 | Kernel::KSharedMemory* handle; | ||
| 353 | const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid); | ||
| 354 | |||
| 355 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw); | ||
| 356 | |||
| 357 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 358 | rb.Push(result); | ||
| 359 | rb.PushCopyObjects(handle); | ||
| 360 | } | ||
| 361 | |||
| 362 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h deleted file mode 100644 index 7a21d8eb8..000000000 --- a/src/core/hle/service/hid/resource_manager.h +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/kernel_helpers.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Core { | ||
| 10 | class System; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Core::Timing { | ||
| 14 | struct EventType; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Kernel { | ||
| 18 | class KSharedMemory; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Service::HID { | ||
| 22 | class AppletResource; | ||
| 23 | class CaptureButton; | ||
| 24 | class Controller_Stubbed; | ||
| 25 | class ConsoleSixAxis; | ||
| 26 | class DebugMouse; | ||
| 27 | class DebugPad; | ||
| 28 | class Digitizer; | ||
| 29 | class Gesture; | ||
| 30 | class HomeButton; | ||
| 31 | class Keyboard; | ||
| 32 | class Mouse; | ||
| 33 | class NPad; | ||
| 34 | class Palma; | ||
| 35 | class SevenSixAxis; | ||
| 36 | class SixAxis; | ||
| 37 | class SleepButton; | ||
| 38 | class TouchScreen; | ||
| 39 | class UniquePad; | ||
| 40 | |||
| 41 | class ResourceManager { | ||
| 42 | |||
| 43 | public: | ||
| 44 | explicit ResourceManager(Core::System& system_); | ||
| 45 | ~ResourceManager(); | ||
| 46 | |||
| 47 | void Initialize(); | ||
| 48 | |||
| 49 | std::shared_ptr<AppletResource> GetAppletResource() const; | ||
| 50 | std::shared_ptr<CaptureButton> GetCaptureButton() const; | ||
| 51 | std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const; | ||
| 52 | std::shared_ptr<DebugMouse> GetDebugMouse() const; | ||
| 53 | std::shared_ptr<DebugPad> GetDebugPad() const; | ||
| 54 | std::shared_ptr<Digitizer> GetDigitizer() const; | ||
| 55 | std::shared_ptr<Gesture> GetGesture() const; | ||
| 56 | std::shared_ptr<HomeButton> GetHomeButton() const; | ||
| 57 | std::shared_ptr<Keyboard> GetKeyboard() const; | ||
| 58 | std::shared_ptr<Mouse> GetMouse() const; | ||
| 59 | std::shared_ptr<NPad> GetNpad() const; | ||
| 60 | std::shared_ptr<Palma> GetPalma() const; | ||
| 61 | std::shared_ptr<SevenSixAxis> GetSevenSixAxis() const; | ||
| 62 | std::shared_ptr<SixAxis> GetSixAxis() const; | ||
| 63 | std::shared_ptr<SleepButton> GetSleepButton() const; | ||
| 64 | std::shared_ptr<TouchScreen> GetTouchScreen() const; | ||
| 65 | std::shared_ptr<UniquePad> GetUniquePad() const; | ||
| 66 | |||
| 67 | Result CreateAppletResource(u64 aruid); | ||
| 68 | |||
| 69 | Result RegisterCoreAppletResource(); | ||
| 70 | Result UnregisterCoreAppletResource(); | ||
| 71 | Result RegisterAppletResourceUserId(u64 aruid, bool bool_value); | ||
| 72 | void UnregisterAppletResourceUserId(u64 aruid); | ||
| 73 | |||
| 74 | Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); | ||
| 75 | void FreeAppletResourceId(u64 aruid); | ||
| 76 | |||
| 77 | void EnableInput(u64 aruid, bool is_enabled); | ||
| 78 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); | ||
| 79 | void EnablePadInput(u64 aruid, bool is_enabled); | ||
| 80 | void EnableTouchScreen(u64 aruid, bool is_enabled); | ||
| 81 | |||
| 82 | void UpdateControllers(std::chrono::nanoseconds ns_late); | ||
| 83 | void UpdateNpad(std::chrono::nanoseconds ns_late); | ||
| 84 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); | ||
| 85 | void UpdateMotion(std::chrono::nanoseconds ns_late); | ||
| 86 | |||
| 87 | private: | ||
| 88 | Result CreateAppletResourceImpl(u64 aruid); | ||
| 89 | void InitializeHidCommonSampler(); | ||
| 90 | void InitializeTouchScreenSampler(); | ||
| 91 | void InitializeConsoleSixAxisSampler(); | ||
| 92 | void InitializeAHidSampler(); | ||
| 93 | |||
| 94 | bool is_initialized{false}; | ||
| 95 | |||
| 96 | mutable std::recursive_mutex shared_mutex; | ||
| 97 | std::shared_ptr<AppletResource> applet_resource = nullptr; | ||
| 98 | |||
| 99 | std::shared_ptr<CaptureButton> capture_button = nullptr; | ||
| 100 | std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr; | ||
| 101 | std::shared_ptr<DebugMouse> debug_mouse = nullptr; | ||
| 102 | std::shared_ptr<DebugPad> debug_pad = nullptr; | ||
| 103 | std::shared_ptr<Digitizer> digitizer = nullptr; | ||
| 104 | std::shared_ptr<Gesture> gesture = nullptr; | ||
| 105 | std::shared_ptr<HomeButton> home_button = nullptr; | ||
| 106 | std::shared_ptr<Keyboard> keyboard = nullptr; | ||
| 107 | std::shared_ptr<Mouse> mouse = nullptr; | ||
| 108 | std::shared_ptr<NPad> npad = nullptr; | ||
| 109 | std::shared_ptr<Palma> palma = nullptr; | ||
| 110 | std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr; | ||
| 111 | std::shared_ptr<SixAxis> six_axis = nullptr; | ||
| 112 | std::shared_ptr<SleepButton> sleep_button = nullptr; | ||
| 113 | std::shared_ptr<TouchScreen> touch_screen = nullptr; | ||
| 114 | std::shared_ptr<UniquePad> unique_pad = nullptr; | ||
| 115 | |||
| 116 | // TODO: Create these resources | ||
| 117 | // std::shared_ptr<AudioControl> audio_control = nullptr; | ||
| 118 | // std::shared_ptr<ButtonConfig> button_config = nullptr; | ||
| 119 | // std::shared_ptr<Config> config = nullptr; | ||
| 120 | // std::shared_ptr<Connection> connection = nullptr; | ||
| 121 | // std::shared_ptr<CustomConfig> custom_config = nullptr; | ||
| 122 | // std::shared_ptr<Digitizer> digitizer = nullptr; | ||
| 123 | // std::shared_ptr<Hdls> hdls = nullptr; | ||
| 124 | // std::shared_ptr<PlayReport> play_report = nullptr; | ||
| 125 | // std::shared_ptr<Rail> rail = nullptr; | ||
| 126 | |||
| 127 | Core::System& system; | ||
| 128 | KernelHelpers::ServiceContext service_context; | ||
| 129 | }; | ||
| 130 | |||
| 131 | class IAppletResource final : public ServiceFramework<IAppletResource> { | ||
| 132 | public: | ||
| 133 | explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, | ||
| 134 | u64 applet_resource_user_id); | ||
| 135 | ~IAppletResource() override; | ||
| 136 | |||
| 137 | private: | ||
| 138 | void GetSharedMemoryHandle(HLERequestContext& ctx); | ||
| 139 | |||
| 140 | std::shared_ptr<Core::Timing::EventType> npad_update_event; | ||
| 141 | std::shared_ptr<Core::Timing::EventType> default_update_event; | ||
| 142 | std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event; | ||
| 143 | std::shared_ptr<Core::Timing::EventType> motion_update_event; | ||
| 144 | |||
| 145 | u64 aruid; | ||
| 146 | std::shared_ptr<ResourceManager> resource_manager; | ||
| 147 | }; | ||
| 148 | |||
| 149 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h deleted file mode 100644 index 0816784e0..000000000 --- a/src/core/hle/service/hid/ring_lifo.h +++ /dev/null | |||
| @@ -1,53 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | |||
| 12 | template <typename State> | ||
| 13 | struct AtomicStorage { | ||
| 14 | s64 sampling_number; | ||
| 15 | State state; | ||
| 16 | }; | ||
| 17 | |||
| 18 | template <typename State, std::size_t max_buffer_size> | ||
| 19 | struct Lifo { | ||
| 20 | s64 timestamp{}; | ||
| 21 | s64 total_buffer_count = static_cast<s64>(max_buffer_size); | ||
| 22 | s64 buffer_tail{}; | ||
| 23 | s64 buffer_count{}; | ||
| 24 | std::array<AtomicStorage<State>, max_buffer_size> entries{}; | ||
| 25 | |||
| 26 | const AtomicStorage<State>& ReadCurrentEntry() const { | ||
| 27 | return entries[buffer_tail]; | ||
| 28 | } | ||
| 29 | |||
| 30 | const AtomicStorage<State>& ReadPreviousEntry() const { | ||
| 31 | return entries[GetPreviousEntryIndex()]; | ||
| 32 | } | ||
| 33 | |||
| 34 | std::size_t GetPreviousEntryIndex() const { | ||
| 35 | return static_cast<size_t>((buffer_tail + max_buffer_size - 1) % max_buffer_size); | ||
| 36 | } | ||
| 37 | |||
| 38 | std::size_t GetNextEntryIndex() const { | ||
| 39 | return static_cast<size_t>((buffer_tail + 1) % max_buffer_size); | ||
| 40 | } | ||
| 41 | |||
| 42 | void WriteNextEntry(const State& new_state) { | ||
| 43 | if (buffer_count < static_cast<s64>(max_buffer_size) - 1) { | ||
| 44 | buffer_count++; | ||
| 45 | } | ||
| 46 | buffer_tail = GetNextEntryIndex(); | ||
| 47 | const auto& previous_entry = ReadPreviousEntry(); | ||
| 48 | entries[buffer_tail].sampling_number = previous_entry.sampling_number + 1; | ||
| 49 | entries[buffer_tail].state = new_state; | ||
| 50 | } | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index f97e5b44c..b37fb6da3 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -22,9 +22,6 @@ | |||
| 22 | #include "common/string_util.h" | 22 | #include "common/string_util.h" |
| 23 | #include "common/tiny_mt.h" | 23 | #include "common/tiny_mt.h" |
| 24 | #include "core/core.h" | 24 | #include "core/core.h" |
| 25 | #include "core/hid/emulated_controller.h" | ||
| 26 | #include "core/hid/hid_core.h" | ||
| 27 | #include "core/hid/hid_types.h" | ||
| 28 | #include "core/hle/kernel/k_event.h" | 25 | #include "core/hle/kernel/k_event.h" |
| 29 | #include "core/hle/service/ipc_helpers.h" | 26 | #include "core/hle/service/ipc_helpers.h" |
| 30 | #include "core/hle/service/mii/mii_manager.h" | 27 | #include "core/hle/service/mii/mii_manager.h" |
| @@ -33,6 +30,9 @@ | |||
| 33 | #include "core/hle/service/nfc/mifare_result.h" | 30 | #include "core/hle/service/nfc/mifare_result.h" |
| 34 | #include "core/hle/service/nfc/nfc_result.h" | 31 | #include "core/hle/service/nfc/nfc_result.h" |
| 35 | #include "core/hle/service/time/time_manager.h" | 32 | #include "core/hle/service/time/time_manager.h" |
| 33 | #include "hid_core/frontend/emulated_controller.h" | ||
| 34 | #include "hid_core/hid_core.h" | ||
| 35 | #include "hid_core/hid_types.h" | ||
| 36 | 36 | ||
| 37 | namespace Service::NFC { | 37 | namespace Service::NFC { |
| 38 | NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, | 38 | NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, |
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index ad534177d..44f651b87 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp | |||
| @@ -5,15 +5,15 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hid/hid_types.h" | ||
| 9 | #include "core/hle/kernel/k_event.h" | 8 | #include "core/hle/kernel/k_event.h" |
| 10 | #include "core/hle/service/hid/hid_util.h" | ||
| 11 | #include "core/hle/service/ipc_helpers.h" | 9 | #include "core/hle/service/ipc_helpers.h" |
| 12 | #include "core/hle/service/nfc/common/device.h" | 10 | #include "core/hle/service/nfc/common/device.h" |
| 13 | #include "core/hle/service/nfc/common/device_manager.h" | 11 | #include "core/hle/service/nfc/common/device_manager.h" |
| 14 | #include "core/hle/service/nfc/nfc_result.h" | 12 | #include "core/hle/service/nfc/nfc_result.h" |
| 15 | #include "core/hle/service/time/clock_types.h" | 13 | #include "core/hle/service/time/clock_types.h" |
| 16 | #include "core/hle/service/time/time_manager.h" | 14 | #include "core/hle/service/time/time_manager.h" |
| 15 | #include "hid_core/hid_types.h" | ||
| 16 | #include "hid_core/hid_util.h" | ||
| 17 | 17 | ||
| 18 | namespace Service::NFC { | 18 | namespace Service::NFC { |
| 19 | 19 | ||
diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h index c9f038e32..f02bdccf5 100644 --- a/src/core/hle/service/nfc/common/device_manager.h +++ b/src/core/hle/service/nfc/common/device_manager.h | |||
| @@ -8,13 +8,13 @@ | |||
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | #include <span> | 9 | #include <span> |
| 10 | 10 | ||
| 11 | #include "core/hid/hid_types.h" | ||
| 12 | #include "core/hle/service/kernel_helpers.h" | 11 | #include "core/hle/service/kernel_helpers.h" |
| 13 | #include "core/hle/service/nfc/mifare_types.h" | 12 | #include "core/hle/service/nfc/mifare_types.h" |
| 14 | #include "core/hle/service/nfc/nfc_types.h" | 13 | #include "core/hle/service/nfc/nfc_types.h" |
| 15 | #include "core/hle/service/nfp/nfp_types.h" | 14 | #include "core/hle/service/nfp/nfp_types.h" |
| 16 | #include "core/hle/service/service.h" | 15 | #include "core/hle/service/service.h" |
| 17 | #include "core/hle/service/time/clock_types.h" | 16 | #include "core/hle/service/time/clock_types.h" |
| 17 | #include "hid_core/hid_types.h" | ||
| 18 | 18 | ||
| 19 | namespace Service::NFC { | 19 | namespace Service::NFC { |
| 20 | class NfcDevice; | 20 | class NfcDevice; |
diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 179c7ba2c..a71cf74b8 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hid/hid_types.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | 6 | #include "core/hle/kernel/k_event.h" |
| 8 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "core/hle/service/nfc/common/device.h" | 8 | #include "core/hle/service/nfc/common/device.h" |
| @@ -15,6 +14,7 @@ | |||
| 15 | #include "core/hle/service/nfc/nfc_types.h" | 14 | #include "core/hle/service/nfc/nfc_types.h" |
| 16 | #include "core/hle/service/nfp/nfp_result.h" | 15 | #include "core/hle/service/nfp/nfp_result.h" |
| 17 | #include "core/hle/service/time/clock_types.h" | 16 | #include "core/hle/service/time/clock_types.h" |
| 17 | #include "hid_core/hid_types.h" | ||
| 18 | 18 | ||
| 19 | namespace Service::NFC { | 19 | namespace Service::NFC { |
| 20 | 20 | ||
diff --git a/src/core/hle/service/nfp/nfp_interface.cpp b/src/core/hle/service/nfp/nfp_interface.cpp index 34ef9d82d..5ba6d1742 100644 --- a/src/core/hle/service/nfp/nfp_interface.cpp +++ b/src/core/hle/service/nfp/nfp_interface.cpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/logging/log.h" | 4 | #include "common/logging/log.h" |
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hid/hid_types.h" | ||
| 7 | #include "core/hle/kernel/k_event.h" | 6 | #include "core/hle/kernel/k_event.h" |
| 8 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "core/hle/service/nfc/common/device.h" | 8 | #include "core/hle/service/nfc/common/device.h" |
| @@ -12,6 +11,7 @@ | |||
| 12 | #include "core/hle/service/nfp/nfp_interface.h" | 11 | #include "core/hle/service/nfp/nfp_interface.h" |
| 13 | #include "core/hle/service/nfp/nfp_result.h" | 12 | #include "core/hle/service/nfp/nfp_result.h" |
| 14 | #include "core/hle/service/nfp/nfp_types.h" | 13 | #include "core/hle/service/nfp/nfp_types.h" |
| 14 | #include "hid_core/hid_types.h" | ||
| 15 | 15 | ||
| 16 | namespace Service::NFP { | 16 | namespace Service::NFP { |
| 17 | 17 | ||
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 7bc5b5ae5..96fa7fa3a 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -9,12 +9,12 @@ | |||
| 9 | #include "core/core_timing.h" | 9 | #include "core/core_timing.h" |
| 10 | #include "core/hle/kernel/k_page_table.h" | 10 | #include "core/hle/kernel/k_page_table.h" |
| 11 | #include "core/hle/kernel/k_process.h" | 11 | #include "core/hle/kernel/k_process.h" |
| 12 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 13 | #include "core/hle/service/hid/hid_server.h" | 12 | #include "core/hle/service/hid/hid_server.h" |
| 14 | #include "core/hle/service/hid/resource_manager.h" | ||
| 15 | #include "core/hle/service/sm/sm.h" | 13 | #include "core/hle/service/sm/sm.h" |
| 16 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| 17 | #include "core/memory/cheat_engine.h" | 15 | #include "core/memory/cheat_engine.h" |
| 16 | #include "hid_core/resource_manager.h" | ||
| 17 | #include "hid_core/resources/npad/npad.h" | ||
| 18 | 18 | ||
| 19 | namespace Core::Memory { | 19 | namespace Core::Memory { |
| 20 | namespace { | 20 | namespace { |