diff options
author | Narr the Reg <juangerman-13@hotmail.com> | 2024-01-06 22:38:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-06 22:38:59 +0100 |
commit | 12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92 (patch) | |
tree | 3b95cbb74be05f0ce7a007353f1f9f95e1ed3901 /src/core | |
parent | Merge pull request #12437 from ameerj/gl-amd-fixes (diff) | |
parent | hid_core: Move hid to it's own subproject (diff) | |
download | yuzu-12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92.tar yuzu-12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92.tar.gz yuzu-12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92.tar.bz2 yuzu-12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92.tar.lz yuzu-12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92.tar.xz yuzu-12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92.tar.zst yuzu-12fd2ae86d78c69d5bce6ab5b5ba26a4b265ac92.zip |
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 frontend/framebuffer_layout.cpp frontend/framebuffer_layout.h frontend/graphics_context.h - hid/emulated_console.cpp - hid/emulated_console.h - hid/emulated_controller.cpp - hid/emulated_controller.h - hid/emulated_devices.cpp - hid/emulated_devices.h - hid/hid_core.cpp - hid/hid_core.h - hid/hid_types.h - hid/input_converter.cpp - hid/input_converter.h - hid/input_interpreter.cpp - hid/input_interpreter.h - hid/irs_types.h - hid/motion_input.cpp - hid/motion_input.h hle/api_version.h hle/ipc.h hle/kernel/board/nintendo/nx/k_memory_layout.cpp @@ -531,94 +515,16 @@ add_library(core STATIC hle/service/hid/hid.h hle/service/hid/hid_debug_server.cpp hle/service/hid/hid_debug_server.h - hle/service/hid/hid_firmware_settings.cpp - hle/service/hid/hid_firmware_settings.h hle/service/hid/hid_server.cpp hle/service/hid/hid_server.h hle/service/hid/hid_system_server.cpp hle/service/hid/hid_system_server.h - hle/service/hid/hid_util.h hle/service/hid/hidbus.cpp hle/service/hid/hidbus.h hle/service/hid/irs.cpp hle/service/hid/irs.h - hle/service/hid/irs_ring_lifo.h - hle/service/hid/resource_manager.cpp - hle/service/hid/resource_manager.h - hle/service/hid/ring_lifo.h hle/service/hid/xcd.cpp hle/service/hid/xcd.h - hle/service/hid/errors.h - hle/service/hid/controllers/npad/npad_data.cpp - hle/service/hid/controllers/npad/npad_data.h - hle/service/hid/controllers/npad/npad_resource.cpp - hle/service/hid/controllers/npad/npad_resource.h - hle/service/hid/controllers/types/debug_pad_types.h - hle/service/hid/controllers/types/keyboard_types.h - hle/service/hid/controllers/types/mouse_types.h - hle/service/hid/controllers/types/npad_types.h - hle/service/hid/controllers/types/shared_memory_format.h - hle/service/hid/controllers/types/touch_types.h - hle/service/hid/controllers/applet_resource.cpp - hle/service/hid/controllers/applet_resource.h - hle/service/hid/controllers/capture_button.cpp - hle/service/hid/controllers/capture_button.h - hle/service/hid/controllers/console_six_axis.cpp - hle/service/hid/controllers/console_six_axis.h - hle/service/hid/controllers/controller_base.cpp - hle/service/hid/controllers/controller_base.h - hle/service/hid/controllers/debug_mouse.cpp - hle/service/hid/controllers/debug_mouse.h - hle/service/hid/controllers/debug_pad.cpp - hle/service/hid/controllers/debug_pad.h - hle/service/hid/controllers/digitizer.cpp - hle/service/hid/controllers/digitizer.h - hle/service/hid/controllers/gesture.cpp - hle/service/hid/controllers/gesture.h - hle/service/hid/controllers/home_button.cpp - hle/service/hid/controllers/home_button.h - hle/service/hid/controllers/keyboard.cpp - hle/service/hid/controllers/keyboard.h - hle/service/hid/controllers/mouse.cpp - hle/service/hid/controllers/mouse.h - hle/service/hid/controllers/npad.cpp - hle/service/hid/controllers/npad.h - hle/service/hid/controllers/palma.cpp - hle/service/hid/controllers/palma.h - hle/service/hid/controllers/seven_six_axis.cpp - hle/service/hid/controllers/seven_six_axis.h - hle/service/hid/controllers/shared_memory_holder.cpp - hle/service/hid/controllers/shared_memory_holder.h - hle/service/hid/controllers/six_axis.cpp - hle/service/hid/controllers/six_axis.h - hle/service/hid/controllers/sleep_button.cpp - hle/service/hid/controllers/sleep_button.h - hle/service/hid/controllers/touchscreen.cpp - hle/service/hid/controllers/touchscreen.h - hle/service/hid/controllers/unique_pad.cpp - hle/service/hid/controllers/unique_pad.h - hle/service/hid/hidbus/hidbus_base.cpp - hle/service/hid/hidbus/hidbus_base.h - hle/service/hid/hidbus/ringcon.cpp - hle/service/hid/hidbus/ringcon.h - hle/service/hid/hidbus/starlink.cpp - hle/service/hid/hidbus/starlink.h - hle/service/hid/hidbus/stubbed.cpp - hle/service/hid/hidbus/stubbed.h - hle/service/hid/irsensor/clustering_processor.cpp - hle/service/hid/irsensor/clustering_processor.h - hle/service/hid/irsensor/image_transfer_processor.cpp - hle/service/hid/irsensor/image_transfer_processor.h - hle/service/hid/irsensor/ir_led_processor.cpp - hle/service/hid/irsensor/ir_led_processor.h - hle/service/hid/irsensor/moment_processor.cpp - hle/service/hid/irsensor/moment_processor.h - hle/service/hid/irsensor/pointing_processor.cpp - hle/service/hid/irsensor/pointing_processor.h - hle/service/hid/irsensor/processor_base.cpp - hle/service/hid/irsensor/processor_base.h - hle/service/hid/irsensor/tera_plugin_processor.cpp - hle/service/hid/irsensor/tera_plugin_processor.h hle/service/lbl/lbl.cpp hle/service/lbl/lbl.h hle/service/ldn/lan_discovery.cpp @@ -959,7 +865,7 @@ endif() create_target_directory_groups(core) -target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core nx_tzdb) +target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb) target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) if (MINGW) 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 @@ #include "core/file_sys/savedata_factory.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" -#include "core/hid/hid_core.h" #include "core/hle/kernel/k_memory_manager.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_resource_limit.h" @@ -52,6 +51,7 @@ #include "core/telemetry_session.h" #include "core/tools/freezer.h" #include "core/tools/renderdoc.h" +#include "hid_core/hid_core.h" #include "network/network.h" #include "video_core/host1x/host1x.h" #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 @@ #include "common/settings.h" #include "common/settings_enums.h" #include "core/frontend/applets/controller.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" +#include "hid_core/hid_types.h" namespace Core::Frontend { 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/settings.h" -#include "core/hid/emulated_console.h" -#include "core/hid/input_converter.h" - -namespace Core::HID { -EmulatedConsole::EmulatedConsole() = default; - -EmulatedConsole::~EmulatedConsole() = default; - -void EmulatedConsole::ReloadFromSettings() { - // Using first motion device from player 1. No need to assign any unique config at the moment - const auto& player = Settings::values.players.GetValue()[0]; - motion_params[0] = Common::ParamPackage(player.motions[0]); - - ReloadInput(); -} - -void EmulatedConsole::SetTouchParams() { - std::size_t index = 0; - - // We can't use mouse as touch if native mouse is enabled - if (!Settings::values.mouse_enabled) { - touch_params[index++] = - Common::ParamPackage{"engine:mouse,axis_x:0,axis_y:1,button:0,port:2"}; - } - - touch_params[index++] = - Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"}; - touch_params[index++] = - Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"}; - - for (int i = 0; i < static_cast<int>(MaxActiveTouchInputs); i++) { - Common::ParamPackage touchscreen_param{}; - touchscreen_param.Set("engine", "touch"); - touchscreen_param.Set("axis_x", i * 2); - touchscreen_param.Set("axis_y", (i * 2) + 1); - touchscreen_param.Set("button", i); - touch_params[index++] = std::move(touchscreen_param); - } - - if (Settings::values.touch_from_button_maps.empty()) { - LOG_WARNING(Input, "touch_from_button_maps is unset by frontend config"); - return; - } - - const auto button_index = - static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); - const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons; - - // Map the rest of the fingers from touch from button configuration - for (const auto& config_entry : touch_buttons) { - if (index >= MaxTouchDevices) { - continue; - } - Common::ParamPackage params{config_entry}; - Common::ParamPackage touch_button_params; - const int x = params.Get("x", 0); - const int y = params.Get("y", 0); - params.Erase("x"); - params.Erase("y"); - touch_button_params.Set("engine", "touch_from_button"); - touch_button_params.Set("button", params.Serialize()); - touch_button_params.Set("x", x); - touch_button_params.Set("y", y); - touch_params[index] = std::move(touch_button_params); - index++; - } -} - -void EmulatedConsole::ReloadInput() { - // If you load any device here add the equivalent to the UnloadInput() function - SetTouchParams(); - - motion_params[1] = Common::ParamPackage{"engine:virtual_gamepad,port:8,motion:0"}; - - for (std::size_t index = 0; index < motion_devices.size(); ++index) { - motion_devices[index] = Common::Input::CreateInputDevice(motion_params[index]); - if (!motion_devices[index]) { - continue; - } - motion_devices[index]->SetCallback({ - .on_change = - [this](const Common::Input::CallbackStatus& callback) { SetMotion(callback); }, - }); - } - - // Restore motion state - auto& emulated_motion = console.motion_values.emulated; - auto& motion = console.motion_state; - emulated_motion.ResetRotations(); - emulated_motion.ResetQuaternion(); - motion.accel = emulated_motion.GetAcceleration(); - motion.gyro = emulated_motion.GetGyroscope(); - motion.rotation = emulated_motion.GetRotations(); - motion.orientation = emulated_motion.GetOrientation(); - motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); - - // Unique index for identifying touch device source - std::size_t index = 0; - for (auto& touch_device : touch_devices) { - touch_device = Common::Input::CreateInputDevice(touch_params[index]); - if (!touch_device) { - continue; - } - touch_device->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetTouch(callback, index); - }, - }); - index++; - } -} - -void EmulatedConsole::UnloadInput() { - for (auto& motion : motion_devices) { - motion.reset(); - } - for (auto& touch : touch_devices) { - touch.reset(); - } -} - -void EmulatedConsole::EnableConfiguration() { - is_configuring = true; - SaveCurrentConfig(); -} - -void EmulatedConsole::DisableConfiguration() { - is_configuring = false; -} - -bool EmulatedConsole::IsConfiguring() const { - return is_configuring; -} - -void EmulatedConsole::SaveCurrentConfig() { - if (!is_configuring) { - return; - } -} - -void EmulatedConsole::RestoreConfig() { - if (!is_configuring) { - return; - } - ReloadFromSettings(); -} - -Common::ParamPackage EmulatedConsole::GetMotionParam() const { - return motion_params[0]; -} - -void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { - motion_params[0] = std::move(param); - ReloadInput(); -} - -void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { - std::unique_lock lock{mutex}; - auto& raw_status = console.motion_values.raw_status; - auto& emulated = console.motion_values.emulated; - - raw_status = TransformToMotion(callback); - emulated.SetAcceleration(Common::Vec3f{ - raw_status.accel.x.value, - raw_status.accel.y.value, - raw_status.accel.z.value, - }); - emulated.SetGyroscope(Common::Vec3f{ - raw_status.gyro.x.value, - raw_status.gyro.y.value, - raw_status.gyro.z.value, - }); - emulated.UpdateRotation(raw_status.delta_timestamp); - emulated.UpdateOrientation(raw_status.delta_timestamp); - - if (is_configuring) { - lock.unlock(); - TriggerOnChange(ConsoleTriggerType::Motion); - return; - } - - auto& motion = console.motion_state; - motion.accel = emulated.GetAcceleration(); - motion.gyro = emulated.GetGyroscope(); - motion.rotation = emulated.GetRotations(); - motion.orientation = emulated.GetOrientation(); - motion.quaternion = emulated.GetQuaternion(); - motion.gyro_bias = emulated.GetGyroBias(); - motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); - // Find what is this value - motion.verticalization_error = 0.0f; - - lock.unlock(); - TriggerOnChange(ConsoleTriggerType::Motion); -} - -void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) { - if (index >= MaxTouchDevices) { - return; - } - std::unique_lock lock{mutex}; - - const auto touch_input = TransformToTouch(callback); - auto touch_index = GetIndexFromFingerId(index); - bool is_new_input = false; - - if (!touch_index.has_value() && touch_input.pressed.value) { - touch_index = GetNextFreeIndex(); - is_new_input = true; - } - - // No free entries or invalid state. Ignore input - if (!touch_index.has_value()) { - return; - } - - auto& touch_value = console.touch_values[touch_index.value()]; - - if (is_new_input) { - touch_value.pressed.value = true; - touch_value.id = static_cast<int>(index); - } - - touch_value.x = touch_input.x; - touch_value.y = touch_input.y; - - if (!touch_input.pressed.value) { - touch_value.pressed.value = false; - } - - if (is_configuring) { - lock.unlock(); - TriggerOnChange(ConsoleTriggerType::Touch); - return; - } - - // Touch outside allowed range. Ignore input - if (touch_index.value() >= MaxActiveTouchInputs) { - return; - } - - console.touch_state[touch_index.value()] = { - .position = {touch_value.x.value, touch_value.y.value}, - .id = static_cast<u32>(touch_index.value()), - .pressed = touch_input.pressed.value, - }; - - lock.unlock(); - TriggerOnChange(ConsoleTriggerType::Touch); -} - -ConsoleMotionValues EmulatedConsole::GetMotionValues() const { - std::scoped_lock lock{mutex}; - return console.motion_values; -} - -TouchValues EmulatedConsole::GetTouchValues() const { - std::scoped_lock lock{mutex}; - return console.touch_values; -} - -ConsoleMotion EmulatedConsole::GetMotion() const { - std::scoped_lock lock{mutex}; - return console.motion_state; -} - -TouchFingerState EmulatedConsole::GetTouch() const { - std::scoped_lock lock{mutex}; - return console.touch_state; -} - -std::optional<std::size_t> EmulatedConsole::GetIndexFromFingerId(std::size_t finger_id) const { - for (std::size_t index = 0; index < MaxTouchDevices; ++index) { - const auto& finger = console.touch_values[index]; - if (!finger.pressed.value) { - continue; - } - if (finger.id == static_cast<int>(finger_id)) { - return index; - } - } - return std::nullopt; -} - -std::optional<std::size_t> EmulatedConsole::GetNextFreeIndex() const { - for (std::size_t index = 0; index < MaxTouchDevices; ++index) { - if (!console.touch_values[index].pressed.value) { - return index; - } - } - return std::nullopt; -} - -void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { - std::scoped_lock lock{callback_mutex}; - for (const auto& poller_pair : callback_list) { - const ConsoleUpdateCallback& poller = poller_pair.second; - if (poller.on_change) { - poller.on_change(type); - } - } -} - -int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { - std::scoped_lock lock{callback_mutex}; - callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); - return last_callback_key++; -} - -void EmulatedConsole::DeleteCallback(int key) { - std::scoped_lock lock{callback_mutex}; - const auto& iterator = callback_list.find(key); - if (iterator == callback_list.end()) { - LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); - return; - } - callback_list.erase(iterator); -} -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <functional> -#include <memory> -#include <mutex> -#include <optional> -#include <unordered_map> - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/input.h" -#include "common/param_package.h" -#include "common/point.h" -#include "common/quaternion.h" -#include "common/vector_math.h" -#include "core/hid/hid_types.h" -#include "core/hid/motion_input.h" - -namespace Core::HID { -static constexpr std::size_t MaxTouchDevices = 32; -static constexpr std::size_t MaxActiveTouchInputs = 16; - -struct ConsoleMotionInfo { - Common::Input::MotionStatus raw_status{}; - MotionInput emulated{}; -}; - -using ConsoleMotionDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, 2>; -using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, MaxTouchDevices>; - -using ConsoleMotionParams = std::array<Common::ParamPackage, 2>; -using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>; - -using ConsoleMotionValues = ConsoleMotionInfo; -using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>; - -// Contains all motion related data that is used on the services -struct ConsoleMotion { - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Vec3f rotation{}; - std::array<Common::Vec3f, 3> orientation{}; - Common::Quaternion<f32> quaternion{}; - Common::Vec3f gyro_bias{}; - f32 verticalization_error{}; - bool is_at_rest{}; -}; - -using TouchFingerState = std::array<TouchFinger, MaxActiveTouchInputs>; - -struct ConsoleStatus { - // Data from input_common - ConsoleMotionValues motion_values{}; - TouchValues touch_values{}; - - // Data for HID services - ConsoleMotion motion_state{}; - TouchFingerState touch_state{}; -}; - -enum class ConsoleTriggerType { - Motion, - Touch, - All, -}; - -struct ConsoleUpdateCallback { - std::function<void(ConsoleTriggerType)> on_change; -}; - -class EmulatedConsole { -public: - /** - * Contains all input data within the emulated switch console tablet such as touch and motion - */ - explicit EmulatedConsole(); - ~EmulatedConsole(); - - YUZU_NON_COPYABLE(EmulatedConsole); - YUZU_NON_MOVEABLE(EmulatedConsole); - - /// Removes all callbacks created from input devices - void UnloadInput(); - - /** - * Sets the emulated console into configuring mode - * This prevents the modification of the HID state of the emulated console by input commands - */ - void EnableConfiguration(); - - /// Returns the emulated console into normal mode, allowing the modification of the HID state - void DisableConfiguration(); - - /// Returns true if the emulated console is in configuring mode - bool IsConfiguring() const; - - /// Reload all input devices - void ReloadInput(); - - /// Overrides current mapped devices with the stored configuration and reloads all input devices - void ReloadFromSettings(); - - /// Saves the current mapped configuration - void SaveCurrentConfig(); - - /// Reverts any mapped changes made that weren't saved - void RestoreConfig(); - - // Returns the current mapped motion device - Common::ParamPackage GetMotionParam() const; - - /** - * Updates the current mapped motion device - * @param param ParamPackage with controller data to be mapped - */ - void SetMotionParam(Common::ParamPackage param); - - /// Returns the latest status of motion input from the console with parameters - ConsoleMotionValues GetMotionValues() const; - - /// Returns the latest status of touch input from the console with parameters - TouchValues GetTouchValues() const; - - /// Returns the latest status of motion input from the console - ConsoleMotion GetMotion() const; - - /// Returns the latest status of touch input from the console - TouchFingerState GetTouch() const; - - /** - * Adds a callback to the list of events - * @param update_callback A ConsoleUpdateCallback that will be triggered - * @return an unique key corresponding to the callback index in the list - */ - int SetCallback(ConsoleUpdateCallback update_callback); - - /** - * Removes a callback from the list stopping any future events to this object - * @param key Key corresponding to the callback index in the list - */ - void DeleteCallback(int key); - -private: - /// Creates and stores the touch params - void SetTouchParams(); - - /** - * Updates the motion status of the console - * @param callback A CallbackStatus containing gyro and accelerometer data - */ - void SetMotion(const Common::Input::CallbackStatus& callback); - - /** - * Updates the touch status of the console - * @param callback A CallbackStatus containing the touch position - * @param index Finger ID to be updated - */ - void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index); - - std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const; - - std::optional<std::size_t> GetNextFreeIndex() const; - - /** - * Triggers a callback that something has changed on the console status - * @param type Input type of the event to trigger - */ - void TriggerOnChange(ConsoleTriggerType type); - - bool is_configuring{false}; - f32 motion_sensitivity{0.01f}; - - ConsoleMotionParams motion_params; - TouchParams touch_params; - - ConsoleMotionDevices motion_devices; - TouchDevices touch_devices; - - mutable std::mutex mutex; - mutable std::mutex callback_mutex; - std::unordered_map<int, ConsoleUpdateCallback> callback_list; - int last_callback_key = 0; - - // Stores the current status of all console input - ConsoleStatus console; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <common/scope_exit.h> - -#include "common/polyfill_ranges.h" -#include "common/thread.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/input_converter.h" -#include "core/hle/service/hid/hid_util.h" - -namespace Core::HID { -constexpr s32 HID_JOYSTICK_MAX = 0x7fff; -constexpr s32 HID_TRIGGER_MAX = 0x7fff; -constexpr u32 TURBO_BUTTON_DELAY = 4; -// Use a common UUID for TAS and Virtual Gamepad -constexpr Common::UUID TAS_UUID = - Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; -constexpr Common::UUID VIRTUAL_UUID = - Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; - -EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {} - -EmulatedController::~EmulatedController() = default; - -NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) { - switch (type) { - case Settings::ControllerType::ProController: - return NpadStyleIndex::ProController; - case Settings::ControllerType::DualJoyconDetached: - return NpadStyleIndex::JoyconDual; - case Settings::ControllerType::LeftJoycon: - return NpadStyleIndex::JoyconLeft; - case Settings::ControllerType::RightJoycon: - return NpadStyleIndex::JoyconRight; - case Settings::ControllerType::Handheld: - return NpadStyleIndex::Handheld; - case Settings::ControllerType::GameCube: - return NpadStyleIndex::GameCube; - case Settings::ControllerType::Pokeball: - return NpadStyleIndex::Pokeball; - case Settings::ControllerType::NES: - return NpadStyleIndex::NES; - case Settings::ControllerType::SNES: - return NpadStyleIndex::SNES; - case Settings::ControllerType::N64: - return NpadStyleIndex::N64; - case Settings::ControllerType::SegaGenesis: - return NpadStyleIndex::SegaGenesis; - default: - return NpadStyleIndex::ProController; - } -} - -Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) { - switch (type) { - case NpadStyleIndex::ProController: - return Settings::ControllerType::ProController; - case NpadStyleIndex::JoyconDual: - return Settings::ControllerType::DualJoyconDetached; - case NpadStyleIndex::JoyconLeft: - return Settings::ControllerType::LeftJoycon; - case NpadStyleIndex::JoyconRight: - return Settings::ControllerType::RightJoycon; - case NpadStyleIndex::Handheld: - return Settings::ControllerType::Handheld; - case NpadStyleIndex::GameCube: - return Settings::ControllerType::GameCube; - case NpadStyleIndex::Pokeball: - return Settings::ControllerType::Pokeball; - case NpadStyleIndex::NES: - return Settings::ControllerType::NES; - case NpadStyleIndex::SNES: - return Settings::ControllerType::SNES; - case NpadStyleIndex::N64: - return Settings::ControllerType::N64; - case NpadStyleIndex::SegaGenesis: - return Settings::ControllerType::SegaGenesis; - default: - return Settings::ControllerType::ProController; - } -} - -void EmulatedController::ReloadFromSettings() { - const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); - const auto& player = Settings::values.players.GetValue()[player_index]; - - for (std::size_t index = 0; index < player.buttons.size(); ++index) { - button_params[index] = Common::ParamPackage(player.buttons[index]); - } - for (std::size_t index = 0; index < player.analogs.size(); ++index) { - stick_params[index] = Common::ParamPackage(player.analogs[index]); - } - for (std::size_t index = 0; index < player.motions.size(); ++index) { - motion_params[index] = Common::ParamPackage(player.motions[index]); - } - - controller.color_values = {}; - ReloadColorsFromSettings(); - - ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs); - - // Other or debug controller should always be a pro controller - if (npad_id_type != NpadIdType::Other) { - SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type)); - original_npad_type = npad_type; - } else { - SetNpadStyleIndex(NpadStyleIndex::ProController); - original_npad_type = npad_type; - } - - Disconnect(); - if (player.connected) { - Connect(); - } - - ReloadInput(); -} - -void EmulatedController::ReloadColorsFromSettings() { - const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); - const auto& player = Settings::values.players.GetValue()[player_index]; - - // Avoid updating colors if overridden by physical controller - if (controller.color_values[LeftIndex].body != 0 && - controller.color_values[RightIndex].body != 0) { - return; - } - - controller.colors_state.fullkey = { - .body = GetNpadColor(player.body_color_left), - .button = GetNpadColor(player.button_color_left), - }; - controller.colors_state.left = { - .body = GetNpadColor(player.body_color_left), - .button = GetNpadColor(player.button_color_left), - }; - controller.colors_state.right = { - .body = GetNpadColor(player.body_color_right), - .button = GetNpadColor(player.button_color_right), - }; -} - -void EmulatedController::LoadDevices() { - // TODO(german77): Use more buttons to detect the correct device - const auto left_joycon = button_params[Settings::NativeButton::DRight]; - const auto right_joycon = button_params[Settings::NativeButton::A]; - - // Triggers for GC controllers - trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; - trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR]; - - color_params[LeftIndex] = left_joycon; - color_params[RightIndex] = right_joycon; - color_params[LeftIndex].Set("color", true); - color_params[RightIndex].Set("color", true); - - battery_params[LeftIndex] = left_joycon; - battery_params[RightIndex] = right_joycon; - battery_params[LeftIndex].Set("battery", true); - battery_params[RightIndex].Set("battery", true); - - camera_params[0] = right_joycon; - camera_params[0].Set("camera", true); - nfc_params[1] = right_joycon; - nfc_params[1].Set("nfc", true); - - // Only map virtual devices to the first controller - if (npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld) { - camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"}; - ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; - nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; - } - - output_params[LeftIndex] = left_joycon; - output_params[RightIndex] = right_joycon; - output_params[2] = camera_params[1]; - output_params[3] = nfc_params[0]; - output_params[LeftIndex].Set("output", true); - output_params[RightIndex].Set("output", true); - output_params[2].Set("output", true); - output_params[3].Set("output", true); - - LoadTASParams(); - LoadVirtualGamepadParams(); - - std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice); - std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice); - std::ranges::transform(motion_params, motion_devices.begin(), Common::Input::CreateInputDevice); - std::ranges::transform(trigger_params, trigger_devices.begin(), - Common::Input::CreateInputDevice); - std::ranges::transform(battery_params, battery_devices.begin(), - Common::Input::CreateInputDevice); - std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice); - std::ranges::transform(camera_params, camera_devices.begin(), Common::Input::CreateInputDevice); - std::ranges::transform(ring_params, ring_analog_devices.begin(), - Common::Input::CreateInputDevice); - std::ranges::transform(nfc_params, nfc_devices.begin(), Common::Input::CreateInputDevice); - std::ranges::transform(output_params, output_devices.begin(), - Common::Input::CreateOutputDevice); - - // Initialize TAS devices - std::ranges::transform(tas_button_params, tas_button_devices.begin(), - Common::Input::CreateInputDevice); - std::ranges::transform(tas_stick_params, tas_stick_devices.begin(), - Common::Input::CreateInputDevice); - - // Initialize virtual gamepad devices - std::ranges::transform(virtual_button_params, virtual_button_devices.begin(), - Common::Input::CreateInputDevice); - std::ranges::transform(virtual_stick_params, virtual_stick_devices.begin(), - Common::Input::CreateInputDevice); - std::ranges::transform(virtual_motion_params, virtual_motion_devices.begin(), - Common::Input::CreateInputDevice); -} - -void EmulatedController::LoadTASParams() { - const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); - Common::ParamPackage common_params{}; - common_params.Set("engine", "tas"); - common_params.Set("port", static_cast<int>(player_index)); - for (auto& param : tas_button_params) { - param = common_params; - } - for (auto& param : tas_stick_params) { - param = common_params; - } - - // TODO(german77): Replace this with an input profile or something better - tas_button_params[Settings::NativeButton::A].Set("button", 0); - tas_button_params[Settings::NativeButton::B].Set("button", 1); - tas_button_params[Settings::NativeButton::X].Set("button", 2); - tas_button_params[Settings::NativeButton::Y].Set("button", 3); - tas_button_params[Settings::NativeButton::LStick].Set("button", 4); - tas_button_params[Settings::NativeButton::RStick].Set("button", 5); - tas_button_params[Settings::NativeButton::L].Set("button", 6); - tas_button_params[Settings::NativeButton::R].Set("button", 7); - tas_button_params[Settings::NativeButton::ZL].Set("button", 8); - tas_button_params[Settings::NativeButton::ZR].Set("button", 9); - tas_button_params[Settings::NativeButton::Plus].Set("button", 10); - tas_button_params[Settings::NativeButton::Minus].Set("button", 11); - tas_button_params[Settings::NativeButton::DLeft].Set("button", 12); - tas_button_params[Settings::NativeButton::DUp].Set("button", 13); - tas_button_params[Settings::NativeButton::DRight].Set("button", 14); - tas_button_params[Settings::NativeButton::DDown].Set("button", 15); - tas_button_params[Settings::NativeButton::SLLeft].Set("button", 16); - tas_button_params[Settings::NativeButton::SRLeft].Set("button", 17); - tas_button_params[Settings::NativeButton::Home].Set("button", 18); - tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19); - tas_button_params[Settings::NativeButton::SLRight].Set("button", 20); - tas_button_params[Settings::NativeButton::SRRight].Set("button", 21); - - tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); - tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); - tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2); - tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); - - // set to optimal stick to avoid sanitizing the stick and tweaking the coordinates - // making sure they play back in the game as originally written down in the script file - tas_stick_params[Settings::NativeAnalog::LStick].Set("deadzone", 0.0f); - tas_stick_params[Settings::NativeAnalog::LStick].Set("range", 1.0f); - tas_stick_params[Settings::NativeAnalog::RStick].Set("deadzone", 0.0f); - tas_stick_params[Settings::NativeAnalog::RStick].Set("range", 1.0f); -} - -void EmulatedController::LoadVirtualGamepadParams() { - const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); - Common::ParamPackage common_params{}; - common_params.Set("engine", "virtual_gamepad"); - common_params.Set("port", static_cast<int>(player_index)); - for (auto& param : virtual_button_params) { - param = common_params; - } - for (auto& param : virtual_stick_params) { - param = common_params; - } - for (auto& param : virtual_stick_params) { - param = common_params; - } - for (auto& param : virtual_motion_params) { - param = common_params; - } - - // TODO(german77): Replace this with an input profile or something better - virtual_button_params[Settings::NativeButton::A].Set("button", 0); - virtual_button_params[Settings::NativeButton::B].Set("button", 1); - virtual_button_params[Settings::NativeButton::X].Set("button", 2); - virtual_button_params[Settings::NativeButton::Y].Set("button", 3); - virtual_button_params[Settings::NativeButton::LStick].Set("button", 4); - virtual_button_params[Settings::NativeButton::RStick].Set("button", 5); - virtual_button_params[Settings::NativeButton::L].Set("button", 6); - virtual_button_params[Settings::NativeButton::R].Set("button", 7); - virtual_button_params[Settings::NativeButton::ZL].Set("button", 8); - virtual_button_params[Settings::NativeButton::ZR].Set("button", 9); - virtual_button_params[Settings::NativeButton::Plus].Set("button", 10); - virtual_button_params[Settings::NativeButton::Minus].Set("button", 11); - virtual_button_params[Settings::NativeButton::DLeft].Set("button", 12); - virtual_button_params[Settings::NativeButton::DUp].Set("button", 13); - virtual_button_params[Settings::NativeButton::DRight].Set("button", 14); - virtual_button_params[Settings::NativeButton::DDown].Set("button", 15); - virtual_button_params[Settings::NativeButton::SLLeft].Set("button", 16); - virtual_button_params[Settings::NativeButton::SRLeft].Set("button", 17); - virtual_button_params[Settings::NativeButton::Home].Set("button", 18); - virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19); - virtual_button_params[Settings::NativeButton::SLRight].Set("button", 20); - virtual_button_params[Settings::NativeButton::SRRight].Set("button", 21); - - virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0); - virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1); - virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2); - virtual_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3); - virtual_stick_params[Settings::NativeAnalog::LStick].Set("deadzone", 0.0f); - virtual_stick_params[Settings::NativeAnalog::LStick].Set("range", 1.0f); - virtual_stick_params[Settings::NativeAnalog::RStick].Set("deadzone", 0.0f); - virtual_stick_params[Settings::NativeAnalog::RStick].Set("range", 1.0f); - - virtual_motion_params[Settings::NativeMotion::MotionLeft].Set("motion", 0); - virtual_motion_params[Settings::NativeMotion::MotionRight].Set("motion", 0); -} - -void EmulatedController::ReloadInput() { - // If you load any device here add the equivalent to the UnloadInput() function - LoadDevices(); - for (std::size_t index = 0; index < button_devices.size(); ++index) { - if (!button_devices[index]) { - continue; - } - const auto uuid = Common::UUID{button_params[index].Get("guid", "")}; - button_devices[index]->SetCallback({ - .on_change = - [this, index, uuid](const Common::Input::CallbackStatus& callback) { - SetButton(callback, index, uuid); - }, - }); - button_devices[index]->ForceUpdate(); - } - - for (std::size_t index = 0; index < stick_devices.size(); ++index) { - if (!stick_devices[index]) { - continue; - } - const auto uuid = Common::UUID{stick_params[index].Get("guid", "")}; - stick_devices[index]->SetCallback({ - .on_change = - [this, index, uuid](const Common::Input::CallbackStatus& callback) { - SetStick(callback, index, uuid); - }, - }); - stick_devices[index]->ForceUpdate(); - } - - for (std::size_t index = 0; index < trigger_devices.size(); ++index) { - if (!trigger_devices[index]) { - continue; - } - const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")}; - trigger_devices[index]->SetCallback({ - .on_change = - [this, index, uuid](const Common::Input::CallbackStatus& callback) { - SetTrigger(callback, index, uuid); - }, - }); - trigger_devices[index]->ForceUpdate(); - } - - for (std::size_t index = 0; index < battery_devices.size(); ++index) { - if (!battery_devices[index]) { - continue; - } - battery_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetBattery(callback, index); - }, - }); - battery_devices[index]->ForceUpdate(); - } - - for (std::size_t index = 0; index < color_devices.size(); ++index) { - if (!color_devices[index]) { - continue; - } - color_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetColors(callback, index); - }, - }); - color_devices[index]->ForceUpdate(); - } - - for (std::size_t index = 0; index < motion_devices.size(); ++index) { - if (!motion_devices[index]) { - continue; - } - motion_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetMotion(callback, index); - }, - }); - - // Restore motion state - auto& emulated_motion = controller.motion_values[index].emulated; - auto& motion = controller.motion_state[index]; - emulated_motion.ResetRotations(); - emulated_motion.ResetQuaternion(); - motion.accel = emulated_motion.GetAcceleration(); - motion.gyro = emulated_motion.GetGyroscope(); - motion.rotation = emulated_motion.GetRotations(); - motion.euler = emulated_motion.GetEulerAngles(); - motion.orientation = emulated_motion.GetOrientation(); - motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); - } - - for (std::size_t index = 0; index < camera_devices.size(); ++index) { - if (!camera_devices[index]) { - continue; - } - camera_devices[index]->SetCallback({ - .on_change = - [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); }, - }); - camera_devices[index]->ForceUpdate(); - } - - for (std::size_t index = 0; index < ring_analog_devices.size(); ++index) { - if (!ring_analog_devices[index]) { - continue; - } - ring_analog_devices[index]->SetCallback({ - .on_change = - [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); }, - }); - ring_analog_devices[index]->ForceUpdate(); - } - - for (std::size_t index = 0; index < nfc_devices.size(); ++index) { - if (!nfc_devices[index]) { - continue; - } - nfc_devices[index]->SetCallback({ - .on_change = - [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); }, - }); - nfc_devices[index]->ForceUpdate(); - } - - // Register TAS devices. No need to force update - for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { - if (!tas_button_devices[index]) { - continue; - } - tas_button_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetButton(callback, index, TAS_UUID); - }, - }); - } - - for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) { - if (!tas_stick_devices[index]) { - continue; - } - tas_stick_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetStick(callback, index, TAS_UUID); - }, - }); - } - - // Register virtual devices. No need to force update - for (std::size_t index = 0; index < virtual_button_devices.size(); ++index) { - if (!virtual_button_devices[index]) { - continue; - } - virtual_button_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetButton(callback, index, VIRTUAL_UUID); - }, - }); - } - - for (std::size_t index = 0; index < virtual_stick_devices.size(); ++index) { - if (!virtual_stick_devices[index]) { - continue; - } - virtual_stick_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetStick(callback, index, VIRTUAL_UUID); - }, - }); - } - - for (std::size_t index = 0; index < virtual_motion_devices.size(); ++index) { - if (!virtual_motion_devices[index]) { - continue; - } - virtual_motion_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetMotion(callback, index); - }, - }); - } - turbo_button_state = 0; - is_initalized = true; -} - -void EmulatedController::UnloadInput() { - is_initalized = false; - for (auto& button : button_devices) { - button.reset(); - } - for (auto& stick : stick_devices) { - stick.reset(); - } - for (auto& motion : motion_devices) { - motion.reset(); - } - for (auto& trigger : trigger_devices) { - trigger.reset(); - } - for (auto& battery : battery_devices) { - battery.reset(); - } - for (auto& color : color_devices) { - color.reset(); - } - for (auto& output : output_devices) { - output.reset(); - } - for (auto& button : tas_button_devices) { - button.reset(); - } - for (auto& stick : tas_stick_devices) { - stick.reset(); - } - for (auto& button : virtual_button_devices) { - button.reset(); - } - for (auto& stick : virtual_stick_devices) { - stick.reset(); - } - for (auto& motion : virtual_motion_devices) { - motion.reset(); - } - for (auto& camera : camera_devices) { - camera.reset(); - } - for (auto& ring : ring_analog_devices) { - ring.reset(); - } - for (auto& nfc : nfc_devices) { - nfc.reset(); - } -} - -void EmulatedController::EnableConfiguration() { - std::scoped_lock lock{connect_mutex, npad_mutex}; - is_configuring = true; - tmp_is_connected = is_connected; - tmp_npad_type = npad_type; -} - -void EmulatedController::DisableConfiguration() { - is_configuring = false; - - // Get Joycon colors before turning on the controller - for (const auto& color_device : color_devices) { - color_device->ForceUpdate(); - } - - // Apply temporary npad type to the real controller - if (tmp_npad_type != npad_type) { - if (is_connected) { - Disconnect(); - } - SetNpadStyleIndex(tmp_npad_type); - original_npad_type = tmp_npad_type; - } - - // Apply temporary connected status to the real controller - if (tmp_is_connected != is_connected) { - if (tmp_is_connected) { - Connect(); - return; - } - Disconnect(); - } -} - -void EmulatedController::EnableSystemButtons() { - std::scoped_lock lock{mutex}; - system_buttons_enabled = true; -} - -void EmulatedController::DisableSystemButtons() { - std::scoped_lock lock{mutex}; - system_buttons_enabled = false; - controller.home_button_state.raw = 0; - controller.capture_button_state.raw = 0; -} - -void EmulatedController::ResetSystemButtons() { - std::scoped_lock lock{mutex}; - controller.home_button_state.home.Assign(false); - controller.capture_button_state.capture.Assign(false); -} - -bool EmulatedController::IsConfiguring() const { - return is_configuring; -} - -void EmulatedController::SaveCurrentConfig() { - const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); - auto& player = Settings::values.players.GetValue()[player_index]; - player.connected = is_connected; - player.controller_type = MapNPadToSettingsType(npad_type); - for (std::size_t index = 0; index < player.buttons.size(); ++index) { - player.buttons[index] = button_params[index].Serialize(); - } - for (std::size_t index = 0; index < player.analogs.size(); ++index) { - player.analogs[index] = stick_params[index].Serialize(); - } - for (std::size_t index = 0; index < player.motions.size(); ++index) { - player.motions[index] = motion_params[index].Serialize(); - } - if (npad_id_type == NpadIdType::Player1) { - Settings::values.ringcon_analogs = ring_params[0].Serialize(); - } -} - -void EmulatedController::RestoreConfig() { - if (!is_configuring) { - return; - } - ReloadFromSettings(); -} - -std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const { - std::vector<Common::ParamPackage> devices; - for (const auto& param : button_params) { - if (!param.Has("engine")) { - continue; - } - const auto devices_it = std::find_if( - devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) { - return param.Get("engine", "") == param_.Get("engine", "") && - param.Get("guid", "") == param_.Get("guid", "") && - param.Get("port", 0) == param_.Get("port", 0) && - param.Get("pad", 0) == param_.Get("pad", 0); - }); - if (devices_it != devices.end()) { - continue; - } - - auto& device = devices.emplace_back(); - device.Set("engine", param.Get("engine", "")); - device.Set("guid", param.Get("guid", "")); - device.Set("port", param.Get("port", 0)); - device.Set("pad", param.Get("pad", 0)); - } - - for (const auto& param : stick_params) { - if (!param.Has("engine")) { - continue; - } - if (param.Get("engine", "") == "analog_from_button") { - continue; - } - const auto devices_it = std::find_if( - devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) { - return param.Get("engine", "") == param_.Get("engine", "") && - param.Get("guid", "") == param_.Get("guid", "") && - param.Get("port", 0) == param_.Get("port", 0) && - param.Get("pad", 0) == param_.Get("pad", 0); - }); - if (devices_it != devices.end()) { - continue; - } - - auto& device = devices.emplace_back(); - device.Set("engine", param.Get("engine", "")); - device.Set("guid", param.Get("guid", "")); - device.Set("port", param.Get("port", 0)); - device.Set("pad", param.Get("pad", 0)); - } - return devices; -} - -Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const { - if (index >= button_params.size()) { - return {}; - } - return button_params[index]; -} - -Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const { - if (index >= stick_params.size()) { - return {}; - } - return stick_params[index]; -} - -Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const { - if (index >= motion_params.size()) { - return {}; - } - return motion_params[index]; -} - -void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) { - if (index >= button_params.size()) { - return; - } - button_params[index] = std::move(param); - ReloadInput(); -} - -void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) { - if (index >= stick_params.size()) { - return; - } - stick_params[index] = std::move(param); - ReloadInput(); -} - -void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) { - if (index >= motion_params.size()) { - return; - } - motion_params[index] = std::move(param); - ReloadInput(); -} - -void EmulatedController::StartMotionCalibration() { - for (ControllerMotionInfo& motion : controller.motion_values) { - motion.emulated.Calibrate(); - } -} - -void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, - Common::UUID uuid) { - if (index >= controller.button_values.size()) { - return; - } - std::unique_lock lock{mutex}; - bool value_changed = false; - const auto new_status = TransformToButton(callback); - auto& current_status = controller.button_values[index]; - - // Only read button values that have the same uuid or are pressed once - if (current_status.uuid != uuid) { - if (!new_status.value) { - return; - } - } - - current_status.toggle = new_status.toggle; - current_status.turbo = new_status.turbo; - current_status.uuid = uuid; - - // Update button status with current - if (!current_status.toggle) { - current_status.locked = false; - if (current_status.value != new_status.value) { - current_status.value = new_status.value; - value_changed = true; - } - } else { - // Toggle button and lock status - if (new_status.value && !current_status.locked) { - current_status.locked = true; - current_status.value = !current_status.value; - value_changed = true; - } - - // Unlock button ready for next press - if (!new_status.value && current_status.locked) { - current_status.locked = false; - } - } - - if (!value_changed) { - return; - } - - if (is_configuring) { - controller.npad_button_state.raw = NpadButton::None; - controller.debug_pad_button_state.raw = 0; - controller.home_button_state.raw = 0; - controller.capture_button_state.raw = 0; - lock.unlock(); - TriggerOnChange(ControllerTriggerType::Button, false); - return; - } - - // GC controllers have triggers not buttons - if (npad_type == NpadStyleIndex::GameCube) { - if (index == Settings::NativeButton::ZR) { - return; - } - if (index == Settings::NativeButton::ZL) { - return; - } - } - - switch (index) { - case Settings::NativeButton::A: - controller.npad_button_state.a.Assign(current_status.value); - controller.debug_pad_button_state.a.Assign(current_status.value); - break; - case Settings::NativeButton::B: - controller.npad_button_state.b.Assign(current_status.value); - controller.debug_pad_button_state.b.Assign(current_status.value); - break; - case Settings::NativeButton::X: - controller.npad_button_state.x.Assign(current_status.value); - controller.debug_pad_button_state.x.Assign(current_status.value); - break; - case Settings::NativeButton::Y: - controller.npad_button_state.y.Assign(current_status.value); - controller.debug_pad_button_state.y.Assign(current_status.value); - break; - case Settings::NativeButton::LStick: - controller.npad_button_state.stick_l.Assign(current_status.value); - break; - case Settings::NativeButton::RStick: - controller.npad_button_state.stick_r.Assign(current_status.value); - break; - case Settings::NativeButton::L: - controller.npad_button_state.l.Assign(current_status.value); - controller.debug_pad_button_state.l.Assign(current_status.value); - break; - case Settings::NativeButton::R: - controller.npad_button_state.r.Assign(current_status.value); - controller.debug_pad_button_state.r.Assign(current_status.value); - break; - case Settings::NativeButton::ZL: - controller.npad_button_state.zl.Assign(current_status.value); - controller.debug_pad_button_state.zl.Assign(current_status.value); - break; - case Settings::NativeButton::ZR: - controller.npad_button_state.zr.Assign(current_status.value); - controller.debug_pad_button_state.zr.Assign(current_status.value); - break; - case Settings::NativeButton::Plus: - controller.npad_button_state.plus.Assign(current_status.value); - controller.debug_pad_button_state.plus.Assign(current_status.value); - break; - case Settings::NativeButton::Minus: - controller.npad_button_state.minus.Assign(current_status.value); - controller.debug_pad_button_state.minus.Assign(current_status.value); - break; - case Settings::NativeButton::DLeft: - controller.npad_button_state.left.Assign(current_status.value); - controller.debug_pad_button_state.d_left.Assign(current_status.value); - break; - case Settings::NativeButton::DUp: - controller.npad_button_state.up.Assign(current_status.value); - controller.debug_pad_button_state.d_up.Assign(current_status.value); - break; - case Settings::NativeButton::DRight: - controller.npad_button_state.right.Assign(current_status.value); - controller.debug_pad_button_state.d_right.Assign(current_status.value); - break; - case Settings::NativeButton::DDown: - controller.npad_button_state.down.Assign(current_status.value); - controller.debug_pad_button_state.d_down.Assign(current_status.value); - break; - case Settings::NativeButton::SLLeft: - controller.npad_button_state.left_sl.Assign(current_status.value); - break; - case Settings::NativeButton::SLRight: - controller.npad_button_state.right_sl.Assign(current_status.value); - break; - case Settings::NativeButton::SRLeft: - controller.npad_button_state.left_sr.Assign(current_status.value); - break; - case Settings::NativeButton::SRRight: - controller.npad_button_state.right_sr.Assign(current_status.value); - break; - case Settings::NativeButton::Home: - if (!system_buttons_enabled) { - break; - } - controller.home_button_state.home.Assign(current_status.value); - break; - case Settings::NativeButton::Screenshot: - if (!system_buttons_enabled) { - break; - } - controller.capture_button_state.capture.Assign(current_status.value); - break; - } - - lock.unlock(); - - if (!is_connected) { - if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) { - Connect(); - } - if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) { - Connect(); - } - } - TriggerOnChange(ControllerTriggerType::Button, true); -} - -void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, - Common::UUID uuid) { - if (index >= controller.stick_values.size()) { - return; - } - auto trigger_guard = - SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); }); - std::scoped_lock lock{mutex}; - const auto stick_value = TransformToStick(callback); - - // Only read stick values that have the same uuid or are over the threshold to avoid flapping - if (controller.stick_values[index].uuid != uuid) { - const bool is_tas = uuid == TAS_UUID; - if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) { - trigger_guard.Cancel(); - return; - } - if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left && - !stick_value.right) { - trigger_guard.Cancel(); - return; - } - } - - controller.stick_values[index] = stick_value; - controller.stick_values[index].uuid = uuid; - - if (is_configuring) { - controller.analog_stick_state.left = {}; - controller.analog_stick_state.right = {}; - return; - } - - const AnalogStickState stick{ - .x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX), - .y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX), - }; - - switch (index) { - case Settings::NativeAnalog::LStick: - controller.analog_stick_state.left = stick; - controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left); - controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up); - controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right); - controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down); - break; - case Settings::NativeAnalog::RStick: - controller.analog_stick_state.right = stick; - controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left); - controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up); - controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right); - controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down); - break; - } -} - -void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback, - std::size_t index, Common::UUID uuid) { - if (index >= controller.trigger_values.size()) { - return; - } - auto trigger_guard = - SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); }); - std::scoped_lock lock{mutex}; - const auto trigger_value = TransformToTrigger(callback); - - // Only read trigger values that have the same uuid or are pressed once - if (controller.trigger_values[index].uuid != uuid) { - if (!trigger_value.pressed.value) { - return; - } - } - - controller.trigger_values[index] = trigger_value; - controller.trigger_values[index].uuid = uuid; - - if (is_configuring) { - controller.gc_trigger_state.left = 0; - controller.gc_trigger_state.right = 0; - return; - } - - // Only GC controllers have analog triggers - if (npad_type != NpadStyleIndex::GameCube) { - trigger_guard.Cancel(); - return; - } - - const auto& trigger = controller.trigger_values[index]; - - switch (index) { - case Settings::NativeTrigger::LTrigger: - controller.gc_trigger_state.left = static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX); - controller.npad_button_state.zl.Assign(trigger.pressed.value); - break; - case Settings::NativeTrigger::RTrigger: - controller.gc_trigger_state.right = - static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX); - controller.npad_button_state.zr.Assign(trigger.pressed.value); - break; - } -} - -void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback, - std::size_t index) { - if (index >= controller.motion_values.size()) { - return; - } - SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); }); - std::scoped_lock lock{mutex}; - auto& raw_status = controller.motion_values[index].raw_status; - auto& emulated = controller.motion_values[index].emulated; - - raw_status = TransformToMotion(callback); - emulated.SetAcceleration(Common::Vec3f{ - raw_status.accel.x.value, - raw_status.accel.y.value, - raw_status.accel.z.value, - }); - emulated.SetGyroscope(Common::Vec3f{ - raw_status.gyro.x.value, - raw_status.gyro.y.value, - raw_status.gyro.z.value, - }); - emulated.SetUserGyroThreshold(raw_status.gyro.x.properties.threshold); - emulated.UpdateRotation(raw_status.delta_timestamp); - emulated.UpdateOrientation(raw_status.delta_timestamp); - - auto& motion = controller.motion_state[index]; - motion.accel = emulated.GetAcceleration(); - motion.gyro = emulated.GetGyroscope(); - motion.rotation = emulated.GetRotations(); - motion.euler = emulated.GetEulerAngles(); - motion.orientation = emulated.GetOrientation(); - motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); -} - -void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback, - std::size_t index) { - if (index >= controller.color_values.size()) { - return; - } - auto trigger_guard = - SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); }); - std::scoped_lock lock{mutex}; - controller.color_values[index] = TransformToColor(callback); - - if (is_configuring) { - return; - } - - if (controller.color_values[index].body == 0) { - trigger_guard.Cancel(); - return; - } - - controller.colors_state.fullkey = { - .body = GetNpadColor(controller.color_values[index].body), - .button = GetNpadColor(controller.color_values[index].buttons), - }; - if (npad_type == NpadStyleIndex::ProController) { - controller.colors_state.left = { - .body = GetNpadColor(controller.color_values[index].left_grip), - .button = GetNpadColor(controller.color_values[index].buttons), - }; - controller.colors_state.right = { - .body = GetNpadColor(controller.color_values[index].right_grip), - .button = GetNpadColor(controller.color_values[index].buttons), - }; - } else { - switch (index) { - case LeftIndex: - controller.colors_state.left = { - .body = GetNpadColor(controller.color_values[index].body), - .button = GetNpadColor(controller.color_values[index].buttons), - }; - break; - case RightIndex: - controller.colors_state.right = { - .body = GetNpadColor(controller.color_values[index].body), - .button = GetNpadColor(controller.color_values[index].buttons), - }; - break; - } - } -} - -void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback, - std::size_t index) { - if (index >= controller.battery_values.size()) { - return; - } - SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); }); - std::scoped_lock lock{mutex}; - controller.battery_values[index] = TransformToBattery(callback); - - if (is_configuring) { - return; - } - - bool is_charging = false; - bool is_powered = false; - NpadBatteryLevel battery_level = NpadBatteryLevel::Empty; - switch (controller.battery_values[index]) { - case Common::Input::BatteryLevel::Charging: - is_charging = true; - is_powered = true; - battery_level = NpadBatteryLevel::Full; - break; - case Common::Input::BatteryLevel::Medium: - battery_level = NpadBatteryLevel::High; - break; - case Common::Input::BatteryLevel::Low: - battery_level = NpadBatteryLevel::Low; - break; - case Common::Input::BatteryLevel::Critical: - battery_level = NpadBatteryLevel::Critical; - break; - case Common::Input::BatteryLevel::Empty: - battery_level = NpadBatteryLevel::Empty; - break; - case Common::Input::BatteryLevel::None: - case Common::Input::BatteryLevel::Full: - default: - is_powered = true; - battery_level = NpadBatteryLevel::Full; - break; - } - - switch (index) { - case LeftIndex: - controller.battery_state.left = { - .is_powered = is_powered, - .is_charging = is_charging, - .battery_level = battery_level, - }; - break; - case RightIndex: - controller.battery_state.right = { - .is_powered = is_powered, - .is_charging = is_charging, - .battery_level = battery_level, - }; - break; - case DualIndex: - controller.battery_state.dual = { - .is_powered = is_powered, - .is_charging = is_charging, - .battery_level = battery_level, - }; - break; - } -} - -void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) { - SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); }); - std::scoped_lock lock{mutex}; - controller.camera_values = TransformToCamera(callback); - - if (is_configuring) { - return; - } - - controller.camera_state.sample++; - controller.camera_state.format = - static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format); - controller.camera_state.data = controller.camera_values.data; -} - -void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) { - SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); }); - std::scoped_lock lock{mutex}; - const auto force_value = TransformToStick(callback); - - controller.ring_analog_value = force_value.x; - - if (is_configuring) { - return; - } - - controller.ring_analog_state.force = force_value.x.value; -} - -void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { - SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); }); - std::scoped_lock lock{mutex}; - controller.nfc_values = TransformToNfc(callback); - - if (is_configuring) { - return; - } - - controller.nfc_state = controller.nfc_values; -} - -bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { - if (!is_initalized) { - return false; - } - if (device_index >= output_devices.size()) { - return false; - } - if (!output_devices[device_index]) { - return false; - } - const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); - const auto& player = Settings::values.players.GetValue()[player_index]; - const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; - - if (!player.vibration_enabled) { - return false; - } - - // Exponential amplification is too strong at low amplitudes. Switch to a linear - // amplification if strength is set below 0.7f - const Common::Input::VibrationAmplificationType type = - strength > 0.7f ? Common::Input::VibrationAmplificationType::Exponential - : Common::Input::VibrationAmplificationType::Linear; - - const Common::Input::VibrationStatus status = { - .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), - .low_frequency = vibration.low_frequency, - .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), - .high_frequency = vibration.high_frequency, - .type = type, - }; - return output_devices[device_index]->SetVibration(status) == - Common::Input::DriverResult::Success; -} - -bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { - const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); - const auto& player = Settings::values.players.GetValue()[player_index]; - - if (!is_initalized) { - return false; - } - - if (!player.vibration_enabled) { - return false; - } - - if (device_index >= output_devices.size()) { - return false; - } - - if (!output_devices[device_index]) { - return false; - } - - return output_devices[device_index]->IsVibrationEnabled(); -} - -Common::Input::DriverResult EmulatedController::SetPollingMode( - EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) { - LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index); - - if (!is_initalized) { - return Common::Input::DriverResult::InvalidHandle; - } - - auto& left_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Left)]; - auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& nfc_output_device = output_devices[3]; - - if (device_index == EmulatedDeviceIndex::LeftIndex) { - controller.left_polling_mode = polling_mode; - return left_output_device->SetPollingMode(polling_mode); - } - - if (device_index == EmulatedDeviceIndex::RightIndex) { - controller.right_polling_mode = polling_mode; - const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); - const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode); - - // Restore previous state - if (mapped_nfc_result != Common::Input::DriverResult::Success) { - right_output_device->SetPollingMode(Common::Input::PollingMode::Active); - } - - if (virtual_nfc_result == Common::Input::DriverResult::Success) { - return virtual_nfc_result; - } - return mapped_nfc_result; - } - - controller.left_polling_mode = polling_mode; - controller.right_polling_mode = polling_mode; - left_output_device->SetPollingMode(polling_mode); - right_output_device->SetPollingMode(polling_mode); - nfc_output_device->SetPollingMode(polling_mode); - return Common::Input::DriverResult::Success; -} - -Common::Input::PollingMode EmulatedController::GetPollingMode( - EmulatedDeviceIndex device_index) const { - if (device_index == EmulatedDeviceIndex::LeftIndex) { - return controller.left_polling_mode; - } - return controller.right_polling_mode; -} - -bool EmulatedController::SetCameraFormat( - Core::IrSensor::ImageTransferProcessorFormat camera_format) { - LOG_INFO(Service_HID, "Set camera format {}", camera_format); - - if (!is_initalized) { - return false; - } - - auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& camera_output_device = output_devices[2]; - - if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( - camera_format)) == Common::Input::DriverResult::Success) { - return true; - } - - // Fallback to Qt camera if native device doesn't have support - return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>( - camera_format)) == Common::Input::DriverResult::Success; -} - -Common::ParamPackage EmulatedController::GetRingParam() const { - return ring_params[0]; -} - -void EmulatedController::SetRingParam(Common::ParamPackage param) { - ring_params[0] = std::move(param); - ReloadInput(); -} - -bool EmulatedController::HasNfc() const { - - if (!is_initalized) { - return false; - } - - const auto& nfc_output_device = output_devices[3]; - - switch (npad_type) { - case NpadStyleIndex::JoyconRight: - case NpadStyleIndex::JoyconDual: - case NpadStyleIndex::ProController: - case NpadStyleIndex::Handheld: - break; - default: - return false; - } - - const bool has_virtual_nfc = - npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld; - const bool is_virtual_nfc_supported = - nfc_output_device->SupportsNfc() != Common::Input::NfcState::NotSupported; - - return is_connected && (has_virtual_nfc && is_virtual_nfc_supported); -} - -bool EmulatedController::AddNfcHandle() { - nfc_handles++; - return SetPollingMode(EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::NFC) == - Common::Input::DriverResult::Success; -} - -bool EmulatedController::RemoveNfcHandle() { - nfc_handles--; - if (nfc_handles <= 0) { - return SetPollingMode(EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Active) == - Common::Input::DriverResult::Success; - } - return true; -} - -bool EmulatedController::StartNfcPolling() { - if (!is_initalized) { - return false; - } - - auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& nfc_virtual_output_device = output_devices[3]; - - const auto device_result = nfc_output_device->StartNfcPolling(); - const auto virtual_device_result = nfc_virtual_output_device->StartNfcPolling(); - - return device_result == Common::Input::NfcState::Success || - virtual_device_result == Common::Input::NfcState::Success; -} - -bool EmulatedController::StopNfcPolling() { - if (!is_initalized) { - return false; - } - - auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& nfc_virtual_output_device = output_devices[3]; - - const auto device_result = nfc_output_device->StopNfcPolling(); - const auto virtual_device_result = nfc_virtual_output_device->StopNfcPolling(); - - return device_result == Common::Input::NfcState::Success || - virtual_device_result == Common::Input::NfcState::Success; -} - -bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) { - if (!is_initalized) { - return false; - } - - auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& nfc_virtual_output_device = output_devices[3]; - - if (nfc_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success) { - return true; - } - - return nfc_virtual_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success; -} - -bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& request, - Common::Input::MifareRequest& out_data) { - if (!is_initalized) { - return false; - } - - auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& nfc_virtual_output_device = output_devices[3]; - - if (nfc_output_device->ReadMifareData(request, out_data) == Common::Input::NfcState::Success) { - return true; - } - - return nfc_virtual_output_device->ReadMifareData(request, out_data) == - Common::Input::NfcState::Success; -} - -bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& request) { - if (!is_initalized) { - return false; - } - - auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& nfc_virtual_output_device = output_devices[3]; - - if (nfc_output_device->WriteMifareData(request) == Common::Input::NfcState::Success) { - return true; - } - - return nfc_virtual_output_device->WriteMifareData(request) == Common::Input::NfcState::Success; -} - -bool EmulatedController::WriteNfc(const std::vector<u8>& data) { - if (!is_initalized) { - return false; - } - - auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)]; - auto& nfc_virtual_output_device = output_devices[3]; - - if (nfc_output_device->SupportsNfc() != Common::Input::NfcState::NotSupported) { - return nfc_output_device->WriteNfcData(data) == Common::Input::NfcState::Success; - } - - return nfc_virtual_output_device->WriteNfcData(data) == Common::Input::NfcState::Success; -} - -void EmulatedController::SetLedPattern() { - if (!is_initalized) { - return; - } - - for (auto& device : output_devices) { - if (!device) { - continue; - } - - const LedPattern pattern = GetLedPattern(); - const Common::Input::LedStatus status = { - .led_1 = pattern.position1 != 0, - .led_2 = pattern.position2 != 0, - .led_3 = pattern.position3 != 0, - .led_4 = pattern.position4 != 0, - }; - device->SetLED(status); - } -} - -void EmulatedController::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode) { - for (auto& motion : controller.motion_values) { - switch (mode) { - case GyroscopeZeroDriftMode::Loose: - motion_sensitivity = motion.emulated.IsAtRestLoose; - motion.emulated.SetGyroThreshold(motion.emulated.ThresholdLoose); - break; - case GyroscopeZeroDriftMode::Tight: - motion_sensitivity = motion.emulated.IsAtRestThight; - motion.emulated.SetGyroThreshold(motion.emulated.ThresholdThight); - break; - case GyroscopeZeroDriftMode::Standard: - default: - motion_sensitivity = motion.emulated.IsAtRestStandard; - motion.emulated.SetGyroThreshold(motion.emulated.ThresholdStandard); - break; - } - } -} - -void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) { - supported_style_tag = supported_styles; - if (!is_connected) { - return; - } - - // Attempt to reconnect with the original type - if (npad_type != original_npad_type) { - Disconnect(); - const auto current_npad_type = npad_type; - SetNpadStyleIndex(original_npad_type); - if (IsControllerSupported()) { - Connect(); - return; - } - SetNpadStyleIndex(current_npad_type); - Connect(); - } - - if (IsControllerSupported()) { - return; - } - - Disconnect(); - - // Fallback Fullkey controllers to Pro controllers - if (IsControllerFullkey() && supported_style_tag.fullkey) { - LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); - SetNpadStyleIndex(NpadStyleIndex::ProController); - Connect(); - return; - } - - // Fallback Dual joycon controllers to Pro controllers - if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) { - LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type); - SetNpadStyleIndex(NpadStyleIndex::ProController); - Connect(); - return; - } - - // Fallback Pro controllers to Dual joycon - if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) { - LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type); - SetNpadStyleIndex(NpadStyleIndex::JoyconDual); - Connect(); - return; - } - - LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller", - npad_type); -} - -bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const { - std::scoped_lock lock{mutex}; - const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; - switch (type) { - case NpadStyleIndex::ProController: - case NpadStyleIndex::GameCube: - case NpadStyleIndex::NES: - case NpadStyleIndex::SNES: - case NpadStyleIndex::N64: - case NpadStyleIndex::SegaGenesis: - return true; - default: - return false; - } -} - -bool EmulatedController::IsControllerSupported(bool use_temporary_value) const { - std::scoped_lock lock{mutex}; - const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; - switch (type) { - case NpadStyleIndex::ProController: - return supported_style_tag.fullkey.As<bool>(); - case NpadStyleIndex::Handheld: - return supported_style_tag.handheld.As<bool>(); - case NpadStyleIndex::JoyconDual: - return supported_style_tag.joycon_dual.As<bool>(); - case NpadStyleIndex::JoyconLeft: - return supported_style_tag.joycon_left.As<bool>(); - case NpadStyleIndex::JoyconRight: - return supported_style_tag.joycon_right.As<bool>(); - case NpadStyleIndex::GameCube: - return supported_style_tag.gamecube.As<bool>(); - case NpadStyleIndex::Pokeball: - return supported_style_tag.palma.As<bool>(); - case NpadStyleIndex::NES: - return supported_style_tag.lark.As<bool>(); - case NpadStyleIndex::SNES: - return supported_style_tag.lucia.As<bool>(); - case NpadStyleIndex::N64: - return supported_style_tag.lagoon.As<bool>(); - case NpadStyleIndex::SegaGenesis: - return supported_style_tag.lager.As<bool>(); - default: - return false; - } -} - -void EmulatedController::Connect(bool use_temporary_value) { - if (!IsControllerSupported(use_temporary_value)) { - const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; - LOG_ERROR(Service_HID, "Controller type {} is not supported", type); - return; - } - - auto trigger_guard = - SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); }); - std::scoped_lock lock{connect_mutex, mutex}; - if (is_configuring) { - tmp_is_connected = true; - return; - } - - if (is_connected) { - trigger_guard.Cancel(); - return; - } - is_connected = true; -} - -void EmulatedController::Disconnect() { - auto trigger_guard = - SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); }); - std::scoped_lock lock{connect_mutex, mutex}; - if (is_configuring) { - tmp_is_connected = false; - return; - } - - if (!is_connected) { - trigger_guard.Cancel(); - return; - } - is_connected = false; -} - -bool EmulatedController::IsConnected(bool get_temporary_value) const { - std::scoped_lock lock{connect_mutex}; - if (get_temporary_value && is_configuring) { - return tmp_is_connected; - } - return is_connected; -} - -NpadIdType EmulatedController::GetNpadIdType() const { - std::scoped_lock lock{mutex}; - return npad_id_type; -} - -NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const { - std::scoped_lock lock{npad_mutex}; - if (get_temporary_value && is_configuring) { - return tmp_npad_type; - } - return npad_type; -} - -void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) { - auto trigger_guard = - SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); }); - std::scoped_lock lock{mutex, npad_mutex}; - - if (is_configuring) { - if (tmp_npad_type == npad_type_) { - trigger_guard.Cancel(); - return; - } - tmp_npad_type = npad_type_; - return; - } - - if (npad_type == npad_type_) { - trigger_guard.Cancel(); - return; - } - if (is_connected) { - LOG_WARNING(Service_HID, "Controller {} type changed while it's connected", - Service::HID::NpadIdTypeToIndex(npad_id_type)); - } - npad_type = npad_type_; -} - -LedPattern EmulatedController::GetLedPattern() const { - switch (npad_id_type) { - case NpadIdType::Player1: - return LedPattern{1, 0, 0, 0}; - case NpadIdType::Player2: - return LedPattern{1, 1, 0, 0}; - case NpadIdType::Player3: - return LedPattern{1, 1, 1, 0}; - case NpadIdType::Player4: - return LedPattern{1, 1, 1, 1}; - case NpadIdType::Player5: - return LedPattern{1, 0, 0, 1}; - case NpadIdType::Player6: - return LedPattern{1, 0, 1, 0}; - case NpadIdType::Player7: - return LedPattern{1, 0, 1, 1}; - case NpadIdType::Player8: - return LedPattern{0, 1, 1, 0}; - default: - return LedPattern{0, 0, 0, 0}; - } -} - -ButtonValues EmulatedController::GetButtonsValues() const { - std::scoped_lock lock{mutex}; - return controller.button_values; -} - -SticksValues EmulatedController::GetSticksValues() const { - std::scoped_lock lock{mutex}; - return controller.stick_values; -} - -TriggerValues EmulatedController::GetTriggersValues() const { - std::scoped_lock lock{mutex}; - return controller.trigger_values; -} - -ControllerMotionValues EmulatedController::GetMotionValues() const { - std::scoped_lock lock{mutex}; - return controller.motion_values; -} - -ColorValues EmulatedController::GetColorsValues() const { - std::scoped_lock lock{mutex}; - return controller.color_values; -} - -BatteryValues EmulatedController::GetBatteryValues() const { - std::scoped_lock lock{mutex}; - return controller.battery_values; -} - -CameraValues EmulatedController::GetCameraValues() const { - std::scoped_lock lock{mutex}; - return controller.camera_values; -} - -RingAnalogValue EmulatedController::GetRingSensorValues() const { - return controller.ring_analog_value; -} - -HomeButtonState EmulatedController::GetHomeButtons() const { - std::scoped_lock lock{mutex}; - if (is_configuring) { - return {}; - } - return controller.home_button_state; -} - -CaptureButtonState EmulatedController::GetCaptureButtons() const { - std::scoped_lock lock{mutex}; - if (is_configuring) { - return {}; - } - return controller.capture_button_state; -} - -NpadButtonState EmulatedController::GetNpadButtons() const { - std::scoped_lock lock{mutex}; - if (is_configuring) { - return {}; - } - return {controller.npad_button_state.raw & GetTurboButtonMask()}; -} - -DebugPadButton EmulatedController::GetDebugPadButtons() const { - std::scoped_lock lock{mutex}; - if (is_configuring) { - return {}; - } - return controller.debug_pad_button_state; -} - -AnalogSticks EmulatedController::GetSticks() const { - std::scoped_lock lock{mutex}; - - if (is_configuring) { - return {}; - } - - return controller.analog_stick_state; -} - -NpadGcTriggerState EmulatedController::GetTriggers() const { - std::scoped_lock lock{mutex}; - if (is_configuring) { - return {}; - } - return controller.gc_trigger_state; -} - -MotionState EmulatedController::GetMotions() const { - std::unique_lock lock{mutex}; - return controller.motion_state; -} - -ControllerColors EmulatedController::GetColors() const { - std::scoped_lock lock{mutex}; - return controller.colors_state; -} - -BatteryLevelState EmulatedController::GetBattery() const { - std::scoped_lock lock{mutex}; - return controller.battery_state; -} - -const CameraState& EmulatedController::GetCamera() const { - std::scoped_lock lock{mutex}; - return controller.camera_state; -} - -RingSensorForce EmulatedController::GetRingSensorForce() const { - return controller.ring_analog_state; -} - -const NfcState& EmulatedController::GetNfc() const { - std::scoped_lock lock{mutex}; - return controller.nfc_state; -} - -NpadColor EmulatedController::GetNpadColor(u32 color) { - return { - .r = static_cast<u8>((color >> 16) & 0xFF), - .g = static_cast<u8>((color >> 8) & 0xFF), - .b = static_cast<u8>(color & 0xFF), - .a = 0xff, - }; -} - -void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { - std::scoped_lock lock{callback_mutex}; - for (const auto& poller_pair : callback_list) { - const ControllerUpdateCallback& poller = poller_pair.second; - if (!is_npad_service_update && poller.is_npad_service) { - continue; - } - if (poller.on_change) { - poller.on_change(type); - } - } -} - -int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) { - std::scoped_lock lock{callback_mutex}; - callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); - return last_callback_key++; -} - -void EmulatedController::DeleteCallback(int key) { - std::scoped_lock lock{callback_mutex}; - const auto& iterator = callback_list.find(key); - if (iterator == callback_list.end()) { - LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); - return; - } - callback_list.erase(iterator); -} - -void EmulatedController::StatusUpdate() { - turbo_button_state = (turbo_button_state + 1) % (TURBO_BUTTON_DELAY * 2); - - // Some drivers like key motion need constant refreshing - for (std::size_t index = 0; index < motion_devices.size(); ++index) { - const auto& raw_status = controller.motion_values[index].raw_status; - auto& device = motion_devices[index]; - if (!raw_status.force_update) { - continue; - } - if (!device) { - continue; - } - device->ForceUpdate(); - } -} - -NpadButton EmulatedController::GetTurboButtonMask() const { - // Apply no mask when disabled - if (turbo_button_state < TURBO_BUTTON_DELAY) { - return {NpadButton::All}; - } - - NpadButtonState button_mask{}; - for (std::size_t index = 0; index < controller.button_values.size(); ++index) { - if (!controller.button_values[index].turbo) { - continue; - } - - switch (index) { - case Settings::NativeButton::A: - button_mask.a.Assign(1); - break; - case Settings::NativeButton::B: - button_mask.b.Assign(1); - break; - case Settings::NativeButton::X: - button_mask.x.Assign(1); - break; - case Settings::NativeButton::Y: - button_mask.y.Assign(1); - break; - case Settings::NativeButton::L: - button_mask.l.Assign(1); - break; - case Settings::NativeButton::R: - button_mask.r.Assign(1); - break; - case Settings::NativeButton::ZL: - button_mask.zl.Assign(1); - break; - case Settings::NativeButton::ZR: - button_mask.zr.Assign(1); - break; - case Settings::NativeButton::DLeft: - button_mask.left.Assign(1); - break; - case Settings::NativeButton::DUp: - button_mask.up.Assign(1); - break; - case Settings::NativeButton::DRight: - button_mask.right.Assign(1); - break; - case Settings::NativeButton::DDown: - button_mask.down.Assign(1); - break; - case Settings::NativeButton::SLLeft: - button_mask.left_sl.Assign(1); - break; - case Settings::NativeButton::SLRight: - button_mask.right_sl.Assign(1); - break; - case Settings::NativeButton::SRLeft: - button_mask.left_sr.Assign(1); - break; - case Settings::NativeButton::SRRight: - button_mask.right_sr.Assign(1); - break; - default: - break; - } - } - - return static_cast<NpadButton>(~button_mask.raw); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <functional> -#include <memory> -#include <mutex> -#include <unordered_map> -#include <vector> - -#include "common/common_types.h" -#include "common/input.h" -#include "common/param_package.h" -#include "common/settings.h" -#include "common/vector_math.h" -#include "core/hid/hid_types.h" -#include "core/hid/irs_types.h" -#include "core/hid/motion_input.h" - -namespace Core::HID { -const std::size_t max_emulated_controllers = 2; -const std::size_t output_devices_size = 4; -struct ControllerMotionInfo { - Common::Input::MotionStatus raw_status{}; - MotionInput emulated{}; -}; - -using ButtonDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeButton::NumButtons>; -using StickDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>; -using ControllerMotionDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>; -using TriggerDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>; -using ColorDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; -using BatteryDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; -using CameraDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; -using RingAnalogDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; -using NfcDevices = - std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; -using OutputDevices = std::array<std::unique_ptr<Common::Input::OutputDevice>, output_devices_size>; - -using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>; -using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>; -using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>; -using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>; -using ColorParams = std::array<Common::ParamPackage, max_emulated_controllers>; -using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>; -using CameraParams = std::array<Common::ParamPackage, max_emulated_controllers>; -using RingAnalogParams = std::array<Common::ParamPackage, max_emulated_controllers>; -using NfcParams = std::array<Common::ParamPackage, max_emulated_controllers>; -using OutputParams = std::array<Common::ParamPackage, output_devices_size>; - -using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>; -using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>; -using TriggerValues = - std::array<Common::Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>; -using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>; -using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>; -using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>; -using CameraValues = Common::Input::CameraStatus; -using RingAnalogValue = Common::Input::AnalogStatus; -using NfcValues = Common::Input::NfcStatus; -using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>; - -struct AnalogSticks { - AnalogStickState left{}; - AnalogStickState right{}; -}; - -struct ControllerColors { - NpadControllerColor fullkey{}; - NpadControllerColor left{}; - NpadControllerColor right{}; -}; - -struct BatteryLevelState { - NpadPowerInfo dual{}; - NpadPowerInfo left{}; - NpadPowerInfo right{}; -}; - -struct CameraState { - Core::IrSensor::ImageTransferProcessorFormat format{}; - std::vector<u8> data{}; - std::size_t sample{}; -}; - -struct RingSensorForce { - f32 force; -}; - -using NfcState = Common::Input::NfcStatus; - -struct ControllerMotion { - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Vec3f rotation{}; - Common::Vec3f euler{}; - std::array<Common::Vec3f, 3> orientation{}; - bool is_at_rest{}; -}; - -enum EmulatedDeviceIndex : u8 { - LeftIndex, - RightIndex, - DualIndex, - AllDevices, -}; - -using MotionState = std::array<ControllerMotion, 2>; - -struct ControllerStatus { - // Data from input_common - ButtonValues button_values{}; - SticksValues stick_values{}; - ControllerMotionValues motion_values{}; - TriggerValues trigger_values{}; - ColorValues color_values{}; - BatteryValues battery_values{}; - VibrationValues vibration_values{}; - CameraValues camera_values{}; - RingAnalogValue ring_analog_value{}; - NfcValues nfc_values{}; - - // Data for HID services - HomeButtonState home_button_state{}; - CaptureButtonState capture_button_state{}; - NpadButtonState npad_button_state{}; - DebugPadButton debug_pad_button_state{}; - AnalogSticks analog_stick_state{}; - MotionState motion_state{}; - NpadGcTriggerState gc_trigger_state{}; - ControllerColors colors_state{}; - BatteryLevelState battery_state{}; - CameraState camera_state{}; - RingSensorForce ring_analog_state{}; - NfcState nfc_state{}; - Common::Input::PollingMode left_polling_mode{}; - Common::Input::PollingMode right_polling_mode{}; -}; - -enum class ControllerTriggerType { - Button, - Stick, - Trigger, - Motion, - Color, - Battery, - Vibration, - IrSensor, - RingController, - Nfc, - Connected, - Disconnected, - Type, - All, -}; - -struct ControllerUpdateCallback { - std::function<void(ControllerTriggerType)> on_change; - bool is_npad_service; -}; - -class EmulatedController { -public: - /** - * Contains all input data (buttons, joysticks, vibration, and motion) within this controller. - * @param npad_id_type npad id type for this specific controller - */ - explicit EmulatedController(NpadIdType npad_id_type_); - ~EmulatedController(); - - YUZU_NON_COPYABLE(EmulatedController); - YUZU_NON_MOVEABLE(EmulatedController); - - /// Converts the controller type from settings to npad type - static NpadStyleIndex MapSettingsTypeToNPad(Settings::ControllerType type); - - /// Converts npad type to the equivalent of controller type from settings - static Settings::ControllerType MapNPadToSettingsType(NpadStyleIndex type); - - /// Gets the NpadIdType for this controller - NpadIdType GetNpadIdType() const; - - /// Sets the NpadStyleIndex for this controller - void SetNpadStyleIndex(NpadStyleIndex npad_type_); - - /** - * Gets the NpadStyleIndex for this controller - * @param get_temporary_value If true tmp_npad_type will be returned - * @return NpadStyleIndex set on the controller - */ - NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; - - /** - * Sets the supported controller types. Disconnects the controller if current type is not - * supported - * @param supported_styles bitflag with supported types - */ - void SetSupportedNpadStyleTag(NpadStyleTag supported_styles); - - /** - * Sets the connected status to true - * @param use_temporary_value If true tmp_npad_type will be used - */ - void Connect(bool use_temporary_value = false); - - /// Sets the connected status to false - void Disconnect(); - - /** - * Is the emulated connected - * @param get_temporary_value If true tmp_is_connected will be returned - * @return true if the controller has the connected status - */ - bool IsConnected(bool get_temporary_value = false) const; - - /// Removes all callbacks created from input devices - void UnloadInput(); - - /** - * Sets the emulated controller into configuring mode - * This prevents the modification of the HID state of the emulated controller by input commands - */ - void EnableConfiguration(); - - /// Returns the emulated controller into normal mode, allowing the modification of the HID state - void DisableConfiguration(); - - /// Enables Home and Screenshot buttons - void EnableSystemButtons(); - - /// Disables Home and Screenshot buttons - void DisableSystemButtons(); - - /// Sets Home and Screenshot buttons to false - void ResetSystemButtons(); - - /// Returns true if the emulated controller is in configuring mode - bool IsConfiguring() const; - - /// Reload all input devices - void ReloadInput(); - - /// Overrides current mapped devices with the stored configuration and reloads all input devices - void ReloadFromSettings(); - - /// Updates current colors with the ones stored in the configuration - void ReloadColorsFromSettings(); - - /// Saves the current mapped configuration - void SaveCurrentConfig(); - - /// Reverts any mapped changes made that weren't saved - void RestoreConfig(); - - /// Returns a vector of mapped devices from the mapped button and stick parameters - std::vector<Common::ParamPackage> GetMappedDevices() const; - - // Returns the current mapped button device - Common::ParamPackage GetButtonParam(std::size_t index) const; - - // Returns the current mapped stick device - Common::ParamPackage GetStickParam(std::size_t index) const; - - // Returns the current mapped motion device - Common::ParamPackage GetMotionParam(std::size_t index) const; - - /** - * Updates the current mapped button device - * @param param ParamPackage with controller data to be mapped - */ - void SetButtonParam(std::size_t index, Common::ParamPackage param); - - /** - * Updates the current mapped stick device - * @param param ParamPackage with controller data to be mapped - */ - void SetStickParam(std::size_t index, Common::ParamPackage param); - - /** - * Updates the current mapped motion device - * @param param ParamPackage with controller data to be mapped - */ - void SetMotionParam(std::size_t index, Common::ParamPackage param); - - /// Auto calibrates the current motion devices - void StartMotionCalibration(); - - /// Returns the latest button status from the controller with parameters - ButtonValues GetButtonsValues() const; - - /// Returns the latest analog stick status from the controller with parameters - SticksValues GetSticksValues() const; - - /// Returns the latest trigger status from the controller with parameters - TriggerValues GetTriggersValues() const; - - /// Returns the latest motion status from the controller with parameters - ControllerMotionValues GetMotionValues() const; - - /// Returns the latest color status from the controller with parameters - ColorValues GetColorsValues() const; - - /// Returns the latest battery status from the controller with parameters - BatteryValues GetBatteryValues() const; - - /// Returns the latest camera status from the controller with parameters - CameraValues GetCameraValues() const; - - /// Returns the latest status of analog input from the ring sensor with parameters - RingAnalogValue GetRingSensorValues() const; - - /// Returns the latest status of button input for the hid::HomeButton service - HomeButtonState GetHomeButtons() const; - - /// Returns the latest status of button input for the hid::CaptureButton service - CaptureButtonState GetCaptureButtons() const; - - /// Returns the latest status of button input for the hid::Npad service - NpadButtonState GetNpadButtons() const; - - /// Returns the latest status of button input for the debug pad service - DebugPadButton GetDebugPadButtons() const; - - /// Returns the latest status of stick input from the mouse - AnalogSticks GetSticks() const; - - /// Returns the latest status of trigger input from the mouse - NpadGcTriggerState GetTriggers() const; - - /// Returns the latest status of motion input from the mouse - MotionState GetMotions() const; - - /// Returns the latest color value from the controller - ControllerColors GetColors() const; - - /// Returns the latest battery status from the controller - BatteryLevelState GetBattery() const; - - /// Returns the latest camera status from the controller - const CameraState& GetCamera() const; - - /// Returns the latest ringcon force sensor value - RingSensorForce GetRingSensorForce() const; - - /// Returns the latest ntag status from the controller - const NfcState& GetNfc() const; - - /** - * Sends a specific vibration to the output device - * @return true if vibration had no errors - */ - bool SetVibration(std::size_t device_index, VibrationValue vibration); - - /** - * Sends a small vibration to the output device - * @return true if SetVibration was successful - */ - bool IsVibrationEnabled(std::size_t device_index); - - /** - * Sets the desired data to be polled from a controller - * @param device_index index of the controller to set the polling mode - * @param polling_mode type of input desired buttons, gyro, nfc, ir, etc. - * @return driver result from this command - */ - Common::Input::DriverResult SetPollingMode(EmulatedDeviceIndex device_index, - Common::Input::PollingMode polling_mode); - /** - * Get the current polling mode from a controller - * @param device_index index of the controller to set the polling mode - * @return current polling mode - */ - Common::Input::PollingMode GetPollingMode(EmulatedDeviceIndex device_index) const; - - /** - * Sets the desired camera format to be polled from a controller - * @param camera_format size of each frame - * @return true if SetCameraFormat was successful - */ - bool SetCameraFormat(Core::IrSensor::ImageTransferProcessorFormat camera_format); - - // Returns the current mapped ring device - Common::ParamPackage GetRingParam() const; - - /** - * Updates the current mapped ring device - * @param param ParamPackage with ring sensor data to be mapped - */ - void SetRingParam(Common::ParamPackage param); - - /// Returns true if the device has nfc support - bool HasNfc() const; - - /// Sets the joycon in nfc mode and increments the handle count - bool AddNfcHandle(); - - /// Decrements the handle count if zero sets the joycon in active mode - bool RemoveNfcHandle(); - - /// Start searching for nfc tags - bool StartNfcPolling(); - - /// Stop searching for nfc tags - bool StopNfcPolling(); - - /// Returns true if the nfc tag was readable - bool ReadAmiiboData(std::vector<u8>& data); - - /// Returns true if the nfc tag was written - bool WriteNfc(const std::vector<u8>& data); - - /// Returns true if the nfc tag was readable - bool ReadMifareData(const Common::Input::MifareRequest& request, - Common::Input::MifareRequest& out_data); - - /// Returns true if the nfc tag was written - bool WriteMifareData(const Common::Input::MifareRequest& request); - - /// Returns the led pattern corresponding to this emulated controller - LedPattern GetLedPattern() const; - - /// Asks the output device to change the player led pattern - void SetLedPattern(); - - /// Changes sensitivity of the motion sensor - void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode); - - /** - * Adds a callback to the list of events - * @param update_callback A ConsoleUpdateCallback that will be triggered - * @return an unique key corresponding to the callback index in the list - */ - int SetCallback(ControllerUpdateCallback update_callback); - - /** - * Removes a callback from the list stopping any future events to this object - * @param key Key corresponding to the callback index in the list - */ - void DeleteCallback(int key); - - /// Swaps the state of the turbo buttons and updates motion input - void StatusUpdate(); - -private: - /// creates input devices from params - void LoadDevices(); - - /// Set the params for TAS devices - void LoadTASParams(); - - /// Set the params for virtual pad devices - void LoadVirtualGamepadParams(); - - /** - * @param use_temporary_value If true tmp_npad_type will be used - * @return true if the controller style is fullkey - */ - bool IsControllerFullkey(bool use_temporary_value = false) const; - - /** - * Checks the current controller type against the supported_style_tag - * @param use_temporary_value If true tmp_npad_type will be used - * @return true if the controller is supported - */ - bool IsControllerSupported(bool use_temporary_value = false) const; - - /** - * Updates the button status of the controller - * @param callback A CallbackStatus containing the button status - * @param index Button ID of the to be updated - */ - void SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, - Common::UUID uuid); - - /** - * Updates the analog stick status of the controller - * @param callback A CallbackStatus containing the analog stick status - * @param index stick ID of the to be updated - */ - void SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, - Common::UUID uuid); - - /** - * Updates the trigger status of the controller - * @param callback A CallbackStatus containing the trigger status - * @param index trigger ID of the to be updated - */ - void SetTrigger(const Common::Input::CallbackStatus& callback, std::size_t index, - Common::UUID uuid); - - /** - * Updates the motion status of the controller - * @param callback A CallbackStatus containing gyro and accelerometer data - * @param index motion ID of the to be updated - */ - void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index); - - /** - * Updates the color status of the controller - * @param callback A CallbackStatus containing the color status - * @param index color ID of the to be updated - */ - void SetColors(const Common::Input::CallbackStatus& callback, std::size_t index); - - /** - * Updates the battery status of the controller - * @param callback A CallbackStatus containing the battery status - * @param index battery ID of the to be updated - */ - void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index); - - /** - * Updates the camera status of the controller - * @param callback A CallbackStatus containing the camera status - */ - void SetCamera(const Common::Input::CallbackStatus& callback); - - /** - * Updates the ring analog sensor status of the ring controller - * @param callback A CallbackStatus containing the force status - */ - void SetRingAnalog(const Common::Input::CallbackStatus& callback); - - /** - * Updates the nfc status of the controller - * @param callback A CallbackStatus containing the nfc status - */ - void SetNfc(const Common::Input::CallbackStatus& callback); - - /** - * Converts a color format from bgra to rgba - * @param color in bgra format - * @return NpadColor in rgba format - */ - NpadColor GetNpadColor(u32 color); - - /** - * Triggers a callback that something has changed on the controller status - * @param type Input type of the event to trigger - * @param is_service_update indicates if this event should only be sent to HID services - */ - void TriggerOnChange(ControllerTriggerType type, bool is_service_update); - - NpadButton GetTurboButtonMask() const; - - const NpadIdType npad_id_type; - NpadStyleIndex npad_type{NpadStyleIndex::None}; - NpadStyleIndex original_npad_type{NpadStyleIndex::None}; - NpadStyleTag supported_style_tag{NpadStyleSet::All}; - bool is_connected{false}; - bool is_configuring{false}; - bool is_initalized{false}; - bool system_buttons_enabled{true}; - f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; - u32 turbo_button_state{0}; - std::size_t nfc_handles{0}; - - // Temporary values to avoid doing changes while the controller is in configuring mode - NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; - bool tmp_is_connected{false}; - - ButtonParams button_params; - StickParams stick_params; - ControllerMotionParams motion_params; - TriggerParams trigger_params; - BatteryParams battery_params; - ColorParams color_params; - CameraParams camera_params; - RingAnalogParams ring_params; - NfcParams nfc_params; - OutputParams output_params; - - ButtonDevices button_devices; - StickDevices stick_devices; - ControllerMotionDevices motion_devices; - TriggerDevices trigger_devices; - BatteryDevices battery_devices; - ColorDevices color_devices; - CameraDevices camera_devices; - RingAnalogDevices ring_analog_devices; - NfcDevices nfc_devices; - OutputDevices output_devices; - - // TAS related variables - ButtonParams tas_button_params; - StickParams tas_stick_params; - ButtonDevices tas_button_devices; - StickDevices tas_stick_devices; - - // Virtual gamepad related variables - ButtonParams virtual_button_params; - StickParams virtual_stick_params; - ControllerMotionParams virtual_motion_params; - ButtonDevices virtual_button_devices; - StickDevices virtual_stick_devices; - ControllerMotionDevices virtual_motion_devices; - - mutable std::mutex mutex; - mutable std::mutex callback_mutex; - mutable std::mutex npad_mutex; - mutable std::mutex connect_mutex; - std::unordered_map<int, ControllerUpdateCallback> callback_list; - int last_callback_key = 0; - - // Stores the current status of all controller input - ControllerStatus controller; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <fmt/format.h> - -#include "core/hid/emulated_devices.h" -#include "core/hid/input_converter.h" - -namespace Core::HID { - -EmulatedDevices::EmulatedDevices() = default; - -EmulatedDevices::~EmulatedDevices() = default; - -void EmulatedDevices::ReloadFromSettings() { - ReloadInput(); -} - -void EmulatedDevices::ReloadInput() { - // If you load any device here add the equivalent to the UnloadInput() function - - // Native Mouse is mapped on port 1, pad 0 - const Common::ParamPackage mouse_params{"engine:mouse,port:1,pad:0"}; - - // Keyboard keys is mapped on port 1, pad 0 for normal keys, pad 1 for moddifier keys - const Common::ParamPackage keyboard_params{"engine:keyboard,port:1"}; - - std::size_t key_index = 0; - for (auto& mouse_device : mouse_button_devices) { - Common::ParamPackage mouse_button_params = mouse_params; - mouse_button_params.Set("button", static_cast<int>(key_index)); - mouse_device = Common::Input::CreateInputDevice(mouse_button_params); - key_index++; - } - - Common::ParamPackage mouse_position_params = mouse_params; - mouse_position_params.Set("axis_x", 0); - mouse_position_params.Set("axis_y", 1); - mouse_position_params.Set("deadzone", 0.0f); - mouse_position_params.Set("range", 1.0f); - mouse_position_params.Set("threshold", 0.0f); - mouse_stick_device = Common::Input::CreateInputDevice(mouse_position_params); - - // First two axis are reserved for mouse position - key_index = 2; - for (auto& mouse_device : mouse_wheel_devices) { - Common::ParamPackage mouse_wheel_params = mouse_params; - mouse_wheel_params.Set("axis", static_cast<int>(key_index)); - mouse_device = Common::Input::CreateInputDevice(mouse_wheel_params); - key_index++; - } - - key_index = 0; - for (auto& keyboard_device : keyboard_devices) { - Common::ParamPackage keyboard_key_params = keyboard_params; - keyboard_key_params.Set("button", static_cast<int>(key_index)); - keyboard_key_params.Set("pad", 0); - keyboard_device = Common::Input::CreateInputDevice(keyboard_key_params); - key_index++; - } - - key_index = 0; - for (auto& keyboard_device : keyboard_modifier_devices) { - Common::ParamPackage keyboard_moddifier_params = keyboard_params; - keyboard_moddifier_params.Set("button", static_cast<int>(key_index)); - keyboard_moddifier_params.Set("pad", 1); - keyboard_device = Common::Input::CreateInputDevice(keyboard_moddifier_params); - key_index++; - } - - for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) { - if (!mouse_button_devices[index]) { - continue; - } - mouse_button_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetMouseButton(callback, index); - }, - }); - } - - for (std::size_t index = 0; index < mouse_wheel_devices.size(); ++index) { - if (!mouse_wheel_devices[index]) { - continue; - } - mouse_wheel_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetMouseWheel(callback, index); - }, - }); - } - - if (mouse_stick_device) { - mouse_stick_device->SetCallback({ - .on_change = - [this](const Common::Input::CallbackStatus& callback) { - SetMousePosition(callback); - }, - }); - } - - for (std::size_t index = 0; index < keyboard_devices.size(); ++index) { - if (!keyboard_devices[index]) { - continue; - } - keyboard_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetKeyboardButton(callback, index); - }, - }); - } - - for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) { - if (!keyboard_modifier_devices[index]) { - continue; - } - keyboard_modifier_devices[index]->SetCallback({ - .on_change = - [this, index](const Common::Input::CallbackStatus& callback) { - SetKeyboardModifier(callback, index); - }, - }); - } -} - -void EmulatedDevices::UnloadInput() { - for (auto& button : mouse_button_devices) { - button.reset(); - } - for (auto& analog : mouse_wheel_devices) { - analog.reset(); - } - mouse_stick_device.reset(); - for (auto& button : keyboard_devices) { - button.reset(); - } - for (auto& button : keyboard_modifier_devices) { - button.reset(); - } -} - -void EmulatedDevices::EnableConfiguration() { - is_configuring = true; - SaveCurrentConfig(); -} - -void EmulatedDevices::DisableConfiguration() { - is_configuring = false; -} - -bool EmulatedDevices::IsConfiguring() const { - return is_configuring; -} - -void EmulatedDevices::SaveCurrentConfig() { - if (!is_configuring) { - return; - } -} - -void EmulatedDevices::RestoreConfig() { - if (!is_configuring) { - return; - } - ReloadFromSettings(); -} - -void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback, - std::size_t index) { - if (index >= device_status.keyboard_values.size()) { - return; - } - std::unique_lock lock{mutex}; - bool value_changed = false; - const auto new_status = TransformToButton(callback); - auto& current_status = device_status.keyboard_values[index]; - current_status.toggle = new_status.toggle; - - // Update button status with current status - if (!current_status.toggle) { - current_status.locked = false; - if (current_status.value != new_status.value) { - current_status.value = new_status.value; - value_changed = true; - } - } else { - // Toggle button and lock status - if (new_status.value && !current_status.locked) { - current_status.locked = true; - current_status.value = !current_status.value; - value_changed = true; - } - - // Unlock button, ready for next press - if (!new_status.value && current_status.locked) { - current_status.locked = false; - } - } - - if (!value_changed) { - return; - } - - if (is_configuring) { - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Keyboard); - return; - } - - // Index should be converted from NativeKeyboard to KeyboardKeyIndex - UpdateKey(index, current_status.value); - - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Keyboard); -} - -void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { - constexpr std::size_t KEYS_PER_BYTE = 8; - auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE]; - const u8 mask = static_cast<u8>(1 << (key_index % KEYS_PER_BYTE)); - if (status) { - entry = entry | mask; - } else { - entry = static_cast<u8>(entry & ~mask); - } -} - -void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& callback, - std::size_t index) { - if (index >= device_status.keyboard_moddifier_values.size()) { - return; - } - std::unique_lock lock{mutex}; - bool value_changed = false; - const auto new_status = TransformToButton(callback); - auto& current_status = device_status.keyboard_moddifier_values[index]; - current_status.toggle = new_status.toggle; - - // Update button status with current - if (!current_status.toggle) { - current_status.locked = false; - if (current_status.value != new_status.value) { - current_status.value = new_status.value; - value_changed = true; - } - } else { - // Toggle button and lock status - if (new_status.value && !current_status.locked) { - current_status.locked = true; - current_status.value = !current_status.value; - value_changed = true; - } - - // Unlock button ready for next press - if (!new_status.value && current_status.locked) { - current_status.locked = false; - } - } - - if (!value_changed) { - return; - } - - if (is_configuring) { - lock.unlock(); - TriggerOnChange(DeviceTriggerType::KeyboardModdifier); - return; - } - - switch (index) { - case Settings::NativeKeyboard::LeftControl: - case Settings::NativeKeyboard::RightControl: - device_status.keyboard_moddifier_state.control.Assign(current_status.value); - break; - case Settings::NativeKeyboard::LeftShift: - case Settings::NativeKeyboard::RightShift: - device_status.keyboard_moddifier_state.shift.Assign(current_status.value); - break; - case Settings::NativeKeyboard::LeftAlt: - device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value); - break; - case Settings::NativeKeyboard::RightAlt: - device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value); - break; - case Settings::NativeKeyboard::CapsLock: - device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value); - break; - case Settings::NativeKeyboard::ScrollLock: - device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value); - break; - case Settings::NativeKeyboard::NumLock: - device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value); - break; - } - - lock.unlock(); - TriggerOnChange(DeviceTriggerType::KeyboardModdifier); -} - -void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callback, - std::size_t index) { - if (index >= device_status.mouse_button_values.size()) { - return; - } - std::unique_lock lock{mutex}; - bool value_changed = false; - const auto new_status = TransformToButton(callback); - auto& current_status = device_status.mouse_button_values[index]; - current_status.toggle = new_status.toggle; - - // Update button status with current - if (!current_status.toggle) { - current_status.locked = false; - if (current_status.value != new_status.value) { - current_status.value = new_status.value; - value_changed = true; - } - } else { - // Toggle button and lock status - if (new_status.value && !current_status.locked) { - current_status.locked = true; - current_status.value = !current_status.value; - value_changed = true; - } - - // Unlock button ready for next press - if (!new_status.value && current_status.locked) { - current_status.locked = false; - } - } - - if (!value_changed) { - return; - } - - if (is_configuring) { - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Mouse); - return; - } - - switch (index) { - case Settings::NativeMouseButton::Left: - device_status.mouse_button_state.left.Assign(current_status.value); - break; - case Settings::NativeMouseButton::Right: - device_status.mouse_button_state.right.Assign(current_status.value); - break; - case Settings::NativeMouseButton::Middle: - device_status.mouse_button_state.middle.Assign(current_status.value); - break; - case Settings::NativeMouseButton::Forward: - device_status.mouse_button_state.forward.Assign(current_status.value); - break; - case Settings::NativeMouseButton::Back: - device_status.mouse_button_state.back.Assign(current_status.value); - break; - } - - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Mouse); -} - -void EmulatedDevices::SetMouseWheel(const Common::Input::CallbackStatus& callback, - std::size_t index) { - if (index >= device_status.mouse_wheel_values.size()) { - return; - } - std::unique_lock lock{mutex}; - const auto analog_value = TransformToAnalog(callback); - - device_status.mouse_wheel_values[index] = analog_value; - - if (is_configuring) { - device_status.mouse_wheel_state = {}; - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Mouse); - return; - } - - switch (index) { - case Settings::NativeMouseWheel::X: - device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value); - break; - case Settings::NativeMouseWheel::Y: - device_status.mouse_wheel_state.y = static_cast<s32>(analog_value.value); - break; - } - - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Mouse); -} - -void EmulatedDevices::SetMousePosition(const Common::Input::CallbackStatus& callback) { - std::unique_lock lock{mutex}; - const auto touch_value = TransformToTouch(callback); - - device_status.mouse_stick_value = touch_value; - - if (is_configuring) { - device_status.mouse_position_state = {}; - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Mouse); - return; - } - - device_status.mouse_position_state.x = touch_value.x.value; - device_status.mouse_position_state.y = touch_value.y.value; - - lock.unlock(); - TriggerOnChange(DeviceTriggerType::Mouse); -} - -KeyboardValues EmulatedDevices::GetKeyboardValues() const { - std::scoped_lock lock{mutex}; - return device_status.keyboard_values; -} - -KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const { - std::scoped_lock lock{mutex}; - return device_status.keyboard_moddifier_values; -} - -MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const { - std::scoped_lock lock{mutex}; - return device_status.mouse_button_values; -} - -KeyboardKey EmulatedDevices::GetKeyboard() const { - std::scoped_lock lock{mutex}; - return device_status.keyboard_state; -} - -KeyboardModifier EmulatedDevices::GetKeyboardModifier() const { - std::scoped_lock lock{mutex}; - return device_status.keyboard_moddifier_state; -} - -MouseButton EmulatedDevices::GetMouseButtons() const { - std::scoped_lock lock{mutex}; - return device_status.mouse_button_state; -} - -MousePosition EmulatedDevices::GetMousePosition() const { - std::scoped_lock lock{mutex}; - return device_status.mouse_position_state; -} - -AnalogStickState EmulatedDevices::GetMouseWheel() const { - std::scoped_lock lock{mutex}; - return device_status.mouse_wheel_state; -} - -void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) { - std::scoped_lock lock{callback_mutex}; - for (const auto& poller_pair : callback_list) { - const InterfaceUpdateCallback& poller = poller_pair.second; - if (poller.on_change) { - poller.on_change(type); - } - } -} - -int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) { - std::scoped_lock lock{callback_mutex}; - callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); - return last_callback_key++; -} - -void EmulatedDevices::DeleteCallback(int key) { - std::scoped_lock lock{callback_mutex}; - const auto& iterator = callback_list.find(key); - if (iterator == callback_list.end()) { - LOG_ERROR(Input, "Tried to delete non-existent callback {}", key); - return; - } - callback_list.erase(iterator); -} -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <functional> -#include <memory> -#include <mutex> -#include <unordered_map> -#include <vector> - -#include "common/common_types.h" -#include "common/input.h" -#include "common/param_package.h" -#include "common/settings.h" -#include "core/hid/hid_types.h" - -namespace Core::HID { -using KeyboardDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, - Settings::NativeKeyboard::NumKeyboardKeys>; -using KeyboardModifierDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, - Settings::NativeKeyboard::NumKeyboardMods>; -using MouseButtonDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, - Settings::NativeMouseButton::NumMouseButtons>; -using MouseWheelDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, - Settings::NativeMouseWheel::NumMouseWheels>; -using MouseStickDevice = std::unique_ptr<Common::Input::InputDevice>; - -using MouseButtonParams = - std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons>; - -using KeyboardValues = - std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardKeys>; -using KeyboardModifierValues = - std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>; -using MouseButtonValues = - std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>; -using MouseWheelValues = - std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>; -using MouseStickValue = Common::Input::TouchStatus; - -struct MousePosition { - f32 x; - f32 y; -}; - -struct DeviceStatus { - // Data from input_common - KeyboardValues keyboard_values{}; - KeyboardModifierValues keyboard_moddifier_values{}; - MouseButtonValues mouse_button_values{}; - MouseWheelValues mouse_wheel_values{}; - MouseStickValue mouse_stick_value{}; - - // Data for HID services - KeyboardKey keyboard_state{}; - KeyboardModifier keyboard_moddifier_state{}; - MouseButton mouse_button_state{}; - MousePosition mouse_position_state{}; - AnalogStickState mouse_wheel_state{}; -}; - -enum class DeviceTriggerType { - Keyboard, - KeyboardModdifier, - Mouse, - RingController, -}; - -struct InterfaceUpdateCallback { - std::function<void(DeviceTriggerType)> on_change; -}; - -class EmulatedDevices { -public: - /** - * Contains all input data related to external devices that aren't necessarily a controller - * This includes devices such as the keyboard or mouse - */ - explicit EmulatedDevices(); - ~EmulatedDevices(); - - YUZU_NON_COPYABLE(EmulatedDevices); - YUZU_NON_MOVEABLE(EmulatedDevices); - - /// Removes all callbacks created from input devices - void UnloadInput(); - - /** - * Sets the emulated devices into configuring mode - * This prevents the modification of the HID state of the emulated devices by input commands - */ - void EnableConfiguration(); - - /// Returns the emulated devices into normal mode, allowing the modification of the HID state - void DisableConfiguration(); - - /// Returns true if the emulated device is in configuring mode - bool IsConfiguring() const; - - /// Reload all input devices - void ReloadInput(); - - /// Overrides current mapped devices with the stored configuration and reloads all input devices - void ReloadFromSettings(); - - /// Saves the current mapped configuration - void SaveCurrentConfig(); - - /// Reverts any mapped changes made that weren't saved - void RestoreConfig(); - - /// Returns the latest status of button input from the keyboard with parameters - KeyboardValues GetKeyboardValues() const; - - /// Returns the latest status of button input from the keyboard modifiers with parameters - KeyboardModifierValues GetKeyboardModdifierValues() const; - - /// Returns the latest status of button input from the mouse with parameters - MouseButtonValues GetMouseButtonsValues() const; - - /// Returns the latest status of button input from the keyboard - KeyboardKey GetKeyboard() const; - - /// Returns the latest status of button input from the keyboard modifiers - KeyboardModifier GetKeyboardModifier() const; - - /// Returns the latest status of button input from the mouse - MouseButton GetMouseButtons() const; - - /// Returns the latest mouse coordinates - MousePosition GetMousePosition() const; - - /// Returns the latest mouse wheel change - AnalogStickState GetMouseWheel() const; - - /** - * Adds a callback to the list of events - * @param update_callback InterfaceUpdateCallback that will be triggered - * @return an unique key corresponding to the callback index in the list - */ - int SetCallback(InterfaceUpdateCallback update_callback); - - /** - * Removes a callback from the list stopping any future events to this object - * @param key Key corresponding to the callback index in the list - */ - void DeleteCallback(int key); - -private: - /// Helps assigning a value to keyboard_state - void UpdateKey(std::size_t key_index, bool status); - - /** - * Updates the touch status of the keyboard device - * @param callback A CallbackStatus containing the key status - * @param index key ID to be updated - */ - void SetKeyboardButton(const Common::Input::CallbackStatus& callback, std::size_t index); - - /** - * Updates the keyboard status of the keyboard device - * @param callback A CallbackStatus containing the modifier key status - * @param index modifier key ID to be updated - */ - void SetKeyboardModifier(const Common::Input::CallbackStatus& callback, std::size_t index); - - /** - * Updates the mouse button status of the mouse device - * @param callback A CallbackStatus containing the button status - * @param index Button ID to be updated - */ - void SetMouseButton(const Common::Input::CallbackStatus& callback, std::size_t index); - - /** - * Updates the mouse wheel status of the mouse device - * @param callback A CallbackStatus containing the wheel status - * @param index wheel ID to be updated - */ - void SetMouseWheel(const Common::Input::CallbackStatus& callback, std::size_t index); - - /** - * Updates the mouse position status of the mouse device - * @param callback A CallbackStatus containing the position status - */ - void SetMousePosition(const Common::Input::CallbackStatus& callback); - - /** - * Triggers a callback that something has changed on the device status - * @param type Input type of the event to trigger - */ - void TriggerOnChange(DeviceTriggerType type); - - bool is_configuring{false}; - - KeyboardDevices keyboard_devices; - KeyboardModifierDevices keyboard_modifier_devices; - MouseButtonDevices mouse_button_devices; - MouseWheelDevices mouse_wheel_devices; - MouseStickDevice mouse_stick_device; - - mutable std::mutex mutex; - mutable std::mutex callback_mutex; - std::unordered_map<int, InterfaceUpdateCallback> callback_list; - int last_callback_key = 0; - - // Stores the current status of all external device input - DeviceStatus device_status; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/assert.h" -#include "core/hid/emulated_console.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/emulated_devices.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/hid_util.h" - -namespace Core::HID { - -HIDCore::HIDCore() - : player_1{std::make_unique<EmulatedController>(NpadIdType::Player1)}, - player_2{std::make_unique<EmulatedController>(NpadIdType::Player2)}, - player_3{std::make_unique<EmulatedController>(NpadIdType::Player3)}, - player_4{std::make_unique<EmulatedController>(NpadIdType::Player4)}, - player_5{std::make_unique<EmulatedController>(NpadIdType::Player5)}, - player_6{std::make_unique<EmulatedController>(NpadIdType::Player6)}, - player_7{std::make_unique<EmulatedController>(NpadIdType::Player7)}, - player_8{std::make_unique<EmulatedController>(NpadIdType::Player8)}, - other{std::make_unique<EmulatedController>(NpadIdType::Other)}, - handheld{std::make_unique<EmulatedController>(NpadIdType::Handheld)}, - console{std::make_unique<EmulatedConsole>()}, devices{std::make_unique<EmulatedDevices>()} {} - -HIDCore::~HIDCore() = default; - -EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) { - switch (npad_id_type) { - case NpadIdType::Player1: - return player_1.get(); - case NpadIdType::Player2: - return player_2.get(); - case NpadIdType::Player3: - return player_3.get(); - case NpadIdType::Player4: - return player_4.get(); - case NpadIdType::Player5: - return player_5.get(); - case NpadIdType::Player6: - return player_6.get(); - case NpadIdType::Player7: - return player_7.get(); - case NpadIdType::Player8: - return player_8.get(); - case NpadIdType::Other: - return other.get(); - case NpadIdType::Handheld: - return handheld.get(); - case NpadIdType::Invalid: - default: - ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type); - return nullptr; - } -} - -const EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) const { - switch (npad_id_type) { - case NpadIdType::Player1: - return player_1.get(); - case NpadIdType::Player2: - return player_2.get(); - case NpadIdType::Player3: - return player_3.get(); - case NpadIdType::Player4: - return player_4.get(); - case NpadIdType::Player5: - return player_5.get(); - case NpadIdType::Player6: - return player_6.get(); - case NpadIdType::Player7: - return player_7.get(); - case NpadIdType::Player8: - return player_8.get(); - case NpadIdType::Other: - return other.get(); - case NpadIdType::Handheld: - return handheld.get(); - case NpadIdType::Invalid: - default: - ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type); - return nullptr; - } -} -EmulatedConsole* HIDCore::GetEmulatedConsole() { - return console.get(); -} - -const EmulatedConsole* HIDCore::GetEmulatedConsole() const { - return console.get(); -} - -EmulatedDevices* HIDCore::GetEmulatedDevices() { - return devices.get(); -} - -const EmulatedDevices* HIDCore::GetEmulatedDevices() const { - return devices.get(); -} - -EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) { - return GetEmulatedController(Service::HID::IndexToNpadIdType(index)); -} - -const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const { - return GetEmulatedController(Service::HID::IndexToNpadIdType(index)); -} - -void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) { - supported_style_tag.raw = style_tag.raw; - player_1->SetSupportedNpadStyleTag(supported_style_tag); - player_2->SetSupportedNpadStyleTag(supported_style_tag); - player_3->SetSupportedNpadStyleTag(supported_style_tag); - player_4->SetSupportedNpadStyleTag(supported_style_tag); - player_5->SetSupportedNpadStyleTag(supported_style_tag); - player_6->SetSupportedNpadStyleTag(supported_style_tag); - player_7->SetSupportedNpadStyleTag(supported_style_tag); - player_8->SetSupportedNpadStyleTag(supported_style_tag); - other->SetSupportedNpadStyleTag(supported_style_tag); - handheld->SetSupportedNpadStyleTag(supported_style_tag); -} - -NpadStyleTag HIDCore::GetSupportedStyleTag() const { - return supported_style_tag; -} - -s8 HIDCore::GetPlayerCount() const { - s8 active_players = 0; - for (std::size_t player_index = 0; player_index < available_controllers - 2; ++player_index) { - const auto* const controller = GetEmulatedControllerByIndex(player_index); - if (controller->IsConnected()) { - active_players++; - } - } - return active_players; -} - -NpadIdType HIDCore::GetFirstNpadId() const { - for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) { - const auto* const controller = GetEmulatedControllerByIndex(player_index); - if (controller->IsConnected()) { - return controller->GetNpadIdType(); - } - } - return NpadIdType::Player1; -} - -NpadIdType HIDCore::GetFirstDisconnectedNpadId() const { - for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) { - const auto* const controller = GetEmulatedControllerByIndex(player_index); - if (!controller->IsConnected()) { - return controller->GetNpadIdType(); - } - } - return NpadIdType::Player1; -} - -void HIDCore::SetLastActiveController(NpadIdType npad_id) { - last_active_controller = npad_id; -} - -NpadIdType HIDCore::GetLastActiveController() const { - return last_active_controller; -} - -void HIDCore::EnableAllControllerConfiguration() { - player_1->EnableConfiguration(); - player_2->EnableConfiguration(); - player_3->EnableConfiguration(); - player_4->EnableConfiguration(); - player_5->EnableConfiguration(); - player_6->EnableConfiguration(); - player_7->EnableConfiguration(); - player_8->EnableConfiguration(); - other->EnableConfiguration(); - handheld->EnableConfiguration(); -} - -void HIDCore::DisableAllControllerConfiguration() { - player_1->DisableConfiguration(); - player_2->DisableConfiguration(); - player_3->DisableConfiguration(); - player_4->DisableConfiguration(); - player_5->DisableConfiguration(); - player_6->DisableConfiguration(); - player_7->DisableConfiguration(); - player_8->DisableConfiguration(); - other->DisableConfiguration(); - handheld->DisableConfiguration(); -} - -void HIDCore::ReloadInputDevices() { - player_1->ReloadFromSettings(); - player_2->ReloadFromSettings(); - player_3->ReloadFromSettings(); - player_4->ReloadFromSettings(); - player_5->ReloadFromSettings(); - player_6->ReloadFromSettings(); - player_7->ReloadFromSettings(); - player_8->ReloadFromSettings(); - other->ReloadFromSettings(); - handheld->ReloadFromSettings(); - console->ReloadFromSettings(); - devices->ReloadFromSettings(); -} - -void HIDCore::UnloadInputDevices() { - player_1->UnloadInput(); - player_2->UnloadInput(); - player_3->UnloadInput(); - player_4->UnloadInput(); - player_5->UnloadInput(); - player_6->UnloadInput(); - player_7->UnloadInput(); - player_8->UnloadInput(); - other->UnloadInput(); - handheld->UnloadInput(); - console->UnloadInput(); - devices->UnloadInput(); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> - -#include "common/common_funcs.h" -#include "core/hid/hid_types.h" - -namespace Core::HID { -class EmulatedConsole; -class EmulatedController; -class EmulatedDevices; -} // namespace Core::HID - -namespace Core::HID { - -class HIDCore { -public: - explicit HIDCore(); - ~HIDCore(); - - YUZU_NON_COPYABLE(HIDCore); - YUZU_NON_MOVEABLE(HIDCore); - - EmulatedController* GetEmulatedController(NpadIdType npad_id_type); - const EmulatedController* GetEmulatedController(NpadIdType npad_id_type) const; - - EmulatedController* GetEmulatedControllerByIndex(std::size_t index); - const EmulatedController* GetEmulatedControllerByIndex(std::size_t index) const; - - EmulatedConsole* GetEmulatedConsole(); - const EmulatedConsole* GetEmulatedConsole() const; - - EmulatedDevices* GetEmulatedDevices(); - const EmulatedDevices* GetEmulatedDevices() const; - - void SetSupportedStyleTag(NpadStyleTag style_tag); - NpadStyleTag GetSupportedStyleTag() const; - - /// Counts the connected players from P1-P8 - s8 GetPlayerCount() const; - - /// Returns the first connected npad id - NpadIdType GetFirstNpadId() const; - - /// Returns the first disconnected npad id - NpadIdType GetFirstDisconnectedNpadId() const; - - /// Sets the npad id of the last active controller - void SetLastActiveController(NpadIdType npad_id); - - /// Returns the npad id of the last controller that pushed a button - NpadIdType GetLastActiveController() const; - - /// Sets all emulated controllers into configuring mode. - void EnableAllControllerConfiguration(); - - /// Sets all emulated controllers into normal mode. - void DisableAllControllerConfiguration(); - - /// Reloads all input devices from settings - void ReloadInputDevices(); - - /// Removes all callbacks from input common - void UnloadInputDevices(); - - /// Number of emulated controllers - static constexpr std::size_t available_controllers{10}; - -private: - std::unique_ptr<EmulatedController> player_1; - std::unique_ptr<EmulatedController> player_2; - std::unique_ptr<EmulatedController> player_3; - std::unique_ptr<EmulatedController> player_4; - std::unique_ptr<EmulatedController> player_5; - std::unique_ptr<EmulatedController> player_6; - std::unique_ptr<EmulatedController> player_7; - std::unique_ptr<EmulatedController> player_8; - std::unique_ptr<EmulatedController> other; - std::unique_ptr<EmulatedController> handheld; - std::unique_ptr<EmulatedConsole> console; - std::unique_ptr<EmulatedDevices> devices; - NpadStyleTag supported_style_tag{NpadStyleSet::All}; - NpadIdType last_active_controller{NpadIdType::Handheld}; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/bit_field.h" -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/point.h" -#include "common/uuid.h" -#include "common/vector_math.h" - -namespace Core::HID { - -enum class DeviceIndex : u8 { - Left = 0, - Right = 1, - None = 2, - MaxDeviceIndex = 3, -}; - -// This is nn::hid::NpadButton -enum class NpadButton : u64 { - None = 0, - A = 1U << 0, - B = 1U << 1, - X = 1U << 2, - Y = 1U << 3, - StickL = 1U << 4, - StickR = 1U << 5, - L = 1U << 6, - R = 1U << 7, - ZL = 1U << 8, - ZR = 1U << 9, - Plus = 1U << 10, - Minus = 1U << 11, - - Left = 1U << 12, - Up = 1U << 13, - Right = 1U << 14, - Down = 1U << 15, - - StickLLeft = 1U << 16, - StickLUp = 1U << 17, - StickLRight = 1U << 18, - StickLDown = 1U << 19, - - StickRLeft = 1U << 20, - StickRUp = 1U << 21, - StickRRight = 1U << 22, - StickRDown = 1U << 23, - - LeftSL = 1U << 24, - LeftSR = 1U << 25, - - RightSL = 1U << 26, - RightSR = 1U << 27, - - Palma = 1U << 28, - Verification = 1U << 29, - HandheldLeftB = 1U << 30, - LagonCLeft = 1U << 31, - LagonCUp = 1ULL << 32, - LagonCRight = 1ULL << 33, - LagonCDown = 1ULL << 34, - - All = 0xFFFFFFFFFFFFFFFFULL, -}; -DECLARE_ENUM_FLAG_OPERATORS(NpadButton); - -enum class KeyboardKeyIndex : u32 { - A = 4, - B = 5, - C = 6, - D = 7, - E = 8, - F = 9, - G = 10, - H = 11, - I = 12, - J = 13, - K = 14, - L = 15, - M = 16, - N = 17, - O = 18, - P = 19, - Q = 20, - R = 21, - S = 22, - T = 23, - U = 24, - V = 25, - W = 26, - X = 27, - Y = 28, - Z = 29, - D1 = 30, - D2 = 31, - D3 = 32, - D4 = 33, - D5 = 34, - D6 = 35, - D7 = 36, - D8 = 37, - D9 = 38, - D0 = 39, - Return = 40, - Escape = 41, - Backspace = 42, - Tab = 43, - Space = 44, - Minus = 45, - Plus = 46, - OpenBracket = 47, - CloseBracket = 48, - Pipe = 49, - Tilde = 50, - Semicolon = 51, - Quote = 52, - Backquote = 53, - Comma = 54, - Period = 55, - Slash = 56, - CapsLock = 57, - F1 = 58, - F2 = 59, - F3 = 60, - F4 = 61, - F5 = 62, - F6 = 63, - F7 = 64, - F8 = 65, - F9 = 66, - F10 = 67, - F11 = 68, - F12 = 69, - PrintScreen = 70, - ScrollLock = 71, - Pause = 72, - Insert = 73, - Home = 74, - PageUp = 75, - Delete = 76, - End = 77, - PageDown = 78, - RightArrow = 79, - LeftArrow = 80, - DownArrow = 81, - UpArrow = 82, - NumLock = 83, - NumPadDivide = 84, - NumPadMultiply = 85, - NumPadSubtract = 86, - NumPadAdd = 87, - NumPadEnter = 88, - NumPad1 = 89, - NumPad2 = 90, - NumPad3 = 91, - NumPad4 = 92, - NumPad5 = 93, - NumPad6 = 94, - NumPad7 = 95, - NumPad8 = 96, - NumPad9 = 97, - NumPad0 = 98, - NumPadDot = 99, - Backslash = 100, - Application = 101, - Power = 102, - NumPadEquals = 103, - F13 = 104, - F14 = 105, - F15 = 106, - F16 = 107, - F17 = 108, - F18 = 109, - F19 = 110, - F20 = 111, - F21 = 112, - F22 = 113, - F23 = 114, - F24 = 115, - NumPadComma = 133, - Ro = 135, - KatakanaHiragana = 136, - Yen = 137, - Henkan = 138, - Muhenkan = 139, - NumPadCommaPc98 = 140, - HangulEnglish = 144, - Hanja = 145, - Katakana = 146, - Hiragana = 147, - ZenkakuHankaku = 148, - LeftControl = 224, - LeftShift = 225, - LeftAlt = 226, - LeftGui = 227, - RightControl = 228, - RightShift = 229, - RightAlt = 230, - RightGui = 231, -}; - -// This is nn::hid::NpadIdType -enum class NpadIdType : u32 { - Player1 = 0x0, - Player2 = 0x1, - Player3 = 0x2, - Player4 = 0x3, - Player5 = 0x4, - Player6 = 0x5, - Player7 = 0x6, - Player8 = 0x7, - Other = 0x10, - Handheld = 0x20, - - Invalid = 0xFFFFFFFF, -}; - -enum class NpadInterfaceType : u8 { - Bluetooth = 1, - Rail = 2, - Usb = 3, - Embedded = 4, -}; - -// This is nn::hid::NpadStyleIndex -enum class NpadStyleIndex : u8 { - None = 0, - ProController = 3, - Handheld = 4, - HandheldNES = 4, - JoyconDual = 5, - JoyconLeft = 6, - JoyconRight = 7, - GameCube = 8, - Pokeball = 9, - NES = 10, - SNES = 12, - N64 = 13, - SegaGenesis = 14, - SystemExt = 32, - System = 33, - MaxNpadType = 34, -}; - -// This is nn::hid::NpadStyleSet -enum class NpadStyleSet : u32 { - None = 0, - Fullkey = 1U << 0, - Handheld = 1U << 1, - JoyDual = 1U << 2, - JoyLeft = 1U << 3, - JoyRight = 1U << 4, - Gc = 1U << 5, - Palma = 1U << 6, - Lark = 1U << 7, - HandheldLark = 1U << 8, - Lucia = 1U << 9, - Lagoon = 1U << 10, - Lager = 1U << 11, - SystemExt = 1U << 29, - System = 1U << 30, - - All = 0xFFFFFFFFU, -}; -static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); -DECLARE_ENUM_FLAG_OPERATORS(NpadStyleSet) - -// This is nn::hid::VibrationDevicePosition -enum class VibrationDevicePosition : u32 { - None = 0, - Left = 1, - Right = 2, -}; - -// This is nn::hid::VibrationDeviceType -enum class VibrationDeviceType : u32 { - Unknown = 0, - LinearResonantActuator = 1, - GcErm = 2, - N64 = 3, -}; - -// This is nn::hid::VibrationGcErmCommand -enum class VibrationGcErmCommand : u64 { - Stop = 0, - Start = 1, - StopHard = 2, -}; - -// This is nn::hid::GyroscopeZeroDriftMode -enum class GyroscopeZeroDriftMode : u32 { - Loose = 0, - Standard = 1, - Tight = 2, -}; - -// This is nn::settings::system::TouchScreenMode -enum class TouchScreenMode : u32 { - Stylus = 0, - Standard = 1, -}; - -// This is nn::hid::TouchScreenModeForNx -enum class TouchScreenModeForNx : u8 { - UseSystemSetting, - Finger, - Heat2, -}; - -// This is nn::hid::system::NpadBatteryLevel -enum class NpadBatteryLevel : u32 { - Empty, - Critical, - Low, - High, - Full, -}; - -// This is nn::hid::NpadStyleTag -struct NpadStyleTag { - union { - NpadStyleSet raw{}; - - BitField<0, 1, u32> fullkey; - BitField<1, 1, u32> handheld; - BitField<2, 1, u32> joycon_dual; - BitField<3, 1, u32> joycon_left; - BitField<4, 1, u32> joycon_right; - BitField<5, 1, u32> gamecube; - BitField<6, 1, u32> palma; - BitField<7, 1, u32> lark; - BitField<8, 1, u32> handheld_lark; - BitField<9, 1, u32> lucia; - BitField<10, 1, u32> lagoon; - BitField<11, 1, u32> lager; - BitField<29, 1, u32> system_ext; - BitField<30, 1, u32> system; - }; -}; -static_assert(sizeof(NpadStyleTag) == 4, "NpadStyleTag is an invalid size"); - -// This is nn::hid::TouchAttribute -struct TouchAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> start_touch; - BitField<1, 1, u32> end_touch; - }; -}; -static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"); - -// This is nn::hid::TouchState -struct TouchState { - u64 delta_time{}; - TouchAttribute attribute{}; - u32 finger{}; - Common::Point<u32> position{}; - u32 diameter_x{}; - u32 diameter_y{}; - u32 rotation_angle{}; -}; -static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); - -struct TouchFinger { - u64 last_touch{}; - Common::Point<float> position{}; - u32 id{}; - TouchAttribute attribute{}; - bool pressed{}; -}; - -// This is nn::hid::TouchScreenConfigurationForNx -struct TouchScreenConfigurationForNx { - TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting}; - INSERT_PADDING_BYTES(0xF); -}; -static_assert(sizeof(TouchScreenConfigurationForNx) == 0x10, - "TouchScreenConfigurationForNx is an invalid size"); - -struct NpadColor { - u8 r{}; - u8 g{}; - u8 b{}; - u8 a{}; -}; -static_assert(sizeof(NpadColor) == 4, "NpadColor is an invalid size"); - -// This is nn::hid::NpadControllerColor -struct NpadControllerColor { - NpadColor body{}; - NpadColor button{}; -}; -static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); - -// This is nn::hid::AnalogStickState -struct AnalogStickState { - s32 x{}; - s32 y{}; -}; -static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size"); - -// This is nn::hid::server::NpadGcTriggerState -struct NpadGcTriggerState { - s64 sampling_number{}; - s32 left{}; - s32 right{}; -}; -static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); - -// This is nn::hid::system::NpadPowerInfo -struct NpadPowerInfo { - bool is_powered{}; - bool is_charging{}; - INSERT_PADDING_BYTES(0x6); - NpadBatteryLevel battery_level{NpadBatteryLevel::Full}; -}; -static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); - -struct LedPattern { - explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { - position1.Assign(light1); - position2.Assign(light2); - position3.Assign(light3); - position4.Assign(light4); - } - union { - u64 raw{}; - BitField<0, 1, u64> position1; - BitField<1, 1, u64> position2; - BitField<2, 1, u64> position3; - BitField<3, 1, u64> position4; - }; -}; - -struct HomeButtonState { - union { - u64 raw{}; - - // Buttons - BitField<0, 1, u64> home; - }; -}; -static_assert(sizeof(HomeButtonState) == 0x8, "HomeButtonState has incorrect size."); - -struct CaptureButtonState { - union { - u64 raw{}; - - // Buttons - BitField<0, 1, u64> capture; - }; -}; -static_assert(sizeof(CaptureButtonState) == 0x8, "CaptureButtonState has incorrect size."); - -struct NpadButtonState { - union { - NpadButton raw{}; - - // Buttons - BitField<0, 1, u64> a; - BitField<1, 1, u64> b; - BitField<2, 1, u64> x; - BitField<3, 1, u64> y; - BitField<4, 1, u64> stick_l; - BitField<5, 1, u64> stick_r; - BitField<6, 1, u64> l; - BitField<7, 1, u64> r; - BitField<8, 1, u64> zl; - BitField<9, 1, u64> zr; - BitField<10, 1, u64> plus; - BitField<11, 1, u64> minus; - - // D-Pad - BitField<12, 1, u64> left; - BitField<13, 1, u64> up; - BitField<14, 1, u64> right; - BitField<15, 1, u64> down; - - // Left JoyStick - BitField<16, 1, u64> stick_l_left; - BitField<17, 1, u64> stick_l_up; - BitField<18, 1, u64> stick_l_right; - BitField<19, 1, u64> stick_l_down; - - // Right JoyStick - BitField<20, 1, u64> stick_r_left; - BitField<21, 1, u64> stick_r_up; - BitField<22, 1, u64> stick_r_right; - BitField<23, 1, u64> stick_r_down; - - BitField<24, 1, u64> left_sl; - BitField<25, 1, u64> left_sr; - - BitField<26, 1, u64> right_sl; - BitField<27, 1, u64> right_sr; - - BitField<28, 1, u64> palma; - BitField<29, 1, u64> verification; - BitField<30, 1, u64> handheld_left_b; - BitField<31, 1, u64> lagon_c_left; - BitField<32, 1, u64> lagon_c_up; - BitField<33, 1, u64> lagon_c_right; - BitField<34, 1, u64> lagon_c_down; - }; -}; -static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect size."); - -// This is nn::hid::DebugPadButton -struct DebugPadButton { - union { - u32 raw{}; - BitField<0, 1, u32> a; - BitField<1, 1, u32> b; - BitField<2, 1, u32> x; - BitField<3, 1, u32> y; - BitField<4, 1, u32> l; - BitField<5, 1, u32> r; - BitField<6, 1, u32> zl; - BitField<7, 1, u32> zr; - BitField<8, 1, u32> plus; - BitField<9, 1, u32> minus; - BitField<10, 1, u32> d_left; - BitField<11, 1, u32> d_up; - BitField<12, 1, u32> d_right; - BitField<13, 1, u32> d_down; - }; -}; -static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); - -// This is nn::hid::ConsoleSixAxisSensorHandle -struct ConsoleSixAxisSensorHandle { - u8 unknown_1{}; - u8 unknown_2{}; - INSERT_PADDING_BYTES_NOINIT(2); -}; -static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4, - "ConsoleSixAxisSensorHandle is an invalid size"); - -// This is nn::hid::SixAxisSensorHandle -struct SixAxisSensorHandle { - NpadStyleIndex npad_type{NpadStyleIndex::None}; - u8 npad_id{}; - DeviceIndex device_index{DeviceIndex::None}; - INSERT_PADDING_BYTES_NOINIT(1); -}; -static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size"); - -// These parameters seem related to how much gyro/accelerometer is used -struct SixAxisSensorFusionParameters { - f32 parameter1{0.03f}; // Range 0.0 to 1.0, default 0.03 - f32 parameter2{0.4f}; // Default 0.4 -}; -static_assert(sizeof(SixAxisSensorFusionParameters) == 8, - "SixAxisSensorFusionParameters is an invalid size"); - -// This is nn::hid::server::SixAxisSensorProperties -struct SixAxisSensorProperties { - union { - u8 raw{}; - BitField<0, 1, u8> is_newly_assigned; - BitField<1, 1, u8> is_firmware_update_available; - }; -}; -static_assert(sizeof(SixAxisSensorProperties) == 1, "SixAxisSensorProperties is an invalid size"); - -// This is nn::hid::SixAxisSensorCalibrationParameter -struct SixAxisSensorCalibrationParameter { - std::array<u8, 0x744> unknown_data{}; -}; -static_assert(sizeof(SixAxisSensorCalibrationParameter) == 0x744, - "SixAxisSensorCalibrationParameter is an invalid size"); - -// This is nn::hid::SixAxisSensorIcInformation -struct SixAxisSensorIcInformation { - f32 angular_rate{2000.0f}; // dps - std::array<f32, 6> unknown_gyro_data1{ - -10.0f, -10.0f, -10.0f, 10.0f, 10.0f, 10.0f, - }; // dps - std::array<f32, 9> unknown_gyro_data2{ - 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, - }; - std::array<f32, 9> unknown_gyro_data3{ - 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, - }; - f32 acceleration_range{8.0f}; // g force - std::array<f32, 6> unknown_accel_data1{ - -0.0612f, -0.0612f, -0.0612f, 0.0612f, 0.0612f, 0.0612f, - }; // g force - std::array<f32, 9> unknown_accel_data2{ - 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f, - }; - std::array<f32, 9> unknown_accel_data3{ - 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f, - }; -}; -static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8, - "SixAxisSensorIcInformation is an invalid size"); - -// This is nn::hid::SixAxisSensorAttribute -struct SixAxisSensorAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> is_connected; - BitField<1, 1, u32> is_interpolated; - }; -}; -static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size"); - -// This is nn::hid::SixAxisSensorState -struct SixAxisSensorState { - s64 delta_time{}; - s64 sampling_number{}; - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Vec3f rotation{}; - std::array<Common::Vec3f, 3> orientation{}; - SixAxisSensorAttribute attribute{}; - INSERT_PADDING_BYTES(4); // Reserved -}; -static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size"); - -// This is nn::hid::VibrationDeviceHandle -struct VibrationDeviceHandle { - NpadStyleIndex npad_type{NpadStyleIndex::None}; - u8 npad_id{}; - DeviceIndex device_index{DeviceIndex::None}; - INSERT_PADDING_BYTES_NOINIT(1); -}; -static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size"); - -// This is nn::hid::VibrationValue -struct VibrationValue { - f32 low_amplitude{}; - f32 low_frequency{}; - f32 high_amplitude{}; - f32 high_frequency{}; -}; -static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); - -constexpr VibrationValue DEFAULT_VIBRATION_VALUE{ - .low_amplitude = 0.0f, - .low_frequency = 160.0f, - .high_amplitude = 0.0f, - .high_frequency = 320.0f, -}; - -// This is nn::hid::VibrationDeviceInfo -struct VibrationDeviceInfo { - VibrationDeviceType type{}; - VibrationDevicePosition position{}; -}; -static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); - -// This is nn::hid::KeyboardModifier -struct KeyboardModifier { - union { - u32 raw{}; - BitField<0, 1, u32> control; - BitField<1, 1, u32> shift; - BitField<2, 1, u32> left_alt; - BitField<3, 1, u32> right_alt; - BitField<4, 1, u32> gui; - BitField<8, 1, u32> caps_lock; - BitField<9, 1, u32> scroll_lock; - BitField<10, 1, u32> num_lock; - BitField<11, 1, u32> katakana; - BitField<12, 1, u32> hiragana; - }; -}; - -static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size"); - -// This is nn::hid::KeyboardAttribute -struct KeyboardAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> is_connected; - }; -}; -static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid size"); - -// This is nn::hid::KeyboardKey -struct KeyboardKey { - // This should be a 256 bit flag - std::array<u8, 32> key{}; -}; -static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size"); - -// This is nn::hid::MouseButton -struct MouseButton { - union { - u32_le raw{}; - BitField<0, 1, u32> left; - BitField<1, 1, u32> right; - BitField<2, 1, u32> middle; - BitField<3, 1, u32> forward; - BitField<4, 1, u32> back; - }; -}; -static_assert(sizeof(MouseButton) == 0x4, "MouseButton is an invalid size"); - -// This is nn::hid::MouseAttribute -struct MouseAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> transferable; - BitField<1, 1, u32> is_connected; - }; -}; -static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size"); - -// This is nn::hid::detail::MouseState -struct MouseState { - s64 sampling_number{}; - s32 x{}; - s32 y{}; - s32 delta_x{}; - s32 delta_y{}; - // Axis Order in HW is switched for the wheel - s32 delta_wheel_y{}; - s32 delta_wheel_x{}; - MouseButton button{}; - MouseAttribute attribute{}; -}; -static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); - -struct UniquePadId { - u64 id; -}; -static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size"); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <random> - -#include "common/input.h" -#include "core/hid/input_converter.h" - -namespace Core::HID { - -Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback) { - Common::Input::BatteryStatus battery{Common::Input::BatteryStatus::None}; - switch (callback.type) { - case Common::Input::InputType::Analog: - case Common::Input::InputType::Trigger: { - const auto value = TransformToTrigger(callback).analog.value; - battery = Common::Input::BatteryLevel::Empty; - if (value > 0.2f) { - battery = Common::Input::BatteryLevel::Critical; - } - if (value > 0.4f) { - battery = Common::Input::BatteryLevel::Low; - } - if (value > 0.6f) { - battery = Common::Input::BatteryLevel::Medium; - } - if (value > 0.8f) { - battery = Common::Input::BatteryLevel::Full; - } - if (value >= 0.95f) { - battery = Common::Input::BatteryLevel::Charging; - } - break; - } - case Common::Input::InputType::Button: - battery = callback.button_status.value ? Common::Input::BatteryLevel::Charging - : Common::Input::BatteryLevel::Critical; - break; - case Common::Input::InputType::Battery: - battery = callback.battery_status; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to battery not implemented", callback.type); - break; - } - - return battery; -} - -Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback) { - Common::Input::ButtonStatus status{}; - switch (callback.type) { - case Common::Input::InputType::Analog: - status.value = TransformToTrigger(callback).pressed.value; - status.toggle = callback.analog_status.properties.toggle; - status.inverted = callback.analog_status.properties.inverted_button; - break; - case Common::Input::InputType::Trigger: - status.value = TransformToTrigger(callback).pressed.value; - break; - case Common::Input::InputType::Button: - status = callback.button_status; - break; - case Common::Input::InputType::Motion: - status.value = std::abs(callback.motion_status.gyro.x.raw_value) > 1.0f; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to button not implemented", callback.type); - break; - } - - if (status.inverted) { - status.value = !status.value; - } - - return status; -} - -Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback) { - Common::Input::MotionStatus status{}; - switch (callback.type) { - case Common::Input::InputType::Button: { - Common::Input::AnalogProperties properties{ - .deadzone = 0.0f, - .range = 1.0f, - .offset = 0.0f, - }; - status.delta_timestamp = 1000; - status.force_update = true; - status.accel.x = { - .value = 0.0f, - .raw_value = 0.0f, - .properties = properties, - }; - status.accel.y = { - .value = 0.0f, - .raw_value = 0.0f, - .properties = properties, - }; - status.accel.z = { - .value = 0.0f, - .raw_value = -1.0f, - .properties = properties, - }; - status.gyro.x = { - .value = 0.0f, - .raw_value = 0.0f, - .properties = properties, - }; - status.gyro.y = { - .value = 0.0f, - .raw_value = 0.0f, - .properties = properties, - }; - status.gyro.z = { - .value = 0.0f, - .raw_value = 0.0f, - .properties = properties, - }; - if (TransformToButton(callback).value) { - std::random_device device; - std::mt19937 gen(device()); - std::uniform_int_distribution<s16> distribution(-5000, 5000); - status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; - status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; - status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; - status.gyro.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; - status.gyro.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; - status.gyro.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; - } - break; - } - case Common::Input::InputType::Motion: - status = callback.motion_status; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to motion not implemented", callback.type); - break; - } - SanitizeAnalog(status.accel.x, false); - SanitizeAnalog(status.accel.y, false); - SanitizeAnalog(status.accel.z, false); - SanitizeAnalog(status.gyro.x, false); - SanitizeAnalog(status.gyro.y, false); - SanitizeAnalog(status.gyro.z, false); - - return status; -} - -Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback) { - Common::Input::StickStatus status{}; - - switch (callback.type) { - case Common::Input::InputType::Stick: - status = callback.stick_status; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to stick not implemented", callback.type); - break; - } - - SanitizeStick(status.x, status.y, true); - const auto& properties_x = status.x.properties; - const auto& properties_y = status.y.properties; - const float x = status.x.value; - const float y = status.y.value; - - // Set directional buttons - status.right = x > properties_x.threshold; - status.left = x < -properties_x.threshold; - status.up = y > properties_y.threshold; - status.down = y < -properties_y.threshold; - - return status; -} - -Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback) { - Common::Input::TouchStatus status{}; - - switch (callback.type) { - case Common::Input::InputType::Touch: - status = callback.touch_status; - break; - case Common::Input::InputType::Stick: - status.x = callback.stick_status.x; - status.y = callback.stick_status.y; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type); - break; - } - - SanitizeAnalog(status.x, true); - SanitizeAnalog(status.y, true); - float& x = status.x.value; - float& y = status.y.value; - - // Adjust if value is inverted - x = status.x.properties.inverted ? 1.0f + x : x; - y = status.y.properties.inverted ? 1.0f + y : y; - - // clamp value - x = std::clamp(x, 0.0f, 1.0f); - y = std::clamp(y, 0.0f, 1.0f); - - if (status.pressed.inverted) { - status.pressed.value = !status.pressed.value; - } - - return status; -} - -Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback) { - Common::Input::TriggerStatus status{}; - float& raw_value = status.analog.raw_value; - bool calculate_button_value = true; - - switch (callback.type) { - case Common::Input::InputType::Analog: - status.analog.properties = callback.analog_status.properties; - raw_value = callback.analog_status.raw_value; - break; - case Common::Input::InputType::Button: - status.analog.properties.range = 1.0f; - status.analog.properties.inverted = callback.button_status.inverted; - raw_value = callback.button_status.value ? 1.0f : 0.0f; - break; - case Common::Input::InputType::Trigger: - status = callback.trigger_status; - calculate_button_value = false; - break; - case Common::Input::InputType::Motion: - status.analog.properties.range = 1.0f; - raw_value = callback.motion_status.accel.x.raw_value; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to trigger not implemented", callback.type); - break; - } - - SanitizeAnalog(status.analog, true); - const auto& properties = status.analog.properties; - float& value = status.analog.value; - - // Set button status - if (calculate_button_value) { - status.pressed.value = value > properties.threshold; - } - - // Adjust if value is inverted - value = properties.inverted ? 1.0f + value : value; - - // clamp value - value = std::clamp(value, 0.0f, 1.0f); - - return status; -} - -Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback) { - Common::Input::AnalogStatus status{}; - - switch (callback.type) { - case Common::Input::InputType::Analog: - status.properties = callback.analog_status.properties; - status.raw_value = callback.analog_status.raw_value; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to analog not implemented", callback.type); - break; - } - - SanitizeAnalog(status, false); - - // Adjust if value is inverted - status.value = status.properties.inverted ? -status.value : status.value; - - return status; -} - -Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatus& callback) { - Common::Input::CameraStatus camera{}; - switch (callback.type) { - case Common::Input::InputType::IrSensor: - camera = { - .format = callback.camera_status, - .data = callback.raw_data, - }; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to camera not implemented", callback.type); - break; - } - - return camera; -} - -Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& callback) { - Common::Input::NfcStatus nfc{}; - switch (callback.type) { - case Common::Input::InputType::Nfc: - return callback.nfc_status; - default: - LOG_ERROR(Input, "Conversion from type {} to NFC not implemented", callback.type); - break; - } - - return nfc; -} - -Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback) { - switch (callback.type) { - case Common::Input::InputType::Color: - return callback.color_status; - break; - default: - LOG_ERROR(Input, "Conversion from type {} to color not implemented", callback.type); - return {}; - break; - } -} - -void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { - const auto& properties = analog.properties; - float& raw_value = analog.raw_value; - float& value = analog.value; - - if (!std::isnormal(raw_value)) { - raw_value = 0; - } - - // Apply center offset - raw_value -= properties.offset; - - // Set initial values to be formatted - value = raw_value; - - // Calculate vector size - const float r = std::abs(value); - - // Return zero if value is smaller than the deadzone - if (r <= properties.deadzone || properties.deadzone == 1.0f) { - analog.value = 0; - return; - } - - // Adjust range of value - const float deadzone_factor = - 1.0f / r * (r - properties.deadzone) / (1.0f - properties.deadzone); - value = value * deadzone_factor / properties.range; - - // Invert direction if needed - if (properties.inverted) { - value = -value; - } - - // Clamp value - if (clamp_value) { - value = std::clamp(value, -1.0f, 1.0f); - } -} - -void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, - bool clamp_value) { - const auto& properties_x = analog_x.properties; - const auto& properties_y = analog_y.properties; - float& raw_x = analog_x.raw_value; - float& raw_y = analog_y.raw_value; - float& x = analog_x.value; - float& y = analog_y.value; - - if (!std::isnormal(raw_x)) { - raw_x = 0; - } - if (!std::isnormal(raw_y)) { - raw_y = 0; - } - - // Apply center offset - raw_x += properties_x.offset; - raw_y += properties_y.offset; - - // Apply X scale correction from offset - if (std::abs(properties_x.offset) < 0.75f) { - if (raw_x > 0) { - raw_x /= 1 + properties_x.offset; - } else { - raw_x /= 1 - properties_x.offset; - } - } - - // Apply Y scale correction from offset - if (std::abs(properties_y.offset) < 0.75f) { - if (raw_y > 0) { - raw_y /= 1 + properties_y.offset; - } else { - raw_y /= 1 - properties_y.offset; - } - } - - // Invert direction if needed - raw_x = properties_x.inverted ? -raw_x : raw_x; - raw_y = properties_y.inverted ? -raw_y : raw_y; - - // Set initial values to be formatted - x = raw_x; - y = raw_y; - - // Calculate vector size - float r = x * x + y * y; - r = std::sqrt(r); - - // TODO(German77): Use deadzone and range of both axis - - // Return zero if values are smaller than the deadzone - if (r <= properties_x.deadzone || properties_x.deadzone >= 1.0f) { - x = 0; - y = 0; - return; - } - - // Adjust range of joystick - const float deadzone_factor = - 1.0f / r * (r - properties_x.deadzone) / (1.0f - properties_x.deadzone); - x = x * deadzone_factor / properties_x.range; - y = y * deadzone_factor / properties_x.range; - r = r * deadzone_factor / properties_x.range; - - // Normalize joystick - if (clamp_value && r > 1.0f) { - x /= r; - y /= r; - } -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -namespace Common::Input { -struct CallbackStatus; -enum class BatteryLevel : u32; -using BatteryStatus = BatteryLevel; -struct AnalogStatus; -struct ButtonStatus; -struct MotionStatus; -struct StickStatus; -struct TouchStatus; -struct TriggerStatus; -}; // namespace Common::Input - -namespace Core::HID { - -/** - * Converts raw input data into a valid battery status. - * - * @param callback Supported callbacks: Analog, Battery, Trigger. - * @return A valid BatteryStatus object. - */ -Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid button status. Applies invert properties to the output. - * - * @param callback Supported callbacks: Analog, Button, Trigger. - * @return A valid TouchStatus object. - */ -Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid motion status. - * - * @param callback Supported callbacks: Motion. - * @return A valid TouchStatus object. - */ -Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert - * properties to the output. - * - * @param callback Supported callbacks: Stick. - * @return A valid StickStatus object. - */ -Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid touch status. - * - * @param callback Supported callbacks: Touch. - * @return A valid TouchStatus object. - */ -Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and - * invert properties to the output. Button status uses the threshold property if necessary. - * - * @param callback Supported callbacks: Analog, Button, Trigger. - * @return A valid TriggerStatus object. - */ -Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid analog status. Applies offset, deadzone, range and - * invert properties to the output. - * - * @param callback Supported callbacks: Analog. - * @return A valid AnalogStatus object. - */ -Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid camera status. - * - * @param callback Supported callbacks: Camera. - * @return A valid CameraObject object. - */ -Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid nfc status. - * - * @param callback Supported callbacks: Nfc. - * @return A valid data tag vector. - */ -Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw input data into a valid color status. - * - * @param callback Supported callbacks: Color. - * @return A valid Color object. - */ -Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback); - -/** - * Converts raw analog data into a valid analog value - * @param analog An analog object containing raw data and properties - * @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f. - */ -void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value); - -/** - * Converts raw stick data into a valid stick value - * @param analog_x raw analog data and properties for the x-axis - * @param analog_y raw analog data and properties for the y-axis - * @param clamp_value bool that determines if the value needs to be clamped into the unit circle. - */ -void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, - bool clamp_value); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hid/input_interpreter.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/hid_server.h" -#include "core/hle/service/hid/resource_manager.h" -#include "core/hle/service/sm/sm.h" - -InputInterpreter::InputInterpreter(Core::System& system) - : npad{system.ServiceManager() - .GetService<Service::HID::IHidServer>("hid") - ->GetResourceManager() - ->GetNpad()} { - ResetButtonStates(); -} - -InputInterpreter::~InputInterpreter() = default; - -void InputInterpreter::PollInput() { - if (npad == nullptr) { - return; - } - const auto button_state = npad->GetAndResetPressState(); - - previous_index = current_index; - current_index = (current_index + 1) % button_states.size(); - - button_states[current_index] = button_state; -} - -void InputInterpreter::ResetButtonStates() { - previous_index = 0; - current_index = 0; - - button_states[0] = Core::HID::NpadButton::All; - - for (std::size_t i = 1; i < button_states.size(); ++i) { - button_states[i] = Core::HID::NpadButton::None; - } -} - -bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const { - return True(button_states[current_index] & button); -} - -bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const { - const bool current_press = True(button_states[current_index] & button); - const bool previous_press = True(button_states[previous_index] & button); - - return current_press && !previous_press; -} - -bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const { - Core::HID::NpadButton held_buttons{button_states[0]}; - - for (std::size_t i = 1; i < button_states.size(); ++i) { - held_buttons &= button_states[i]; - } - - return True(held_buttons & button); -} 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 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> - -#include "common/common_types.h" - -namespace Core { -class System; -} - -namespace Core::HID { -enum class NpadButton : u64; -} - -namespace Service::HID { -class NPad; -} - -/** - * The InputInterpreter class interfaces with HID to retrieve button press states. - * Input is intended to be polled every 50ms so that a button is considered to be - * held down after 400ms has elapsed since the initial button press and subsequent - * repeated presses occur every 50ms. - */ -class InputInterpreter { -public: - explicit InputInterpreter(Core::System& system); - virtual ~InputInterpreter(); - - /// Gets a button state from HID and inserts it into the array of button states. - void PollInput(); - - /// Resets all the button states to their defaults. - void ResetButtonStates(); - - /** - * Checks whether the button is pressed. - * - * @param button The button to check. - * - * @returns True when the button is pressed. - */ - [[nodiscard]] bool IsButtonPressed(Core::HID::NpadButton button) const; - - /** - * Checks whether any of the buttons in the parameter list is pressed. - * - * @tparam HIDButton The buttons to check. - * - * @returns True when at least one of the buttons is pressed. - */ - template <Core::HID::NpadButton... T> - [[nodiscard]] bool IsAnyButtonPressed() { - return (IsButtonPressed(T) || ...); - } - - /** - * The specified button is considered to be pressed once - * if it is currently pressed and not pressed previously. - * - * @param button The button to check. - * - * @returns True when the button is pressed once. - */ - [[nodiscard]] bool IsButtonPressedOnce(Core::HID::NpadButton button) const; - - /** - * Checks whether any of the buttons in the parameter list is pressed once. - * - * @tparam T The buttons to check. - * - * @returns True when at least one of the buttons is pressed once. - */ - template <Core::HID::NpadButton... T> - [[nodiscard]] bool IsAnyButtonPressedOnce() const { - return (IsButtonPressedOnce(T) || ...); - } - - /** - * The specified button is considered to be held down if it is pressed in all 9 button states. - * - * @param button The button to check. - * - * @returns True when the button is held down. - */ - [[nodiscard]] bool IsButtonHeld(Core::HID::NpadButton button) const; - - /** - * Checks whether any of the buttons in the parameter list is held down. - * - * @tparam T The buttons to check. - * - * @returns True when at least one of the buttons is held down. - */ - template <Core::HID::NpadButton... T> - [[nodiscard]] bool IsAnyButtonHeld() const { - return (IsButtonHeld(T) || ...); - } - -private: - std::shared_ptr<Service::HID::NPad> npad; - - /// Stores 9 consecutive button states polled from HID. - std::array<Core::HID::NpadButton, 9> button_states{}; - - std::size_t previous_index{}; - std::size_t current_index{}; -}; 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "core/hid/hid_types.h" - -namespace Core::IrSensor { - -// This is nn::irsensor::CameraAmbientNoiseLevel -enum class CameraAmbientNoiseLevel : u32 { - Low, - Medium, - High, - Unknown3, // This level can't be reached -}; - -// This is nn::irsensor::CameraLightTarget -enum class CameraLightTarget : u32 { - AllLeds, - BrightLeds, - DimLeds, - None, -}; - -// This is nn::irsensor::PackedCameraLightTarget -enum class PackedCameraLightTarget : u8 { - AllLeds, - BrightLeds, - DimLeds, - None, -}; - -// This is nn::irsensor::AdaptiveClusteringMode -enum class AdaptiveClusteringMode : u32 { - StaticFov, - DynamicFov, -}; - -// This is nn::irsensor::AdaptiveClusteringTargetDistance -enum class AdaptiveClusteringTargetDistance : u32 { - Near, - Middle, - Far, -}; - -// This is nn::irsensor::ImageTransferProcessorFormat -enum class ImageTransferProcessorFormat : u32 { - Size320x240, - Size160x120, - Size80x60, - Size40x30, - Size20x15, -}; - -// This is nn::irsensor::PackedImageTransferProcessorFormat -enum class PackedImageTransferProcessorFormat : u8 { - Size320x240, - Size160x120, - Size80x60, - Size40x30, - Size20x15, -}; - -// This is nn::irsensor::IrCameraStatus -enum class IrCameraStatus : u32 { - Available, - Unsupported, - Unconnected, -}; - -// This is nn::irsensor::IrCameraInternalStatus -enum class IrCameraInternalStatus : u32 { - Stopped, - FirmwareUpdateNeeded, - Unknown2, - Unknown3, - Unknown4, - FirmwareVersionRequested, - FirmwareVersionIsInvalid, - Ready, - Setting, -}; - -// This is nn::irsensor::detail::StatusManager::IrSensorMode -enum class IrSensorMode : u64 { - None, - MomentProcessor, - ClusteringProcessor, - ImageTransferProcessor, - PointingProcessorMarker, - TeraPluginProcessor, - IrLedProcessor, -}; - -// This is nn::irsensor::ImageProcessorStatus -enum ImageProcessorStatus : u32 { - Stopped, - Running, -}; - -// This is nn::irsensor::HandAnalysisMode -enum class HandAnalysisMode : u32 { - None, - Silhouette, - Image, - SilhoueteAndImage, - SilhuetteOnly, -}; - -// This is nn::irsensor::IrSensorFunctionLevel -enum class IrSensorFunctionLevel : u8 { - unknown0, - unknown1, - unknown2, - unknown3, - unknown4, -}; - -// This is nn::irsensor::MomentProcessorPreprocess -enum class MomentProcessorPreprocess : u32 { - Unknown0, - Unknown1, -}; - -// This is nn::irsensor::PackedMomentProcessorPreprocess -enum class PackedMomentProcessorPreprocess : u8 { - Unknown0, - Unknown1, -}; - -// This is nn::irsensor::PointingStatus -enum class PointingStatus : u32 { - Unknown0, - Unknown1, -}; - -struct IrsRect { - s16 x; - s16 y; - s16 width; - s16 height; -}; - -struct IrsCentroid { - f32 x; - f32 y; -}; - -struct CameraConfig { - u64 exposure_time; - CameraLightTarget light_target; - u32 gain; - bool is_negative_used; - INSERT_PADDING_BYTES(7); -}; -static_assert(sizeof(CameraConfig) == 0x18, "CameraConfig is an invalid size"); - -struct PackedCameraConfig { - u64 exposure_time; - PackedCameraLightTarget light_target; - u8 gain; - bool is_negative_used; - INSERT_PADDING_BYTES(5); -}; -static_assert(sizeof(PackedCameraConfig) == 0x10, "PackedCameraConfig is an invalid size"); - -// This is nn::irsensor::IrCameraHandle -struct IrCameraHandle { - u8 npad_id{}; - Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; - INSERT_PADDING_BYTES(2); -}; -static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size"); - -// This is nn::irsensor::PackedMcuVersion -struct PackedMcuVersion { - u16 major; - u16 minor; -}; -static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size"); - -// This is nn::irsensor::PackedMomentProcessorConfig -struct PackedMomentProcessorConfig { - PackedCameraConfig camera_config; - IrsRect window_of_interest; - PackedMcuVersion required_mcu_version; - PackedMomentProcessorPreprocess preprocess; - u8 preprocess_intensity_threshold; - INSERT_PADDING_BYTES(2); -}; -static_assert(sizeof(PackedMomentProcessorConfig) == 0x20, - "PackedMomentProcessorConfig is an invalid size"); - -// This is nn::irsensor::PackedClusteringProcessorConfig -struct PackedClusteringProcessorConfig { - PackedCameraConfig camera_config; - IrsRect window_of_interest; - PackedMcuVersion required_mcu_version; - u32 pixel_count_min; - u32 pixel_count_max; - u8 object_intensity_min; - bool is_external_light_filter_enabled; - INSERT_PADDING_BYTES(2); -}; -static_assert(sizeof(PackedClusteringProcessorConfig) == 0x28, - "PackedClusteringProcessorConfig is an invalid size"); - -// This is nn::irsensor::PackedImageTransferProcessorConfig -struct PackedImageTransferProcessorConfig { - PackedCameraConfig camera_config; - PackedMcuVersion required_mcu_version; - PackedImageTransferProcessorFormat format; - INSERT_PADDING_BYTES(3); -}; -static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18, - "PackedImageTransferProcessorConfig is an invalid size"); - -// This is nn::irsensor::PackedTeraPluginProcessorConfig -struct PackedTeraPluginProcessorConfig { - PackedMcuVersion required_mcu_version; - u8 mode; - u8 unknown_1; - u8 unknown_2; - u8 unknown_3; -}; -static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8, - "PackedTeraPluginProcessorConfig is an invalid size"); - -// This is nn::irsensor::PackedPointingProcessorConfig -struct PackedPointingProcessorConfig { - IrsRect window_of_interest; - PackedMcuVersion required_mcu_version; -}; -static_assert(sizeof(PackedPointingProcessorConfig) == 0xC, - "PackedPointingProcessorConfig is an invalid size"); - -// This is nn::irsensor::PackedFunctionLevel -struct PackedFunctionLevel { - IrSensorFunctionLevel function_level; - INSERT_PADDING_BYTES(3); -}; -static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size"); - -// This is nn::irsensor::PackedImageTransferProcessorExConfig -struct PackedImageTransferProcessorExConfig { - PackedCameraConfig camera_config; - PackedMcuVersion required_mcu_version; - PackedImageTransferProcessorFormat origin_format; - PackedImageTransferProcessorFormat trimming_format; - u16 trimming_start_x; - u16 trimming_start_y; - bool is_external_light_filter_enabled; - INSERT_PADDING_BYTES(5); -}; -static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20, - "PackedImageTransferProcessorExConfig is an invalid size"); - -// This is nn::irsensor::PackedIrLedProcessorConfig -struct PackedIrLedProcessorConfig { - PackedMcuVersion required_mcu_version; - u8 light_target; - INSERT_PADDING_BYTES(3); -}; -static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8, - "PackedIrLedProcessorConfig is an invalid size"); - -// This is nn::irsensor::HandAnalysisConfig -struct HandAnalysisConfig { - HandAnalysisMode mode; -}; -static_assert(sizeof(HandAnalysisConfig) == 0x4, "HandAnalysisConfig is an invalid size"); - -// This is nn::irsensor::detail::ProcessorState contents are different for each processor -struct ProcessorState { - std::array<u8, 0xE20> processor_raw_data{}; -}; -static_assert(sizeof(ProcessorState) == 0xE20, "ProcessorState is an invalid size"); - -// This is nn::irsensor::detail::DeviceFormat -struct DeviceFormat { - Core::IrSensor::IrCameraStatus camera_status{Core::IrSensor::IrCameraStatus::Unconnected}; - Core::IrSensor::IrCameraInternalStatus camera_internal_status{ - Core::IrSensor::IrCameraInternalStatus::Ready}; - Core::IrSensor::IrSensorMode mode{Core::IrSensor::IrSensorMode::None}; - ProcessorState state{}; -}; -static_assert(sizeof(DeviceFormat) == 0xE30, "DeviceFormat is an invalid size"); - -// This is nn::irsensor::ImageTransferProcessorState -struct ImageTransferProcessorState { - u64 sampling_number; - Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; - INSERT_PADDING_BYTES(4); -}; -static_assert(sizeof(ImageTransferProcessorState) == 0x10, - "ImageTransferProcessorState is an invalid size"); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <cmath> - -#include "common/math_util.h" -#include "core/hid/motion_input.h" - -namespace Core::HID { - -MotionInput::MotionInput() { - // Initialize PID constants with default values - SetPID(0.3f, 0.005f, 0.0f); - SetGyroThreshold(ThresholdStandard); - ResetQuaternion(); - ResetRotations(); -} - -void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) { - kp = new_kp; - ki = new_ki; - kd = new_kd; -} - -void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) { - accel = acceleration; - - accel.x = std::clamp(accel.x, -AccelMaxValue, AccelMaxValue); - accel.y = std::clamp(accel.y, -AccelMaxValue, AccelMaxValue); - accel.z = std::clamp(accel.z, -AccelMaxValue, AccelMaxValue); -} - -void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { - gyro = gyroscope - gyro_bias; - - gyro.x = std::clamp(gyro.x, -GyroMaxValue, GyroMaxValue); - gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue); - gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue); - - // Auto adjust gyro_bias to minimize drift - if (!IsMoving(IsAtRestRelaxed)) { - gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f); - } - - // Adjust drift when calibration mode is enabled - if (calibration_mode) { - gyro_bias = (gyro_bias * 0.99f) + (gyroscope * 0.01f); - StopCalibration(); - } - - if (gyro.Length() < gyro_threshold * user_gyro_threshold) { - gyro = {}; - } else { - only_accelerometer = false; - } -} - -void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) { - quat = quaternion; -} - -void MotionInput::SetEulerAngles(const Common::Vec3f& euler_angles) { - const float cr = std::cos(euler_angles.x * 0.5f); - const float sr = std::sin(euler_angles.x * 0.5f); - const float cp = std::cos(euler_angles.y * 0.5f); - const float sp = std::sin(euler_angles.y * 0.5f); - const float cy = std::cos(euler_angles.z * 0.5f); - const float sy = std::sin(euler_angles.z * 0.5f); - - quat.w = cr * cp * cy + sr * sp * sy; - quat.xyz.x = sr * cp * cy - cr * sp * sy; - quat.xyz.y = cr * sp * cy + sr * cp * sy; - quat.xyz.z = cr * cp * sy - sr * sp * cy; -} - -void MotionInput::SetGyroBias(const Common::Vec3f& bias) { - gyro_bias = bias; -} - -void MotionInput::SetGyroThreshold(f32 threshold) { - gyro_threshold = threshold; -} - -void MotionInput::SetUserGyroThreshold(f32 threshold) { - user_gyro_threshold = threshold / ThresholdStandard; -} - -void MotionInput::EnableReset(bool reset) { - reset_enabled = reset; -} - -void MotionInput::ResetRotations() { - rotations = {}; -} - -void MotionInput::ResetQuaternion() { - quat = {{0.0f, 0.0f, -1.0f}, 0.0f}; -} - -bool MotionInput::IsMoving(f32 sensitivity) const { - return gyro.Length() >= sensitivity || accel.Length() <= 0.9f || accel.Length() >= 1.1f; -} - -bool MotionInput::IsCalibrated(f32 sensitivity) const { - return real_error.Length() < sensitivity; -} - -void MotionInput::UpdateRotation(u64 elapsed_time) { - const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f; - if (sample_period > 0.1f) { - return; - } - rotations += gyro * sample_period; -} - -void MotionInput::Calibrate() { - calibration_mode = true; - calibration_counter = 0; -} - -void MotionInput::StopCalibration() { - if (calibration_counter++ > CalibrationSamples) { - calibration_mode = false; - ResetQuaternion(); - ResetRotations(); - } -} - -// Based on Madgwick's implementation of Mayhony's AHRS algorithm. -// 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 -void MotionInput::UpdateOrientation(u64 elapsed_time) { - if (!IsCalibrated(0.1f)) { - ResetOrientation(); - } - // Short name local variable for readability - f32 q1 = quat.w; - f32 q2 = quat.xyz[0]; - f32 q3 = quat.xyz[1]; - f32 q4 = quat.xyz[2]; - const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f; - - // Ignore invalid elapsed time - if (sample_period > 0.1f) { - return; - } - - const auto normal_accel = accel.Normalized(); - auto rad_gyro = gyro * Common::PI * 2; - const f32 swap = rad_gyro.x; - rad_gyro.x = rad_gyro.y; - rad_gyro.y = -swap; - rad_gyro.z = -rad_gyro.z; - - // Clear gyro values if there is no gyro present - if (only_accelerometer) { - rad_gyro.x = 0; - rad_gyro.y = 0; - rad_gyro.z = 0; - } - - // Ignore drift correction if acceleration is not reliable - if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) { - const f32 ax = -normal_accel.x; - const f32 ay = normal_accel.y; - const f32 az = -normal_accel.z; - - // Estimated direction of gravity - const f32 vx = 2.0f * (q2 * q4 - q1 * q3); - const f32 vy = 2.0f * (q1 * q2 + q3 * q4); - const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; - - // Error is cross product between estimated direction and measured direction of gravity - const Common::Vec3f new_real_error = { - az * vx - ax * vz, - ay * vz - az * vy, - ax * vy - ay * vx, - }; - - derivative_error = new_real_error - real_error; - real_error = new_real_error; - - // Prevent integral windup - if (ki != 0.0f && !IsCalibrated(0.05f)) { - integral_error += real_error; - } else { - integral_error = {}; - } - - // Apply feedback terms - if (!only_accelerometer) { - rad_gyro += kp * real_error; - rad_gyro += ki * integral_error; - rad_gyro += kd * derivative_error; - } else { - // Give more weight to accelerometer values to compensate for the lack of gyro - rad_gyro += 35.0f * kp * real_error; - rad_gyro += 10.0f * ki * integral_error; - rad_gyro += 10.0f * kd * derivative_error; - - // Emulate gyro values for games that need them - gyro.x = -rad_gyro.y; - gyro.y = rad_gyro.x; - gyro.z = -rad_gyro.z; - UpdateRotation(elapsed_time); - } - } - - const f32 gx = rad_gyro.y; - const f32 gy = rad_gyro.x; - const f32 gz = rad_gyro.z; - - // Integrate rate of change of quaternion - const f32 pa = q2; - const f32 pb = q3; - const f32 pc = q4; - q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period); - q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period); - q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); - q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); - - quat.w = q1; - quat.xyz[0] = q2; - quat.xyz[1] = q3; - quat.xyz[2] = q4; - quat = quat.Normalized(); -} - -std::array<Common::Vec3f, 3> MotionInput::GetOrientation() const { - const Common::Quaternion<float> quad{ - .xyz = {-quat.xyz[1], -quat.xyz[0], -quat.w}, - .w = -quat.xyz[2], - }; - const std::array<float, 16> matrix4x4 = quad.ToMatrix(); - - return {Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]), - Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]), - Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])}; -} - -Common::Vec3f MotionInput::GetAcceleration() const { - return accel; -} - -Common::Vec3f MotionInput::GetGyroscope() const { - return gyro; -} - -Common::Vec3f MotionInput::GetGyroBias() const { - return gyro_bias; -} - -Common::Quaternion<f32> MotionInput::GetQuaternion() const { - return quat; -} - -Common::Vec3f MotionInput::GetRotations() const { - return rotations; -} - -Common::Vec3f MotionInput::GetEulerAngles() const { - // roll (x-axis rotation) - const float sinr_cosp = 2 * (quat.w * quat.xyz.x + quat.xyz.y * quat.xyz.z); - const float cosr_cosp = 1 - 2 * (quat.xyz.x * quat.xyz.x + quat.xyz.y * quat.xyz.y); - - // pitch (y-axis rotation) - const float sinp = std::sqrt(1 + 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); - const float cosp = std::sqrt(1 - 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); - - // yaw (z-axis rotation) - const float siny_cosp = 2 * (quat.w * quat.xyz.z + quat.xyz.x * quat.xyz.y); - const float cosy_cosp = 1 - 2 * (quat.xyz.y * quat.xyz.y + quat.xyz.z * quat.xyz.z); - - return { - std::atan2(sinr_cosp, cosr_cosp), - 2 * std::atan2(sinp, cosp) - Common::PI / 2, - std::atan2(siny_cosp, cosy_cosp), - }; -} - -void MotionInput::ResetOrientation() { - if (!reset_enabled || only_accelerometer) { - return; - } - if (!IsMoving(IsAtRestRelaxed) && accel.z <= -0.9f) { - ++reset_counter; - if (reset_counter > 900) { - quat.w = 0; - quat.xyz[0] = 0; - quat.xyz[1] = 0; - quat.xyz[2] = -1; - SetOrientationFromAccelerometer(); - integral_error = {}; - reset_counter = 0; - } - } else { - reset_counter = 0; - } -} - -void MotionInput::SetOrientationFromAccelerometer() { - int iterations = 0; - const f32 sample_period = 0.015f; - - const auto normal_accel = accel.Normalized(); - - while (!IsCalibrated(0.01f) && ++iterations < 100) { - // Short name local variable for readability - f32 q1 = quat.w; - f32 q2 = quat.xyz[0]; - f32 q3 = quat.xyz[1]; - f32 q4 = quat.xyz[2]; - - Common::Vec3f rad_gyro; - const f32 ax = -normal_accel.x; - const f32 ay = normal_accel.y; - const f32 az = -normal_accel.z; - - // Estimated direction of gravity - const f32 vx = 2.0f * (q2 * q4 - q1 * q3); - const f32 vy = 2.0f * (q1 * q2 + q3 * q4); - const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; - - // Error is cross product between estimated direction and measured direction of gravity - const Common::Vec3f new_real_error = { - az * vx - ax * vz, - ay * vz - az * vy, - ax * vy - ay * vx, - }; - - derivative_error = new_real_error - real_error; - real_error = new_real_error; - - rad_gyro += 10.0f * kp * real_error; - rad_gyro += 5.0f * ki * integral_error; - rad_gyro += 10.0f * kd * derivative_error; - - const f32 gx = rad_gyro.y; - const f32 gy = rad_gyro.x; - const f32 gz = rad_gyro.z; - - // Integrate rate of change of quaternion - const f32 pa = q2; - const f32 pb = q3; - const f32 pc = q4; - q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period); - q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period); - q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); - q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); - - quat.w = q1; - quat.xyz[0] = q2; - quat.xyz[1] = q3; - quat.xyz[2] = q4; - quat = quat.Normalized(); - } -} -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "common/quaternion.h" -#include "common/vector_math.h" - -namespace Core::HID { - -class MotionInput { -public: - static constexpr float ThresholdLoose = 0.01f; - static constexpr float ThresholdStandard = 0.007f; - static constexpr float ThresholdThight = 0.002f; - - static constexpr float IsAtRestRelaxed = 0.05f; - static constexpr float IsAtRestLoose = 0.02f; - static constexpr float IsAtRestStandard = 0.01f; - static constexpr float IsAtRestThight = 0.005f; - - static constexpr float GyroMaxValue = 5.0f; - static constexpr float AccelMaxValue = 7.0f; - - static constexpr std::size_t CalibrationSamples = 300; - - explicit MotionInput(); - - MotionInput(const MotionInput&) = default; - MotionInput& operator=(const MotionInput&) = default; - - MotionInput(MotionInput&&) = default; - MotionInput& operator=(MotionInput&&) = default; - - void SetPID(f32 new_kp, f32 new_ki, f32 new_kd); - void SetAcceleration(const Common::Vec3f& acceleration); - void SetGyroscope(const Common::Vec3f& gyroscope); - void SetQuaternion(const Common::Quaternion<f32>& quaternion); - void SetEulerAngles(const Common::Vec3f& euler_angles); - void SetGyroBias(const Common::Vec3f& bias); - void SetGyroThreshold(f32 threshold); - - /// Applies a modifier on top of the normal gyro threshold - void SetUserGyroThreshold(f32 threshold); - - void EnableReset(bool reset); - void ResetRotations(); - void ResetQuaternion(); - - void UpdateRotation(u64 elapsed_time); - void UpdateOrientation(u64 elapsed_time); - - void Calibrate(); - - [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; - [[nodiscard]] Common::Vec3f GetAcceleration() const; - [[nodiscard]] Common::Vec3f GetGyroscope() const; - [[nodiscard]] Common::Vec3f GetGyroBias() const; - [[nodiscard]] Common::Vec3f GetRotations() const; - [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; - [[nodiscard]] Common::Vec3f GetEulerAngles() const; - - [[nodiscard]] bool IsMoving(f32 sensitivity) const; - [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; - -private: - void StopCalibration(); - void ResetOrientation(); - void SetOrientationFromAccelerometer(); - - // PID constants - f32 kp; - f32 ki; - f32 kd; - - // PID errors - Common::Vec3f real_error; - Common::Vec3f integral_error; - Common::Vec3f derivative_error; - - // Quaternion containing the device orientation - Common::Quaternion<f32> quat; - - // Number of full rotations in each axis - Common::Vec3f rotations; - - // Acceleration vector measurement in G force - Common::Vec3f accel; - - // Gyroscope vector measurement in radians/s. - Common::Vec3f gyro; - - // Vector to be subtracted from gyro measurements - Common::Vec3f gyro_bias; - - // Minimum gyro amplitude to detect if the device is moving - f32 gyro_threshold = 0.0f; - - // Multiplies gyro_threshold by this value - f32 user_gyro_threshold = 0.0f; - - // Number of invalid sequential data - u32 reset_counter = 0; - - // If the provided data is invalid the device will be autocalibrated - bool reset_enabled = true; - - // Use accelerometer values to calculate position - bool only_accelerometer = true; - - // When enabled it will aggressively adjust for gyro drift - bool calibration_mode = false; - - // Used to auto disable calibration mode - std::size_t calibration_counter = 0; -}; - -} // 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 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/savedata_factory.h" -#include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/result.h" @@ -37,7 +36,6 @@ #include "core/hle/service/caps/caps_su.h" #include "core/hle/service/caps/caps_types.h" #include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ns/ns.h" #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" @@ -48,6 +46,8 @@ #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_results.h" #include "core/memory.h" +#include "hid_core/hid_types.h" +#include "hid_core/resources/npad/npad.h" namespace Service::AM { 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 @@ #include "common/logging/log.h" #include "core/core.h" #include "core/frontend/applets/cabinet.h" -#include "core/hid/hid_core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applet_cabinet.h" #include "core/hle/service/mii/mii_manager.h" #include "core/hle/service/nfc/common/device.h" +#include "hid_core/hid_core.h" namespace Service::AM::Applets { 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 @@ #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/controller.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" #include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applet_controller.h" -#include "core/hle/service/hid/controllers/npad.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" +#include "hid_core/hid_types.h" +#include "hid_core/resources/npad/npad.h" namespace Service::AM::Applets { 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/core.h" -#include "core/hle/kernel/k_shared_memory.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" -#include "core/hle/service/hid/errors.h" - -namespace Service::HID { - -AppletResource::AppletResource(Core::System& system_) : system{system_} {} - -AppletResource::~AppletResource() = default; - -Result AppletResource::CreateAppletResource(u64 aruid) { - const u64 index = GetIndexFromAruid(aruid); - - if (index >= AruidIndexMax) { - return ResultAruidNotRegistered; - } - - if (data[index].flag.is_assigned) { - return ResultAruidAlreadyRegistered; - } - - auto& shared_memory = shared_memory_holder[index]; - if (!shared_memory.IsMapped()) { - const Result result = shared_memory.Initialize(system); - if (result.IsError()) { - return result; - } - if (shared_memory.GetAddress() == nullptr) { - shared_memory.Finalize(); - return ResultSharedMemoryNotInitialized; - } - } - - auto* shared_memory_format = shared_memory.GetAddress(); - if (shared_memory_format != nullptr) { - shared_memory_format->Initialize(); - } - - data[index].shared_memory_format = shared_memory_format; - data[index].flag.is_assigned.Assign(true); - // TODO: InitializeSixAxisControllerConfig(false); - active_aruid = aruid; - return ResultSuccess; -} - -Result AppletResource::RegisterAppletResourceUserId(u64 aruid, bool enable_input) { - const u64 index = GetIndexFromAruid(aruid); - - if (index < AruidIndexMax) { - return ResultAruidAlreadyRegistered; - } - - std::size_t data_index = AruidIndexMax; - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (!data[i].flag.is_initialized) { - data_index = i; - break; - } - } - - if (data_index == AruidIndexMax) { - return ResultAruidNoAvailableEntries; - } - - AruidData& aruid_data = data[data_index]; - - aruid_data.aruid = aruid; - aruid_data.flag.is_initialized.Assign(true); - if (enable_input) { - aruid_data.flag.enable_pad_input.Assign(true); - aruid_data.flag.enable_six_axis_sensor.Assign(true); - aruid_data.flag.bit_18.Assign(true); - aruid_data.flag.enable_touchscreen.Assign(true); - } - - data_index = AruidIndexMax; - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (registration_list.flag[i] == RegistrationStatus::Initialized) { - if (registration_list.aruid[i] != aruid) { - continue; - } - data_index = i; - break; - } - if (registration_list.flag[i] == RegistrationStatus::None) { - data_index = i; - break; - } - } - - if (data_index == AruidIndexMax) { - return ResultSuccess; - } - - registration_list.flag[data_index] = RegistrationStatus::Initialized; - registration_list.aruid[data_index] = aruid; - - return ResultSuccess; -} - -void AppletResource::UnregisterAppletResourceUserId(u64 aruid) { - u64 index = GetIndexFromAruid(aruid); - - if (index < AruidIndexMax) { - if (data[index].flag.is_assigned) { - data[index].shared_memory_format = nullptr; - data[index].flag.is_assigned.Assign(false); - } - } - - index = GetIndexFromAruid(aruid); - if (index < AruidIndexMax) { - DestroySevenSixAxisTransferMemory(); - data[index].flag.raw = 0; - data[index].aruid = 0; - - index = GetIndexFromAruid(aruid); - if (index < AruidIndexMax) { - registration_list.flag[index] = RegistrationStatus::PendingDelete; - } - } -} - -void AppletResource::FreeAppletResourceId(u64 aruid) { - u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return; - } - - auto& aruid_data = data[index]; - if (aruid_data.flag.is_assigned) { - aruid_data.shared_memory_format = nullptr; - aruid_data.flag.is_assigned.Assign(false); - } -} - -u64 AppletResource::GetActiveAruid() { - return active_aruid; -} - -Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) { - u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return ResultAruidNotRegistered; - } - - *out_handle = shared_memory_holder[index].GetHandle(); - return ResultSuccess; -} - -Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, - u64 aruid) { - u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return ResultAruidNotRegistered; - } - - *out_shared_memory_format = data[index].shared_memory_format; - return ResultSuccess; -} - -AruidData* AppletResource::GetAruidData(u64 aruid) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index == AruidIndexMax) { - return nullptr; - } - return &data[aruid_index]; -} - -AruidData* AppletResource::GetAruidDataByIndex(std::size_t aruid_index) { - return &data[aruid_index]; -} - -bool AppletResource::IsVibrationAruidActive(u64 aruid) const { - return aruid == 0 || aruid == active_vibration_aruid; -} - -u64 AppletResource::GetIndexFromAruid(u64 aruid) { - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (registration_list.flag[i] == RegistrationStatus::Initialized && - registration_list.aruid[i] == aruid) { - return i; - } - } - return AruidIndexMax; -} - -Result AppletResource::DestroySevenSixAxisTransferMemory() { - // TODO - return ResultSuccess; -} - -void AppletResource::EnableInput(u64 aruid, bool is_enabled) { - const u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return; - } - - data[index].flag.enable_pad_input.Assign(is_enabled); - data[index].flag.enable_touchscreen.Assign(is_enabled); -} - -void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { - const u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return; - } - - data[index].flag.enable_six_axis_sensor.Assign(is_enabled); -} - -void AppletResource::EnablePadInput(u64 aruid, bool is_enabled) { - const u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return; - } - - data[index].flag.enable_pad_input.Assign(is_enabled); -} - -void AppletResource::EnableTouchScreen(u64 aruid, bool is_enabled) { - const u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return; - } - - data[index].flag.enable_touchscreen.Assign(is_enabled); -} - -void AppletResource::SetIsPalmaConnectable(u64 aruid, bool is_connectable) { - const u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return; - } - - data[index].flag.is_palma_connectable.Assign(is_connectable); -} - -void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) { - const u64 index = GetIndexFromAruid(aruid); - if (index >= AruidIndexMax) { - return; - } - - data[index].flag.enable_palma_boost_mode.Assign(is_enabled); -} - -Result AppletResource::RegisterCoreAppletResource() { - if (ref_counter == std::numeric_limits<s32>::max() - 1) { - return ResultAppletResourceOverflow; - } - if (ref_counter == 0) { - const u64 index = GetIndexFromAruid(0); - if (index < AruidIndexMax) { - return ResultAruidAlreadyRegistered; - } - - std::size_t data_index = AruidIndexMax; - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (!data[i].flag.is_initialized) { - data_index = i; - break; - } - } - - if (data_index == AruidIndexMax) { - return ResultAruidNoAvailableEntries; - } - - AruidData& aruid_data = data[data_index]; - - aruid_data.aruid = 0; - aruid_data.flag.is_initialized.Assign(true); - aruid_data.flag.enable_pad_input.Assign(true); - aruid_data.flag.enable_six_axis_sensor.Assign(true); - aruid_data.flag.bit_18.Assign(true); - aruid_data.flag.enable_touchscreen.Assign(true); - - data_index = AruidIndexMax; - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (registration_list.flag[i] == RegistrationStatus::Initialized) { - if (registration_list.aruid[i] != 0) { - continue; - } - data_index = i; - break; - } - if (registration_list.flag[i] == RegistrationStatus::None) { - data_index = i; - break; - } - } - - Result result = ResultSuccess; - - if (data_index == AruidIndexMax) { - result = CreateAppletResource(0); - } else { - registration_list.flag[data_index] = RegistrationStatus::Initialized; - registration_list.aruid[data_index] = 0; - } - - if (result.IsError()) { - UnregisterAppletResourceUserId(0); - return result; - } - } - ref_counter++; - return ResultSuccess; -} - -Result AppletResource::UnregisterCoreAppletResource() { - if (ref_counter == 0) { - return ResultAppletResourceNotInitialized; - } - - if (--ref_counter == 0) { - UnregisterAppletResourceUserId(0); - } - - return ResultSuccess; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <array> -#include <mutex> - -#include "common/bit_field.h" -#include "common/common_types.h" -#include "core/hle/result.h" -#include "core/hle/service/hid/controllers/shared_memory_holder.h" - -namespace Core { -class System; -} - -namespace Kernel { -class KSharedMemory; -} - -namespace Service::HID { -struct SharedMemoryFormat; -class AppletResource; -class NPadResource; - -static constexpr std::size_t AruidIndexMax = 0x20; -static constexpr u64 SystemAruid = 0; - -enum class RegistrationStatus : u32 { - None, - Initialized, - PendingDelete, -}; - -struct DataStatusFlag { - union { - u32 raw{}; - - BitField<0, 1, u32> is_initialized; - BitField<1, 1, u32> is_assigned; - BitField<16, 1, u32> enable_pad_input; - BitField<17, 1, u32> enable_six_axis_sensor; - BitField<18, 1, u32> bit_18; - BitField<19, 1, u32> is_palma_connectable; - BitField<20, 1, u32> enable_palma_boost_mode; - BitField<21, 1, u32> enable_touchscreen; - }; -}; - -struct AruidRegisterList { - std::array<RegistrationStatus, AruidIndexMax> flag{}; - std::array<u64, AruidIndexMax> aruid{}; -}; -static_assert(sizeof(AruidRegisterList) == 0x180, "AruidRegisterList is an invalid size"); - -struct AruidData { - DataStatusFlag flag{}; - u64 aruid{}; - SharedMemoryFormat* shared_memory_format{nullptr}; -}; - -struct HandheldConfig { - bool is_handheld_hid_enabled; - bool is_force_handheld; - bool is_joycon_rail_enabled; - bool is_force_handheld_style_vibration; -}; -static_assert(sizeof(HandheldConfig) == 0x4, "HandheldConfig is an invalid size"); - -struct AppletResourceHolder { - std::shared_ptr<AppletResource> applet_resource{nullptr}; - std::recursive_mutex* shared_mutex{nullptr}; - NPadResource* shared_npad_resource{nullptr}; - std::shared_ptr<HandheldConfig> handheld_config{nullptr}; - long* handle_1; -}; - -class AppletResource { -public: - explicit AppletResource(Core::System& system_); - ~AppletResource(); - - Result CreateAppletResource(u64 aruid); - - Result RegisterAppletResourceUserId(u64 aruid, bool enable_input); - void UnregisterAppletResourceUserId(u64 aruid); - - void FreeAppletResourceId(u64 aruid); - - u64 GetActiveAruid(); - Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); - Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid); - AruidData* GetAruidData(u64 aruid); - AruidData* GetAruidDataByIndex(std::size_t aruid_index); - - bool IsVibrationAruidActive(u64 aruid) const; - - u64 GetIndexFromAruid(u64 aruid); - - Result DestroySevenSixAxisTransferMemory(); - - void EnableInput(u64 aruid, bool is_enabled); - void EnableSixAxisSensor(u64 aruid, bool is_enabled); - void EnablePadInput(u64 aruid, bool is_enabled); - void EnableTouchScreen(u64 aruid, bool is_enabled); - void SetIsPalmaConnectable(u64 aruid, bool is_connectable); - void EnablePalmaBoostMode(u64 aruid, bool is_enabled); - - Result RegisterCoreAppletResource(); - Result UnregisterCoreAppletResource(); - -private: - u64 active_aruid{}; - AruidRegisterList registration_list{}; - std::array<AruidData, AruidIndexMax> data{}; - std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{}; - s32 ref_counter{}; - u64 active_vibration_aruid; - - Core::System& system; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/capture_button.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -CaptureButton::CaptureButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} - -CaptureButton::~CaptureButton() = default; - -void CaptureButton::OnInit() {} - -void CaptureButton::OnRelease() {} - -void CaptureButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - auto& header = data->shared_memory_format->capture_button.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Service::HID { - -class CaptureButton final : public ControllerBase { -public: - explicit CaptureButton(Core::HID::HIDCore& hid_core_); - ~CaptureButton() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - bool smart_update{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/hid/emulated_console.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/console_six_axis.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { - console = hid_core.GetEmulatedConsole(); -} - -ConsoleSixAxis::~ConsoleSixAxis() = default; - -void ConsoleSixAxis::OnInit() {} - -void ConsoleSixAxis::OnRelease() {} - -void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - ConsoleSixAxisSensorSharedMemoryFormat& shared_memory = data->shared_memory_format->console; - - if (!IsControllerActivated()) { - return; - } - - const auto motion_status = console->GetMotion(); - - shared_memory.sampling_number++; - shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; - shared_memory.verticalization_error = motion_status.verticalization_error; - shared_memory.gyro_bias = motion_status.gyro_bias; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Core::HID { -class EmulatedConsole; -} // namespace Core::HID - -namespace Service::HID { -class ConsoleSixAxis final : public ControllerBase { -public: - explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_); - ~ConsoleSixAxis() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - Core::HID::EmulatedConsole* console = nullptr; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Service::HID { - -ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} -ControllerBase::~ControllerBase() = default; - -Result ControllerBase::Activate() { - if (is_activated) { - return ResultSuccess; - } - is_activated = true; - OnInit(); - return ResultSuccess; -} - -Result ControllerBase::Activate(u64 aruid) { - return Activate(); -} - -void ControllerBase::DeactivateController() { - if (is_activated) { - OnRelease(); - } - is_activated = false; -} - -bool ControllerBase::IsControllerActivated() const { - return is_activated; -} - -void ControllerBase::SetAppletResource(std::shared_ptr<AppletResource> resource, - std::recursive_mutex* resource_mutex) { - applet_resource = resource; - shared_mutex = resource_mutex; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> - -#include "common/common_types.h" -#include "core/hle/result.h" -#include "core/hle/service/hid/controllers/applet_resource.h" - -namespace Core::Timing { -class CoreTiming; -} - -namespace Core::HID { -class HIDCore; -} // namespace Core::HID - -namespace Service::HID { -class ControllerBase { -public: - explicit ControllerBase(Core::HID::HIDCore& hid_core_); - virtual ~ControllerBase(); - - // Called when the controller is initialized - virtual void OnInit() = 0; - - // When the controller is released - virtual void OnRelease() = 0; - - // When the controller is requesting an update for the shared memory - virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing) = 0; - - // When the controller is requesting a motion update for the shared memory - virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {} - - Result Activate(); - Result Activate(u64 aruid); - - void DeactivateController(); - - bool IsControllerActivated() const; - - void SetAppletResource(std::shared_ptr<AppletResource> resource, - std::recursive_mutex* resource_mutex); - -protected: - bool is_activated{false}; - std::shared_ptr<AppletResource> applet_resource{nullptr}; - std::recursive_mutex* shared_mutex{nullptr}; - - Core::HID::HIDCore& hid_core; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/frontend/emu_window.h" -#include "core/hid/emulated_devices.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/debug_mouse.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -DebugMouse::DebugMouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { - emulated_devices = hid_core.GetEmulatedDevices(); -} - -DebugMouse::~DebugMouse() = default; - -void DebugMouse::OnInit() {} -void DebugMouse::OnRelease() {} - -void DebugMouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - MouseSharedMemoryFormat& shared_memory = data->shared_memory_format->debug_mouse; - - if (!IsControllerActivated()) { - shared_memory.mouse_lifo.buffer_count = 0; - shared_memory.mouse_lifo.buffer_tail = 0; - return; - } - - next_state = {}; - - const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state; - next_state.sampling_number = last_entry.sampling_number + 1; - - if (Settings::values.mouse_enabled) { - const auto& mouse_button_state = emulated_devices->GetMouseButtons(); - const auto& mouse_position_state = emulated_devices->GetMousePosition(); - const auto& mouse_wheel_state = emulated_devices->GetMouseWheel(); - next_state.attribute.is_connected.Assign(1); - next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width); - next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height); - next_state.delta_x = next_state.x - last_entry.x; - next_state.delta_y = next_state.y - last_entry.y; - next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x; - next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y; - - last_mouse_wheel_state = mouse_wheel_state; - next_state.button = mouse_button_state; - } - - shared_memory.mouse_lifo.WriteNextEntry(next_state); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Core::HID { -class EmulatedDevices; -struct MouseState; -struct AnalogStickState; -} // namespace Core::HID - -namespace Service::HID { -class DebugMouse final : public ControllerBase { -public: - explicit DebugMouse(Core::HID::HIDCore& hid_core_); - ~DebugMouse() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - Core::HID::MouseState next_state{}; - Core::HID::AnalogStickState last_mouse_wheel_state{}; - Core::HID::EmulatedDevices* emulated_devices = nullptr; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/settings.h" -#include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/debug_pad.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -DebugPad::DebugPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { - controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); -} - -DebugPad::~DebugPad() = default; - -void DebugPad::OnInit() {} - -void DebugPad::OnRelease() {} - -void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - DebugPadSharedMemoryFormat& shared_memory = data->shared_memory_format->debug_pad; - - if (!IsControllerActivated()) { - shared_memory.debug_pad_lifo.buffer_count = 0; - shared_memory.debug_pad_lifo.buffer_tail = 0; - return; - } - - const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state; - next_state.sampling_number = last_entry.sampling_number + 1; - - if (Settings::values.debug_pad_enabled) { - next_state.attribute.connected.Assign(1); - - const auto& button_state = controller->GetDebugPadButtons(); - const auto& stick_state = controller->GetSticks(); - - next_state.pad_state = button_state; - next_state.l_stick = stick_state.left; - next_state.r_stick = stick_state.right; - } - - shared_memory.debug_pad_lifo.WriteNextEntry(next_state); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/controllers/types/debug_pad_types.h" - -namespace Core::HID { -class HIDCore; -} - -namespace Core::Timing { -class CoreTiming; -} - -namespace Service::HID { -class DebugPad final : public ControllerBase { -public: - explicit DebugPad(Core::HID::HIDCore& hid_core_); - ~DebugPad() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - DebugPadState next_state{}; - Core::HID::EmulatedController* controller = nullptr; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/digitizer.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -Digitizer::Digitizer(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} - -Digitizer::~Digitizer() = default; - -void Digitizer::OnInit() {} - -void Digitizer::OnRelease() {} - -void Digitizer::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - auto& header = data->shared_memory_format->digitizer.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Service::HID { - -class Digitizer final : public ControllerBase { -public: - explicit Digitizer(Core::HID::HIDCore& hid_core_); - ~Digitizer() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - bool smart_update{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/math_util.h" -#include "common/settings.h" -#include "core/frontend/emu_window.h" -#include "core/hid/emulated_console.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/gesture.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { -// HW is around 700, value is set to 400 to make it easier to trigger with mouse -constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s -constexpr f32 angle_threshold = 0.015f; // Threshold in radians -constexpr f32 pinch_threshold = 0.5f; // Threshold in pixels -constexpr f32 press_delay = 0.5f; // Time in seconds -constexpr f32 double_tap_delay = 0.35f; // Time in seconds - -constexpr f32 Square(s32 num) { - return static_cast<f32>(num * num); -} - -Gesture::Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) { - console = hid_core.GetEmulatedConsole(); -} -Gesture::~Gesture() = default; - -void Gesture::OnInit() { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - shared_memory = &data->shared_memory_format->gesture; - shared_memory->gesture_lifo.buffer_count = 0; - shared_memory->gesture_lifo.buffer_tail = 0; - force_update = true; -} - -void Gesture::OnRelease() {} - -void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - shared_memory = &data->shared_memory_format->gesture; - - if (!IsControllerActivated()) { - shared_memory->gesture_lifo.buffer_count = 0; - shared_memory->gesture_lifo.buffer_tail = 0; - return; - } - - ReadTouchInput(); - - GestureProperties gesture = GetGestureProperties(); - f32 time_difference = - static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) / - (1000 * 1000 * 1000); - - // Only update if necessary - if (!ShouldUpdateGesture(gesture, time_difference)) { - return; - } - - last_update_timestamp = shared_memory->gesture_lifo.timestamp; - UpdateGestureSharedMemory(gesture, time_difference); -} - -void Gesture::ReadTouchInput() { - if (!Settings::values.touchscreen.enabled) { - fingers = {}; - return; - } - - const auto touch_status = console->GetTouch(); - for (std::size_t id = 0; id < fingers.size(); ++id) { - fingers[id] = touch_status[id]; - } -} - -bool Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) { - const auto& last_entry = GetLastGestureEntry(); - if (force_update) { - force_update = false; - return true; - } - - // Update if coordinates change - for (size_t id = 0; id < MAX_POINTS; id++) { - if (gesture.points[id] != last_gesture.points[id]) { - return true; - } - } - - // Update on press and hold event after 0.5 seconds - if (last_entry.type == GestureType::Touch && last_entry.point_count == 1 && - time_difference > press_delay) { - return enable_press_and_tap; - } - - return false; -} - -void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference) { - GestureType type = GestureType::Idle; - GestureAttribute attributes{}; - - const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state; - - // Reset next state to default - next_state.sampling_number = last_entry.sampling_number + 1; - next_state.delta = {}; - next_state.vel_x = 0; - next_state.vel_y = 0; - next_state.direction = GestureDirection::None; - next_state.rotation_angle = 0; - next_state.scale = 0; - - if (gesture.active_points > 0) { - if (last_gesture.active_points == 0) { - NewGesture(gesture, type, attributes); - } else { - UpdateExistingGesture(gesture, type, time_difference); - } - } else { - EndGesture(gesture, last_gesture, type, attributes, time_difference); - } - - // Apply attributes - next_state.detection_count = gesture.detection_count; - next_state.type = type; - next_state.attributes = attributes; - next_state.pos = gesture.mid_point; - next_state.point_count = static_cast<s32>(gesture.active_points); - next_state.points = gesture.points; - last_gesture = gesture; - - shared_memory->gesture_lifo.WriteNextEntry(next_state); -} - -void Gesture::NewGesture(GestureProperties& gesture, GestureType& type, - GestureAttribute& attributes) { - const auto& last_entry = GetLastGestureEntry(); - - gesture.detection_count++; - type = GestureType::Touch; - - // New touch after cancel is not considered new - if (last_entry.type != GestureType::Cancel) { - attributes.is_new_touch.Assign(1); - enable_press_and_tap = true; - } -} - -void Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type, - f32 time_difference) { - const auto& last_entry = GetLastGestureEntry(); - - // Promote to pan type if touch moved - for (size_t id = 0; id < MAX_POINTS; id++) { - if (gesture.points[id] != last_gesture.points[id]) { - type = GestureType::Pan; - break; - } - } - - // Number of fingers changed cancel the last event and clear data - if (gesture.active_points != last_gesture.active_points) { - type = GestureType::Cancel; - enable_press_and_tap = false; - gesture.active_points = 0; - gesture.mid_point = {}; - gesture.points.fill({}); - return; - } - - // Calculate extra parameters of panning - if (type == GestureType::Pan) { - UpdatePanEvent(gesture, last_gesture, type, time_difference); - return; - } - - // Promote to press type - if (last_entry.type == GestureType::Touch) { - type = GestureType::Press; - } -} - -void Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, GestureAttribute& attributes, f32 time_difference) { - const auto& last_entry = GetLastGestureEntry(); - - if (last_gesture_props.active_points != 0) { - switch (last_entry.type) { - case GestureType::Touch: - if (enable_press_and_tap) { - SetTapEvent(gesture, last_gesture_props, type, attributes); - return; - } - type = GestureType::Cancel; - force_update = true; - break; - case GestureType::Press: - case GestureType::Tap: - case GestureType::Swipe: - case GestureType::Pinch: - case GestureType::Rotate: - type = GestureType::Complete; - force_update = true; - break; - case GestureType::Pan: - EndPanEvent(gesture, last_gesture_props, type, time_difference); - break; - default: - break; - } - return; - } - if (last_entry.type == GestureType::Complete || last_entry.type == GestureType::Cancel) { - gesture.detection_count++; - } -} - -void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, GestureAttribute& attributes) { - type = GestureType::Tap; - gesture = last_gesture_props; - force_update = true; - f32 tap_time_difference = - static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); - last_tap_timestamp = last_update_timestamp; - if (tap_time_difference < double_tap_delay) { - attributes.is_double_tap.Assign(1); - } -} - -void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, f32 time_difference) { - const auto& last_entry = GetLastGestureEntry(); - - next_state.delta = gesture.mid_point - last_entry.pos; - next_state.vel_x = static_cast<f32>(next_state.delta.x) / time_difference; - next_state.vel_y = static_cast<f32>(next_state.delta.y) / time_difference; - last_pan_time_difference = time_difference; - - // Promote to pinch type - if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > - pinch_threshold) { - type = GestureType::Pinch; - next_state.scale = gesture.average_distance / last_gesture_props.average_distance; - } - - const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / - (1 + (gesture.angle * last_gesture_props.angle))); - // Promote to rotate type - if (std::abs(angle_between_two_lines) > angle_threshold) { - type = GestureType::Rotate; - next_state.scale = 0; - next_state.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; - } -} - -void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, f32 time_difference) { - const auto& last_entry = GetLastGestureEntry(); - next_state.vel_x = - static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference); - next_state.vel_y = - static_cast<f32>(last_entry.delta.y) / (last_pan_time_difference + time_difference); - const f32 curr_vel = - std::sqrt((next_state.vel_x * next_state.vel_x) + (next_state.vel_y * next_state.vel_y)); - - // Set swipe event with parameters - if (curr_vel > swipe_threshold) { - SetSwipeEvent(gesture, last_gesture_props, type); - return; - } - - // End panning without swipe - type = GestureType::Complete; - next_state.vel_x = 0; - next_state.vel_y = 0; - force_update = true; -} - -void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type) { - const auto& last_entry = GetLastGestureEntry(); - - type = GestureType::Swipe; - gesture = last_gesture_props; - force_update = true; - next_state.delta = last_entry.delta; - - if (std::abs(next_state.delta.x) > std::abs(next_state.delta.y)) { - if (next_state.delta.x > 0) { - next_state.direction = GestureDirection::Right; - return; - } - next_state.direction = GestureDirection::Left; - return; - } - if (next_state.delta.y > 0) { - next_state.direction = GestureDirection::Down; - return; - } - next_state.direction = GestureDirection::Up; -} - -const GestureState& Gesture::GetLastGestureEntry() const { - return shared_memory->gesture_lifo.ReadCurrentEntry().state; -} - -GestureProperties Gesture::GetGestureProperties() { - GestureProperties gesture; - std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers; - const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), - [](const auto& finger) { return finger.pressed; }); - gesture.active_points = - static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); - - for (size_t id = 0; id < gesture.active_points; ++id) { - const auto& [active_x, active_y] = active_fingers[id].position; - gesture.points[id] = { - .x = static_cast<s32>(active_x * Layout::ScreenUndocked::Width), - .y = static_cast<s32>(active_y * Layout::ScreenUndocked::Height), - }; - - // Hack: There is no touch in docked but games still allow it - if (Settings::IsDockedMode()) { - gesture.points[id] = { - .x = static_cast<s32>(active_x * Layout::ScreenDocked::Width), - .y = static_cast<s32>(active_y * Layout::ScreenDocked::Height), - }; - } - - gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); - gesture.mid_point.y += static_cast<s32>(gesture.points[id].y / gesture.active_points); - } - - for (size_t id = 0; id < gesture.active_points; ++id) { - const f32 distance = std::sqrt(Square(gesture.mid_point.x - gesture.points[id].x) + - Square(gesture.mid_point.y - gesture.points[id].y)); - gesture.average_distance += distance / static_cast<f32>(gesture.active_points); - } - - gesture.angle = std::atan2(static_cast<f32>(gesture.mid_point.y - gesture.points[0].y), - static_cast<f32>(gesture.mid_point.x - gesture.points[0].x)); - - gesture.detection_count = last_gesture.detection_count; - - return gesture; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> - -#include "common/common_types.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/controllers/types/touch_types.h" - -namespace Core::HID { -class EmulatedConsole; -} - -namespace Service::HID { -struct GestureSharedMemoryFormat; - -class Gesture final : public ControllerBase { -public: - explicit Gesture(Core::HID::HIDCore& hid_core_); - ~Gesture() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - // Reads input from all available input engines - void ReadTouchInput(); - - // Returns true if gesture state needs to be updated - bool ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference); - - // Updates the shared memory to the next state - void UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference); - - // Initializes new gesture - void NewGesture(GestureProperties& gesture, GestureType& type, GestureAttribute& attributes); - - // Updates existing gesture state - void UpdateExistingGesture(GestureProperties& gesture, GestureType& type, f32 time_difference); - - // Terminates exiting gesture - void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, GestureAttribute& attributes, f32 time_difference); - - // Set current event to a tap event - void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, GestureAttribute& attributes); - - // Calculates and set the extra parameters related to a pan event - void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, f32 time_difference); - - // Terminates the pan event - void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type, f32 time_difference); - - // Set current event to a swipe event - void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, - GestureType& type); - - // Retrieves the last gesture entry, as indicated by shared memory indices. - [[nodiscard]] const GestureState& GetLastGestureEntry() const; - - // Returns the average distance, angle and middle point of the active fingers - GestureProperties GetGestureProperties(); - - GestureState next_state{}; - GestureSharedMemoryFormat* shared_memory; - Core::HID::EmulatedConsole* console = nullptr; - - std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{}; - GestureProperties last_gesture{}; - s64 last_update_timestamp{}; - s64 last_tap_timestamp{}; - f32 last_pan_time_difference{}; - bool force_update{false}; - bool enable_press_and_tap{false}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/home_button.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -HomeButton::HomeButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} - -HomeButton::~HomeButton() = default; - -void HomeButton::OnInit() {} - -void HomeButton::OnRelease() {} - -void HomeButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - auto& header = data->shared_memory_format->home_button.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Service::HID { - -class HomeButton final : public ControllerBase { -public: - explicit HomeButton(Core::HID::HIDCore& hid_core_); - ~HomeButton() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - bool smart_update{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/settings.h" -#include "core/core_timing.h" -#include "core/hid/emulated_devices.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/keyboard.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -Keyboard::Keyboard(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { - emulated_devices = hid_core.GetEmulatedDevices(); -} - -Keyboard::~Keyboard() = default; - -void Keyboard::OnInit() {} - -void Keyboard::OnRelease() {} - -void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - KeyboardSharedMemoryFormat& shared_memory = data->shared_memory_format->keyboard; - - if (!IsControllerActivated()) { - shared_memory.keyboard_lifo.buffer_count = 0; - shared_memory.keyboard_lifo.buffer_tail = 0; - return; - } - - const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state; - next_state.sampling_number = last_entry.sampling_number + 1; - - if (Settings::values.keyboard_enabled) { - const auto& keyboard_state = emulated_devices->GetKeyboard(); - const auto& keyboard_modifier_state = emulated_devices->GetKeyboardModifier(); - - next_state.key = keyboard_state; - next_state.modifier = keyboard_modifier_state; - next_state.attribute.is_connected.Assign(1); - } - - shared_memory.keyboard_lifo.WriteNextEntry(next_state); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/controllers/types/keyboard_types.h" - -namespace Service::HID { -class Keyboard final : public ControllerBase { -public: - explicit Keyboard(Core::HID::HIDCore& hid_core_); - ~Keyboard() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - KeyboardState next_state{}; - Core::HID::EmulatedDevices* emulated_devices = nullptr; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/frontend/emu_window.h" -#include "core/hid/emulated_devices.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/mouse.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -Mouse::Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { - emulated_devices = hid_core.GetEmulatedDevices(); -} - -Mouse::~Mouse() = default; - -void Mouse::OnInit() {} -void Mouse::OnRelease() {} - -void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - MouseSharedMemoryFormat& shared_memory = data->shared_memory_format->mouse; - - if (!IsControllerActivated()) { - shared_memory.mouse_lifo.buffer_count = 0; - shared_memory.mouse_lifo.buffer_tail = 0; - return; - } - - next_state = {}; - - const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state; - next_state.sampling_number = last_entry.sampling_number + 1; - - if (Settings::values.mouse_enabled) { - const auto& mouse_button_state = emulated_devices->GetMouseButtons(); - const auto& mouse_position_state = emulated_devices->GetMousePosition(); - const auto& mouse_wheel_state = emulated_devices->GetMouseWheel(); - next_state.attribute.is_connected.Assign(1); - next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width); - next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height); - next_state.delta_x = next_state.x - last_entry.x; - next_state.delta_y = next_state.y - last_entry.y; - next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x; - next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y; - - last_mouse_wheel_state = mouse_wheel_state; - next_state.button = mouse_button_state; - } - - shared_memory.mouse_lifo.WriteNextEntry(next_state); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Core::HID { -class EmulatedDevices; -struct MouseState; -struct AnalogStickState; -} // namespace Core::HID - -namespace Service::HID { -class Mouse final : public ControllerBase { -public: - explicit Mouse(Core::HID::HIDCore& hid_core_); - ~Mouse() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - Core::HID::MouseState next_state{}; - Core::HID::AnalogStickState last_mouse_wheel_state{}; - Core::HID::EmulatedDevices* emulated_devices = nullptr; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <array> -#include <chrono> -#include <cstring> - -#include "common/assert.h" -#include "common/bit_field.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "common/settings.h" -#include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" -#include "core/hle/service/hid/errors.h" -#include "core/hle/service/hid/hid_util.h" -#include "core/hle/service/kernel_helpers.h" - -namespace Service::HID { - -NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) - : hid_core{hid_core_}, service_context{service_context_}, npad_resource{service_context} { - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { - for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { - auto& controller = controller_data[aruid_index][i]; - controller.device = hid_core.GetEmulatedControllerByIndex(i); - controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex] - .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = - [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, - .is_npad_service = true, - }; - controller.callback_key = controller.device->SetCallback(engine_callback); - } - } -} - -NPad::~NPad() { - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { - for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { - auto& controller = controller_data[aruid_index][i]; - controller.device->DeleteCallback(controller.callback_key); - } - } -} - -Result NPad::Activate() { - if (ref_counter == std::numeric_limits<s32>::max() - 1) { - return ResultNpadResourceOverflow; - } - - if (ref_counter == 0) { - std::scoped_lock lock{mutex}; - - // TODO: Activate handlers and AbstractedPad - } - - ref_counter++; - return ResultSuccess; -} - -Result NPad::Activate(u64 aruid) { - std::scoped_lock lock{mutex}; - std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex}; - - auto* data = applet_resource_holder.applet_resource->GetAruidData(aruid); - const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return ResultSuccess; - } - - for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { - auto& controller = controller_data[aruid_index][i]; - controller.shared_memory = &data->shared_memory_format->npad.npad_entry[i].internal_state; - } - - // Prefill controller buffers - for (auto& controller : controller_data[aruid_index]) { - auto* npad = controller.shared_memory; - npad->fullkey_color = { - .attribute = ColorAttribute::NoController, - .fullkey = {}, - }; - npad->joycon_color = { - .attribute = ColorAttribute::NoController, - .left = {}, - .right = {}, - }; - // HW seems to initialize the first 19 entries - for (std::size_t i = 0; i < 19; ++i) { - WriteEmptyEntry(npad); - } - } - - return ResultSuccess; -} - -Result NPad::ActivateNpadResource() { - return npad_resource.Activate(); -} - -Result NPad::ActivateNpadResource(u64 aruid) { - return npad_resource.Activate(aruid); -} - -void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) { - if (type == Core::HID::ControllerTriggerType::All) { - ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); - ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); - return; - } - - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { - if (controller_idx >= controller_data[aruid_index].size()) { - return; - } - - auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); - - if (!data->flag.is_assigned) { - continue; - } - - auto& controller = controller_data[aruid_index][controller_idx]; - const auto is_connected = controller.device->IsConnected(); - const auto npad_type = controller.device->GetNpadStyleIndex(); - const auto npad_id = controller.device->GetNpadIdType(); - switch (type) { - case Core::HID::ControllerTriggerType::Connected: - case Core::HID::ControllerTriggerType::Disconnected: - if (is_connected == controller.is_connected) { - return; - } - UpdateControllerAt(data->aruid, npad_type, npad_id, is_connected); - break; - case Core::HID::ControllerTriggerType::Battery: { - if (!controller.device->IsConnected()) { - return; - } - auto* shared_memory = controller.shared_memory; - const auto& battery_level = controller.device->GetBattery(); - shared_memory->battery_level_dual = battery_level.dual.battery_level; - shared_memory->battery_level_left = battery_level.left.battery_level; - shared_memory->battery_level_right = battery_level.right.battery_level; - break; - } - default: - break; - } - } -} - -void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!npad_resource.IsControllerSupported(aruid, controller.device->GetNpadStyleIndex())) { - return; - } - LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); - const auto controller_type = controller.device->GetNpadStyleIndex(); - const auto& body_colors = controller.device->GetColors(); - const auto& battery_level = controller.device->GetBattery(); - auto* shared_memory = controller.shared_memory; - if (controller_type == Core::HID::NpadStyleIndex::None) { - npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); - return; - } - - // Reset memory values - shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; - shared_memory->device_type.raw = 0; - shared_memory->system_properties.raw = 0; - shared_memory->joycon_color.attribute = ColorAttribute::NoController; - shared_memory->joycon_color.attribute = ColorAttribute::NoController; - shared_memory->fullkey_color = {}; - shared_memory->joycon_color.left = {}; - shared_memory->joycon_color.right = {}; - shared_memory->battery_level_dual = {}; - shared_memory->battery_level_left = {}; - shared_memory->battery_level_right = {}; - - switch (controller_type) { - case Core::HID::NpadStyleIndex::None: - ASSERT(false); - break; - case Core::HID::NpadStyleIndex::ProController: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.fullkey; - shared_memory->battery_level_dual = battery_level.dual.battery_level; - shared_memory->style_tag.fullkey.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.dual.is_charging); - shared_memory->applet_footer_type = AppletFooterUiType::SwitchProController; - shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::Handheld: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.fullkey; - shared_memory->joycon_color.left = body_colors.left; - shared_memory->joycon_color.right = body_colors.right; - shared_memory->style_tag.handheld.Assign(1); - shared_memory->device_type.handheld_left.Assign(1); - shared_memory->device_type.handheld_right.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.use_directional_buttons.Assign(1); - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.left.is_charging); - shared_memory->system_properties.is_charging_joy_left.Assign( - battery_level.left.is_charging); - shared_memory->system_properties.is_charging_joy_right.Assign( - battery_level.right.is_charging); - shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; - shared_memory->applet_footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; - shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::JoyconDual: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->style_tag.joycon_dual.Assign(1); - if (controller.is_dual_left_connected) { - shared_memory->joycon_color.left = body_colors.left; - shared_memory->battery_level_left = battery_level.left.battery_level; - shared_memory->device_type.joycon_left.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.is_charging_joy_left.Assign( - battery_level.left.is_charging); - shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1); - } - if (controller.is_dual_right_connected) { - shared_memory->joycon_color.right = body_colors.right; - shared_memory->battery_level_right = battery_level.right.battery_level; - shared_memory->device_type.joycon_right.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.is_charging_joy_right.Assign( - battery_level.right.is_charging); - shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1); - } - shared_memory->system_properties.use_directional_buttons.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; - - if (controller.is_dual_left_connected && controller.is_dual_right_connected) { - shared_memory->applet_footer_type = AppletFooterUiType::JoyDual; - shared_memory->fullkey_color.fullkey = body_colors.left; - shared_memory->battery_level_dual = battery_level.left.battery_level; - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.left.is_charging); - } else if (controller.is_dual_left_connected) { - shared_memory->applet_footer_type = AppletFooterUiType::JoyDualLeftOnly; - shared_memory->fullkey_color.fullkey = body_colors.left; - shared_memory->battery_level_dual = battery_level.left.battery_level; - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.left.is_charging); - } else { - shared_memory->applet_footer_type = AppletFooterUiType::JoyDualRightOnly; - shared_memory->fullkey_color.fullkey = body_colors.right; - shared_memory->battery_level_dual = battery_level.right.battery_level; - shared_memory->system_properties.is_charging_joy_dual.Assign( - battery_level.right.is_charging); - } - break; - case Core::HID::NpadStyleIndex::JoyconLeft: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.left; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.left = body_colors.left; - shared_memory->battery_level_dual = battery_level.left.battery_level; - shared_memory->style_tag.joycon_left.Assign(1); - shared_memory->device_type.joycon_left.Assign(1); - shared_memory->system_properties.is_horizontal.Assign(1); - shared_memory->system_properties.use_minus.Assign(1); - shared_memory->system_properties.is_charging_joy_left.Assign( - battery_level.left.is_charging); - shared_memory->applet_footer_type = AppletFooterUiType::JoyLeftHorizontal; - shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::JoyconRight: - shared_memory->fullkey_color.attribute = ColorAttribute::Ok; - shared_memory->fullkey_color.fullkey = body_colors.right; - shared_memory->joycon_color.attribute = ColorAttribute::Ok; - shared_memory->joycon_color.right = body_colors.right; - shared_memory->battery_level_right = battery_level.right.battery_level; - shared_memory->style_tag.joycon_right.Assign(1); - shared_memory->device_type.joycon_right.Assign(1); - shared_memory->system_properties.is_horizontal.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - shared_memory->system_properties.is_charging_joy_right.Assign( - battery_level.right.is_charging); - shared_memory->applet_footer_type = AppletFooterUiType::JoyRightHorizontal; - shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::GameCube: - shared_memory->style_tag.gamecube.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->system_properties.is_vertical.Assign(1); - shared_memory->system_properties.use_plus.Assign(1); - break; - case Core::HID::NpadStyleIndex::Pokeball: - shared_memory->style_tag.palma.Assign(1); - shared_memory->device_type.palma.Assign(1); - shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1); - break; - case Core::HID::NpadStyleIndex::NES: - shared_memory->style_tag.lark.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - break; - case Core::HID::NpadStyleIndex::SNES: - shared_memory->style_tag.lucia.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->applet_footer_type = AppletFooterUiType::Lucia; - break; - case Core::HID::NpadStyleIndex::N64: - shared_memory->style_tag.lagoon.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - shared_memory->applet_footer_type = AppletFooterUiType::Lagon; - break; - case Core::HID::NpadStyleIndex::SegaGenesis: - shared_memory->style_tag.lager.Assign(1); - shared_memory->device_type.fullkey.Assign(1); - break; - default: - break; - } - - controller.is_connected = true; - controller.device->Connect(); - controller.device->SetLedPattern(); - if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) { - if (controller.is_dual_left_connected) { - controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex, - Common::Input::PollingMode::Active); - } - if (controller.is_dual_right_connected) { - controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Active); - } - } else { - controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, - Common::Input::PollingMode::Active); - } - - npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); - WriteEmptyEntry(controller.shared_memory); - hid_core.SetLastActiveController(npad_id); -} - -void NPad::WriteEmptyEntry(NpadInternalState* npad) { - NPadGenericState dummy_pad_state{}; - NpadGcTriggerState dummy_gc_state{}; - dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1; - npad->fullkey_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1; - npad->handheld_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; - npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1; - npad->joy_left_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1; - npad->joy_right_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1; - npad->palma_lifo.WriteNextEntry(dummy_pad_state); - dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1; - npad->system_ext_lifo.WriteNextEntry(dummy_pad_state); - dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; - npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); -} - -void NPad::RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id) { - std::scoped_lock lock{*applet_resource_holder.shared_mutex}; - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - const auto controller_type = controller.device->GetNpadStyleIndex(); - - if (!controller.device->IsConnected() && controller.is_connected) { - DisconnectNpad(aruid, npad_id); - return; - } - if (!controller.device->IsConnected()) { - return; - } - if (controller.device->IsConnected() && !controller.is_connected) { - InitNewlyAddedController(aruid, npad_id); - } - - // This function is unique to yuzu for the turbo buttons and motion to work properly - controller.device->StatusUpdate(); - - auto& pad_entry = controller.npad_pad_state; - auto& trigger_entry = controller.npad_trigger_state; - const auto button_state = controller.device->GetNpadButtons(); - const auto stick_state = controller.device->GetSticks(); - - using btn = Core::HID::NpadButton; - pad_entry.npad_buttons.raw = btn::None; - if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) { - constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R | - btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp | - btn::StickRRight | btn::StickRDown; - pad_entry.npad_buttons.raw = button_state.raw & right_button_mask; - pad_entry.r_stick = stick_state.right; - } - - if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) { - constexpr btn left_button_mask = - btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL | - btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown; - pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask; - pad_entry.l_stick = stick_state.left; - } - - if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft || - controller_type == Core::HID::NpadStyleIndex::JoyconDual) { - pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); - pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); - } - - if (controller_type == Core::HID::NpadStyleIndex::JoyconRight || - controller_type == Core::HID::NpadStyleIndex::JoyconDual) { - pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); - pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); - } - - if (controller_type == Core::HID::NpadStyleIndex::GameCube) { - const auto& trigger_state = controller.device->GetTriggers(); - trigger_entry.l_analog = trigger_state.left; - trigger_entry.r_analog = trigger_state.right; - pad_entry.npad_buttons.zl.Assign(false); - pad_entry.npad_buttons.zr.Assign(button_state.r); - pad_entry.npad_buttons.l.Assign(button_state.zl); - pad_entry.npad_buttons.r.Assign(button_state.zr); - } - - if (pad_entry.npad_buttons.raw != Core::HID::NpadButton::None) { - hid_core.SetLastActiveController(npad_id); - } -} - -void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (ref_counter == 0) { - return; - } - - std::scoped_lock lock{*applet_resource_holder.shared_mutex}; - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { - const auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index); - const auto aruid = data->aruid; - - if (!data->flag.is_assigned) { - continue; - } - - for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { - auto& controller = controller_data[aruid_index][i]; - controller.shared_memory = - &data->shared_memory_format->npad.npad_entry[i].internal_state; - auto* npad = controller.shared_memory; - - const auto& controller_type = controller.device->GetNpadStyleIndex(); - - if (controller_type == Core::HID::NpadStyleIndex::None || - !controller.device->IsConnected()) { - continue; - } - - RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); - auto& pad_state = controller.npad_pad_state; - auto& libnx_state = controller.npad_libnx_state; - auto& trigger_state = controller.npad_trigger_state; - - // LibNX exclusively uses this section, so we always update it since LibNX doesn't - // activate any controllers. - libnx_state.connection_status.raw = 0; - libnx_state.connection_status.is_connected.Assign(1); - switch (controller_type) { - case Core::HID::NpadStyleIndex::None: - ASSERT(false); - break; - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::NES: - case Core::HID::NpadStyleIndex::SNES: - case Core::HID::NpadStyleIndex::N64: - case Core::HID::NpadStyleIndex::SegaGenesis: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_wired.Assign(1); - - libnx_state.connection_status.is_wired.Assign(1); - pad_state.sampling_number = - npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->fullkey_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::Handheld: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_wired.Assign(1); - pad_state.connection_status.is_left_connected.Assign(1); - pad_state.connection_status.is_right_connected.Assign(1); - pad_state.connection_status.is_left_wired.Assign(1); - pad_state.connection_status.is_right_wired.Assign(1); - - libnx_state.connection_status.is_wired.Assign(1); - libnx_state.connection_status.is_left_connected.Assign(1); - libnx_state.connection_status.is_right_connected.Assign(1); - libnx_state.connection_status.is_left_wired.Assign(1); - libnx_state.connection_status.is_right_wired.Assign(1); - pad_state.sampling_number = - npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->handheld_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::JoyconDual: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - if (controller.is_dual_left_connected) { - pad_state.connection_status.is_left_connected.Assign(1); - libnx_state.connection_status.is_left_connected.Assign(1); - } - if (controller.is_dual_right_connected) { - pad_state.connection_status.is_right_connected.Assign(1); - libnx_state.connection_status.is_right_connected.Assign(1); - } - - pad_state.sampling_number = - npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->joy_dual_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::JoyconLeft: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_left_connected.Assign(1); - - libnx_state.connection_status.is_left_connected.Assign(1); - pad_state.sampling_number = - npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->joy_left_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::JoyconRight: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_right_connected.Assign(1); - - libnx_state.connection_status.is_right_connected.Assign(1); - pad_state.sampling_number = - npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->joy_right_lifo.WriteNextEntry(pad_state); - break; - case Core::HID::NpadStyleIndex::GameCube: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.connection_status.is_wired.Assign(1); - - libnx_state.connection_status.is_wired.Assign(1); - pad_state.sampling_number = - npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; - trigger_state.sampling_number = - npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->fullkey_lifo.WriteNextEntry(pad_state); - npad->gc_trigger_lifo.WriteNextEntry(trigger_state); - break; - case Core::HID::NpadStyleIndex::Pokeball: - pad_state.connection_status.raw = 0; - pad_state.connection_status.is_connected.Assign(1); - pad_state.sampling_number = - npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1; - npad->palma_lifo.WriteNextEntry(pad_state); - break; - default: - break; - } - - libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; - libnx_state.l_stick = pad_state.l_stick; - libnx_state.r_stick = pad_state.r_stick; - npad->system_ext_lifo.WriteNextEntry(pad_state); - - press_state |= static_cast<u64>(pad_state.npad_buttons.raw); - } - } -} - -Result NPad::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set) { - std::scoped_lock lock{mutex}; - hid_core.SetSupportedStyleTag({supported_style_set}); - const Result result = npad_resource.SetSupportedNpadStyleSet(aruid, supported_style_set); - if (result.IsSuccess()) { - OnUpdate({}); - } - return result; -} - -Result NPad::GetSupportedNpadStyleSet(u64 aruid, - Core::HID::NpadStyleSet& out_supported_style_set) const { - std::scoped_lock lock{mutex}; - const Result result = npad_resource.GetSupportedNpadStyleSet(out_supported_style_set, aruid); - - if (result == ResultUndefinedStyleset) { - out_supported_style_set = Core::HID::NpadStyleSet::None; - return ResultSuccess; - } - - return result; -} - -Result NPad::GetMaskedSupportedNpadStyleSet( - u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { - std::scoped_lock lock{mutex}; - const Result result = - npad_resource.GetMaskedSupportedNpadStyleSet(out_supported_style_set, aruid); - - if (result == ResultUndefinedStyleset) { - out_supported_style_set = Core::HID::NpadStyleSet::None; - return ResultSuccess; - } - - return result; -} - -Result NPad::SetSupportedNpadIdType(u64 aruid, - std::span<const Core::HID::NpadIdType> supported_npad_list) { - std::scoped_lock lock{mutex}; - if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { - return ResultInvalidArraySize; - } - - Result result = npad_resource.SetSupportedNpadIdType(aruid, supported_npad_list); - - if (result.IsSuccess()) { - OnUpdate({}); - } - - return result; -} - -Result NPad::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { - std::scoped_lock lock{mutex}; - return npad_resource.SetNpadJoyHoldType(aruid, hold_type); -} - -Result NPad::GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const { - std::scoped_lock lock{mutex}; - return npad_resource.GetNpadJoyHoldType(out_hold_type, aruid); -} - -Result NPad::SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode) { - std::scoped_lock lock{mutex}; - Result result = npad_resource.SetNpadHandheldActivationMode(aruid, mode); - if (result.IsSuccess()) { - OnUpdate({}); - } - return result; -} - -Result NPad::GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const { - std::scoped_lock lock{mutex}; - return npad_resource.GetNpadHandheldActivationMode(out_mode, aruid); -} - -bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, - NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return false; - } - - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (controller.shared_memory->assignment_mode != assignment_mode) { - controller.shared_memory->assignment_mode = assignment_mode; - } - - if (!controller.device->IsConnected()) { - return false; - } - - if (assignment_mode == NpadJoyAssignmentMode::Dual) { - if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) { - DisconnectNpad(aruid, npad_id); - controller.is_dual_left_connected = true; - controller.is_dual_right_connected = false; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return false; - } - if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { - DisconnectNpad(aruid, npad_id); - controller.is_dual_left_connected = false; - controller.is_dual_right_connected = true; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); - return false; - } - return false; - } - - // This is for NpadJoyAssignmentMode::Single - - // Only JoyconDual get affected by this function - if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { - return false; - } - - if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { - DisconnectNpad(aruid, npad_id); - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); - return false; - } - if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { - DisconnectNpad(aruid, npad_id); - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); - return false; - } - - // We have two controllers connected to the same npad_id we need to split them - new_npad_id = hid_core.GetFirstDisconnectedNpadId(); - auto& controller_2 = GetControllerFromNpadIdType(aruid, new_npad_id); - DisconnectNpad(aruid, npad_id); - if (npad_device_type == NpadJoyDeviceType::Left) { - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); - controller_2.is_dual_left_connected = false; - controller_2.is_dual_right_connected = true; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); - } else { - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); - controller_2.is_dual_left_connected = true; - controller_2.is_dual_right_connected = false; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); - } - return true; -} - -bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index, - const Core::HID::VibrationValue& vibration_value) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!controller.device->IsConnected()) { - return false; - } - - if (!controller.device->IsVibrationEnabled(device_index)) { - if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || - controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { - // Send an empty vibration to stop any vibrations. - Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; - controller.device->SetVibration(device_index, vibration); - // Then reset the vibration value to its default value. - controller.vibration[device_index].latest_vibration_value = - Core::HID::DEFAULT_VIBRATION_VALUE; - } - - return false; - } - - if (!Settings::values.enable_accurate_vibrations.GetValue()) { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::steady_clock; - - const auto now = steady_clock::now(); - - // Filter out non-zero vibrations that are within 15ms of each other. - if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && - duration_cast<milliseconds>( - now - controller.vibration[device_index].last_vibration_timepoint) < - milliseconds(15)) { - return false; - } - - controller.vibration[device_index].last_vibration_timepoint = now; - } - - Core::HID::VibrationValue vibration{ - vibration_value.low_amplitude, vibration_value.low_frequency, - vibration_value.high_amplitude, vibration_value.high_frequency}; - return controller.device->SetVibration(device_index, vibration); -} - -void NPad::VibrateController(u64 aruid, - const Core::HID::VibrationDeviceHandle& vibration_device_handle, - const Core::HID::VibrationValue& vibration_value) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); - - if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { - return; - } - - if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { - ASSERT_MSG(false, "DeviceIndex should never be None!"); - return; - } - - // Some games try to send mismatched parameters in the device handle, block these. - if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || - (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && - (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || - vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { - return; - } - - // Filter out vibrations with equivalent values to reduce unnecessary state changes. - if (vibration_value.low_amplitude == - controller.vibration[device_index].latest_vibration_value.low_amplitude && - vibration_value.high_amplitude == - controller.vibration[device_index].latest_vibration_value.high_amplitude) { - return; - } - - if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index, - vibration_value)) { - controller.vibration[device_index].latest_vibration_value = vibration_value; - } -} - -void NPad::VibrateControllers( - u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, - std::span<const Core::HID::VibrationValue> vibration_values) { - if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { - return; - } - - ASSERT_OR_EXECUTE_MSG( - vibration_device_handles.size() == vibration_values.size(), { return; }, - "The amount of device handles does not match with the amount of vibration values," - "this is undefined behavior!"); - - for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { - VibrateController(aruid, vibration_device_handles[i], vibration_values[i]); - } -} - -Core::HID::VibrationValue NPad::GetLastVibration( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return {}; - } - - const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); - return controller.vibration[device_index].latest_vibration_value; -} - -void NPad::InitializeVibrationDevice( - const Core::HID::VibrationDeviceHandle& vibration_device_handle) { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return; - } - - const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); - const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id); - const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); - InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index); -} - -void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!Settings::values.vibration_enabled.GetValue()) { - controller.vibration[device_index].device_mounted = false; - return; - } - - controller.vibration[device_index].device_mounted = - controller.device->IsVibrationEnabled(device_index); -} - -void NPad::SetPermitVibrationSession(bool permit_vibration_session) { - permit_vibration_session_enabled = permit_vibration_session; -} - -bool NPad::IsVibrationDeviceMounted( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { - if (IsVibrationHandleValid(vibration_device_handle).IsError()) { - return false; - } - - const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); - const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); - return controller.vibration[device_index].device_mounted; -} - -Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, - Core::HID::NpadIdType npad_id) { - std::scoped_lock lock{mutex}; - return npad_resource.AcquireNpadStyleSetUpdateEventHandle(aruid, out_event, npad_id); -} - -void NPad::AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, - Core::HID::NpadIdType npad_id) { - UpdateControllerAt(aruid, controller, npad_id, true); -} - -void NPad::UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex type, - Core::HID::NpadIdType npad_id, bool connected) { - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - if (!connected) { - DisconnectNpad(aruid, npad_id); - return; - } - - controller.device->SetNpadStyleIndex(type); - InitNewlyAddedController(aruid, npad_id); -} - -Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return ResultInvalidNpadId; - } - - LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); - auto& controller = GetControllerFromNpadIdType(aruid, npad_id); - for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { - // Send an empty vibration to stop any vibrations. - VibrateControllerAtIndex(aruid, npad_id, device_idx, {}); - controller.vibration[device_idx].device_mounted = false; - } - - auto* shared_memory = controller.shared_memory; - // Don't reset shared_memory->assignment_mode this value is persistent - shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out - shared_memory->device_type.raw = 0; - shared_memory->system_properties.raw = 0; - shared_memory->button_properties.raw = 0; - shared_memory->sixaxis_fullkey_properties.raw = 0; - shared_memory->sixaxis_handheld_properties.raw = 0; - shared_memory->sixaxis_dual_left_properties.raw = 0; - shared_memory->sixaxis_dual_right_properties.raw = 0; - shared_memory->sixaxis_left_properties.raw = 0; - shared_memory->sixaxis_right_properties.raw = 0; - shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty; - shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty; - shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty; - shared_memory->fullkey_color = { - .attribute = ColorAttribute::NoController, - .fullkey = {}, - }; - shared_memory->joycon_color = { - .attribute = ColorAttribute::NoController, - .left = {}, - .right = {}, - }; - shared_memory->applet_footer_type = AppletFooterUiType::None; - - controller.is_dual_left_connected = true; - controller.is_dual_right_connected = true; - controller.is_connected = false; - controller.device->Disconnect(); - npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); - WriteEmptyEntry(shared_memory); - return ResultSuccess; -} - -Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor( - u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool& is_firmware_available) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - const auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle); - is_firmware_available = sixaxis_properties.is_firmware_update_available != 0; - return ResultSuccess; -} - -Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( - u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle); - sixaxis_properties.is_newly_assigned.Assign(0); - - return ResultSuccess; -} - -Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2) { - if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, - npad_id_2); - return ResultInvalidNpadId; - } - auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1); - auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2); - auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); - auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); - - // Simplify this code by converting dualjoycon with only a side connected to single joycons - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) { - if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { - controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft; - } - if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) { - controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight; - } - } - if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { - if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) { - controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft; - } - if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) { - controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight; - } - } - - // Invalid merge errors - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual || - controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) { - return NpadIsDualJoycon; - } - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && - controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) { - return NpadIsSameType; - } - if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight && - controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { - return NpadIsSameType; - } - - // These exceptions are handled as if they where dual joycon - if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft && - controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) { - return NpadIsDualJoycon; - } - if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft && - controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) { - return NpadIsDualJoycon; - } - - // Disconnect the joycons and connect them as dual joycon at the first index. - DisconnectNpad(aruid, npad_id_1); - DisconnectNpad(aruid, npad_id_2); - controller_1.is_dual_left_connected = true; - controller_1.is_dual_right_connected = true; - AddNewControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); - return ResultSuccess; -} - -Result NPad::StartLrAssignmentMode(u64 aruid) { - std::scoped_lock lock{mutex}; - bool is_enabled{}; - Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); - if (result.IsSuccess() && is_enabled == false) { - result = npad_resource.SetLrAssignmentMode(aruid, true); - } - return result; -} - -Result NPad::StopLrAssignmentMode(u64 aruid) { - std::scoped_lock lock{mutex}; - bool is_enabled{}; - Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid); - if (result.IsSuccess() && is_enabled == true) { - result = npad_resource.SetLrAssignmentMode(aruid, false); - } - return result; -} - -Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2) { - if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, - npad_id_2); - return ResultInvalidNpadId; - } - if (npad_id_1 == Core::HID::NpadIdType::Handheld || - npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other || - npad_id_2 == Core::HID::NpadIdType::Other) { - return ResultSuccess; - } - const auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1).device; - const auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2).device; - const auto type_index_1 = controller_1->GetNpadStyleIndex(); - const auto type_index_2 = controller_2->GetNpadStyleIndex(); - const auto is_connected_1 = controller_1->IsConnected(); - const auto is_connected_2 = controller_2->IsConnected(); - - if (!npad_resource.IsControllerSupported(aruid, type_index_1) && is_connected_1) { - return ResultNpadNotConnected; - } - if (!npad_resource.IsControllerSupported(aruid, type_index_2) && is_connected_2) { - return ResultNpadNotConnected; - } - - UpdateControllerAt(aruid, type_index_2, npad_id_1, is_connected_2); - UpdateControllerAt(aruid, type_index_1, npad_id_2, is_connected_1); - - return ResultSuccess; -} - -Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - return ResultInvalidNpadId; - } - const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); - const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device; - pattern = controller->GetLedPattern(); - return ResultSuccess; -} - -Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, - Core::HID::NpadIdType npad_id) const { - std::scoped_lock lock{mutex}; - return npad_resource.GetHomeProtectionEnabled(out_is_enabled, aruid, npad_id); -} - -Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, - bool is_enabled) { - std::scoped_lock lock{mutex}; - return npad_resource.SetHomeProtectionEnabled(aruid, npad_id, is_enabled); -} - -void NPad::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { - std::scoped_lock lock{mutex}; - npad_resource.SetNpadAnalogStickUseCenterClamp(aruid, is_enabled); -} - -void NPad::ClearAllConnectedControllers() { - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { - for (auto& controller : controller_data[aruid_index]) { - if (controller.device->IsConnected() && - controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) { - controller.device->Disconnect(); - controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); - } - } - } -} - -void NPad::DisconnectAllConnectedControllers() { - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { - for (auto& controller : controller_data[aruid_index]) { - controller.device->Disconnect(); - } - } -} - -void NPad::ConnectAllDisconnectedControllers() { - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { - for (auto& controller : controller_data[aruid_index]) { - if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None && - !controller.device->IsConnected()) { - controller.device->Connect(); - } - } - } -} - -void NPad::ClearAllControllers() { - for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) { - for (auto& controller : controller_data[aruid_index]) { - controller.device->Disconnect(); - controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); - } - } -} - -Core::HID::NpadButton NPad::GetAndResetPressState() { - return static_cast<Core::HID::NpadButton>(press_state.exchange(0)); -} - -Result NPad::ApplyNpadSystemCommonPolicy(u64 aruid) { - std::scoped_lock lock{mutex}; - const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, false); - if (result.IsSuccess()) { - OnUpdate({}); - } - return result; -} - -Result NPad::ApplyNpadSystemCommonPolicyFull(u64 aruid) { - std::scoped_lock lock{mutex}; - const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, true); - if (result.IsSuccess()) { - OnUpdate({}); - } - return result; -} - -Result NPad::ClearNpadSystemCommonPolicy(u64 aruid) { - std::scoped_lock lock{mutex}; - const Result result = npad_resource.ClearNpadSystemCommonPolicy(aruid); - if (result.IsSuccess()) { - OnUpdate({}); - } - return result; -} - -void NPad::SetRevision(u64 aruid, NpadRevision revision) { - npad_resource.SetNpadRevision(aruid, revision); -} - -NpadRevision NPad::GetRevision(u64 aruid) { - return npad_resource.GetNpadRevision(aruid); -} - -Result NPad::RegisterAppletResourceUserId(u64 aruid) { - return npad_resource.RegisterAppletResourceUserId(aruid); -} - -void NPad::UnregisterAppletResourceUserId(u64 aruid) { - npad_resource.UnregisterAppletResourceUserId(aruid); -} - -void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, - std::recursive_mutex* shared_mutex) { - applet_resource_holder.applet_resource = resource; - applet_resource_holder.shared_mutex = shared_mutex; - applet_resource_holder.shared_npad_resource = &npad_resource; -} - -NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) { - const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); -} - -const NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { - const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); -} - -NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) { - const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); -} - -const NPad::NpadControllerData& NPad::GetControllerFromHandle( - u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const { - const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); - return GetControllerFromNpadIdType(aruid, npad_id); -} - -NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(u64 aruid, - Core::HID::NpadIdType npad_id) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - npad_id = Core::HID::NpadIdType::Player1; - } - const auto npad_index = NpadIdTypeToIndex(npad_id); - const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); - return controller_data[aruid_index][npad_index]; -} - -const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType( - u64 aruid, Core::HID::NpadIdType npad_id) const { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - npad_id = Core::HID::NpadIdType::Player1; - } - const auto npad_index = NpadIdTypeToIndex(npad_id); - const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid); - return controller_data[aruid_index][npad_index]; -} - -Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( - u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) { - auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); - switch (sixaxis_handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Pokeball: - return controller.shared_memory->sixaxis_fullkey_properties; - case Core::HID::NpadStyleIndex::Handheld: - return controller.shared_memory->sixaxis_handheld_properties; - case Core::HID::NpadStyleIndex::JoyconDual: - if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { - return controller.shared_memory->sixaxis_dual_left_properties; - } - return controller.shared_memory->sixaxis_dual_right_properties; - case Core::HID::NpadStyleIndex::JoyconLeft: - return controller.shared_memory->sixaxis_left_properties; - case Core::HID::NpadStyleIndex::JoyconRight: - return controller.shared_memory->sixaxis_right_properties; - default: - return controller.shared_memory->sixaxis_fullkey_properties; - } -} - -const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties( - u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { - const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle); - switch (sixaxis_handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Pokeball: - return controller.shared_memory->sixaxis_fullkey_properties; - case Core::HID::NpadStyleIndex::Handheld: - return controller.shared_memory->sixaxis_handheld_properties; - case Core::HID::NpadStyleIndex::JoyconDual: - if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { - return controller.shared_memory->sixaxis_dual_left_properties; - } - return controller.shared_memory->sixaxis_dual_right_properties; - case Core::HID::NpadStyleIndex::JoyconLeft: - return controller.shared_memory->sixaxis_left_properties; - case Core::HID::NpadStyleIndex::JoyconRight: - return controller.shared_memory->sixaxis_right_properties; - default: - return controller.shared_memory->sixaxis_fullkey_properties; - } -} - -AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) { - const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); - const auto& shared_memory = GetControllerFromNpadIdType(aruid, npad_id).shared_memory; - - return { - .ui_variant = 0, - .footer = shared_memory->applet_footer_type, - }; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <atomic> -#include <mutex> -#include <span> - -#include "common/common_types.h" -#include "core/hid/hid_types.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/controllers/npad/npad_resource.h" -#include "core/hle/service/hid/controllers/types/npad_types.h" - -namespace Core::HID { -class EmulatedController; -enum class ControllerTriggerType; -} // namespace Core::HID - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Service::KernelHelpers { -class ServiceContext; -} // namespace Service::KernelHelpers - -union Result; - -namespace Service::HID { -class AppletResource; -struct NpadInternalState; -struct NpadSixAxisSensorLifo; -struct NpadSharedMemoryFormat; - -class NPad final { -public: - explicit NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); - ~NPad(); - - Result Activate(); - Result Activate(u64 aruid); - - Result ActivateNpadResource(); - Result ActivateNpadResource(u64 aruid); - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing); - - Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set); - Result GetSupportedNpadStyleSet(u64 aruid, - Core::HID::NpadStyleSet& out_supported_style_set) const; - Result GetMaskedSupportedNpadStyleSet(u64 aruid, - Core::HID::NpadStyleSet& out_supported_style_set) const; - - Result SetSupportedNpadIdType(u64 aruid, - std::span<const Core::HID::NpadIdType> supported_npad_list); - - Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); - Result GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const; - - Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode); - Result GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const; - - bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, - NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); - - bool VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index, - const Core::HID::VibrationValue& vibration_value); - - void VibrateController(u64 aruid, - const Core::HID::VibrationDeviceHandle& vibration_device_handle, - const Core::HID::VibrationValue& vibration_value); - - void VibrateControllers( - u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, - std::span<const Core::HID::VibrationValue> vibration_values); - - Core::HID::VibrationValue GetLastVibration( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - - void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); - - void InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t device_index); - - void SetPermitVibrationSession(bool permit_vibration_session); - - bool IsVibrationDeviceMounted( - u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; - - Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, - Core::HID::NpadIdType npad_id); - - // Adds a new controller at an index. - void AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, - Core::HID::NpadIdType npad_id); - // Adds a new controller at an index with connection status. - void UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, - Core::HID::NpadIdType npad_id, bool connected); - - Result DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id); - - Result IsFirmwareUpdateAvailableForSixAxisSensor( - u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool& is_firmware_available) const; - Result ResetIsSixAxisSensorDeviceNewlyAssigned( - u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle); - - Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; - - Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, - Core::HID::NpadIdType npad_id) const; - Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, - bool is_enabled); - - void SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); - void ClearAllConnectedControllers(); - void DisconnectAllConnectedControllers(); - void ConnectAllDisconnectedControllers(); - void ClearAllControllers(); - - Result MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2); - Result StartLrAssignmentMode(u64 aruid); - Result StopLrAssignmentMode(u64 aruid); - Result SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2); - - // Logical OR for all buttons presses on all controllers - // Specifically for cheat engine and other features. - Core::HID::NpadButton GetAndResetPressState(); - - Result ApplyNpadSystemCommonPolicy(u64 aruid); - Result ApplyNpadSystemCommonPolicyFull(u64 aruid); - Result ClearNpadSystemCommonPolicy(u64 aruid); - - void SetRevision(u64 aruid, NpadRevision revision); - NpadRevision GetRevision(u64 aruid); - - Result RegisterAppletResourceUserId(u64 aruid); - void UnregisterAppletResourceUserId(u64 aruid); - void SetNpadExternals(std::shared_ptr<AppletResource> resource, - std::recursive_mutex* shared_mutex); - - AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); - -private: - struct VibrationData { - bool device_mounted{}; - Core::HID::VibrationValue latest_vibration_value{}; - std::chrono::steady_clock::time_point last_vibration_timepoint{}; - }; - - struct NpadControllerData { - NpadInternalState* shared_memory = nullptr; - Core::HID::EmulatedController* device = nullptr; - - std::array<VibrationData, 2> vibration{}; - bool is_connected{}; - - // Dual joycons can have only one side connected - bool is_dual_left_connected{true}; - bool is_dual_right_connected{true}; - - // Current pad state - NPadGenericState npad_pad_state{}; - NPadGenericState npad_libnx_state{}; - NpadGcTriggerState npad_trigger_state{}; - int callback_key{}; - }; - - void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); - void InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id); - void RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id); - void WriteEmptyEntry(NpadInternalState* npad); - - NpadControllerData& GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle); - const NpadControllerData& GetControllerFromHandle( - u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const; - NpadControllerData& GetControllerFromHandle( - u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); - const NpadControllerData& GetControllerFromHandle( - u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; - NpadControllerData& GetControllerFromNpadIdType(u64 aruid, Core::HID::NpadIdType npad_id); - const NpadControllerData& GetControllerFromNpadIdType(u64 aruid, - Core::HID::NpadIdType npad_id) const; - - Core::HID::SixAxisSensorProperties& GetSixaxisProperties( - u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); - const Core::HID::SixAxisSensorProperties& GetSixaxisProperties( - u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; - - Core::HID::HIDCore& hid_core; - KernelHelpers::ServiceContext& service_context; - - s32 ref_counter{}; - mutable std::mutex mutex; - NPadResource npad_resource; - AppletResourceHolder applet_resource_holder{}; - Kernel::KEvent* input_event{nullptr}; - std::mutex* input_mutex{nullptr}; - - std::atomic<u64> press_state{}; - bool permit_vibration_session_enabled; - std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> - controller_data{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/hle/service/hid/controllers/npad/npad_data.h" -#include "core/hle/service/hid/hid_util.h" - -namespace Service::HID { - -NPadData::NPadData() { - ClearNpadSystemCommonPolicy(); -} - -NPadData::~NPadData() = default; - -NpadStatus NPadData::GetNpadStatus() const { - return status; -} - -void NPadData::SetNpadAnalogStickUseCenterClamp(bool is_enabled) { - status.use_center_clamp.Assign(is_enabled); -} - -bool NPadData::GetNpadAnalogStickUseCenterClamp() const { - return status.use_center_clamp.As<bool>(); -} - -void NPadData::SetNpadSystemExtStateEnabled(bool is_enabled) { - status.system_ext_state.Assign(is_enabled); -} - -bool NPadData::GetNpadSystemExtState() const { - return status.system_ext_state.As<bool>(); -} - -Result NPadData::SetSupportedNpadIdType(std::span<const Core::HID::NpadIdType> list) { - // Note: Real limit is 11. But array size is 10. N's bug? - if (list.size() > MaxSupportedNpadIdTypes) { - return ResultInvalidArraySize; - } - - supported_npad_id_types_count = list.size(); - memcpy(supported_npad_id_types.data(), list.data(), - list.size() * sizeof(Core::HID::NpadIdType)); - - return ResultSuccess; -} - -std::size_t NPadData::GetSupportedNpadIdType(std::span<Core::HID::NpadIdType> out_list) const { - std::size_t out_size = std::min(supported_npad_id_types_count, out_list.size()); - - memcpy(out_list.data(), supported_npad_id_types.data(), - out_size * sizeof(Core::HID::NpadIdType)); - - return out_size; -} - -bool NPadData::IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const { - for (std::size_t i = 0; i < supported_npad_id_types_count; i++) { - if (supported_npad_id_types[i] == npad_id) { - return true; - } - } - - return false; -} - -void NPadData::SetNpadSystemCommonPolicy(bool is_full_policy) { - supported_npad_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::JoyDual | - Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; - handheld_activation_mode = NpadHandheldActivationMode::Dual; - - status.is_supported_styleset_set.Assign(true); - status.is_hold_type_set.Assign(true); - status.lr_assignment_mode.Assign(false); - status.is_policy.Assign(true); - if (is_full_policy) { - status.is_full_policy.Assign(true); - } - - supported_npad_id_types_count = 10; - supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; - supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; - supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; - supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; - supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; - supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; - supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; - supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; - supported_npad_id_types[8] = Core::HID::NpadIdType::Other; - supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; - - for (auto& input_protection : is_unintended_home_button_input_protection) { - input_protection = true; - } -} - -void NPadData::ClearNpadSystemCommonPolicy() { - status.raw = 0; - supported_npad_style_set = Core::HID::NpadStyleSet::All; - npad_hold_type = NpadJoyHoldType::Vertical; - handheld_activation_mode = NpadHandheldActivationMode::Dual; - - for (auto& button_assignment : npad_button_assignment) { - button_assignment = Core::HID::NpadButton::None; - } - - supported_npad_id_types_count = 10; - supported_npad_id_types[0] = Core::HID::NpadIdType::Player1; - supported_npad_id_types[1] = Core::HID::NpadIdType::Player2; - supported_npad_id_types[2] = Core::HID::NpadIdType::Player3; - supported_npad_id_types[3] = Core::HID::NpadIdType::Player4; - supported_npad_id_types[4] = Core::HID::NpadIdType::Player5; - supported_npad_id_types[5] = Core::HID::NpadIdType::Player6; - supported_npad_id_types[6] = Core::HID::NpadIdType::Player7; - supported_npad_id_types[7] = Core::HID::NpadIdType::Player8; - supported_npad_id_types[8] = Core::HID::NpadIdType::Other; - supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; - - for (auto& input_protection : is_unintended_home_button_input_protection) { - input_protection = true; - } -} - -void NPadData::SetNpadJoyHoldType(NpadJoyHoldType hold_type) { - npad_hold_type = hold_type; - status.is_hold_type_set.Assign(true); -} - -NpadJoyHoldType NPadData::GetNpadJoyHoldType() const { - return npad_hold_type; -} - -void NPadData::SetHandheldActivationMode(NpadHandheldActivationMode activation_mode) { - handheld_activation_mode = activation_mode; -} - -NpadHandheldActivationMode NPadData::GetHandheldActivationMode() const { - return handheld_activation_mode; -} - -void NPadData::SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set) { - supported_npad_style_set = style_set; - status.is_supported_styleset_set.Assign(true); - status.is_hold_type_set.Assign(true); -} - -Core::HID::NpadStyleSet NPadData::GetSupportedNpadStyleSet() const { - return supported_npad_style_set; -} - -bool NPadData::IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const { - Core::HID::NpadStyleTag style = {supported_npad_style_set}; - switch (style_index) { - case Core::HID::NpadStyleIndex::ProController: - return style.fullkey.As<bool>(); - case Core::HID::NpadStyleIndex::Handheld: - return style.handheld.As<bool>(); - case Core::HID::NpadStyleIndex::JoyconDual: - return style.joycon_dual.As<bool>(); - case Core::HID::NpadStyleIndex::JoyconLeft: - return style.joycon_left.As<bool>(); - case Core::HID::NpadStyleIndex::JoyconRight: - return style.joycon_right.As<bool>(); - case Core::HID::NpadStyleIndex::GameCube: - return style.gamecube.As<bool>(); - case Core::HID::NpadStyleIndex::Pokeball: - return style.palma.As<bool>(); - case Core::HID::NpadStyleIndex::NES: - return style.lark.As<bool>(); - case Core::HID::NpadStyleIndex::SNES: - return style.lucia.As<bool>(); - case Core::HID::NpadStyleIndex::N64: - return style.lagoon.As<bool>(); - case Core::HID::NpadStyleIndex::SegaGenesis: - return style.lager.As<bool>(); - default: - return false; - } -} - -void NPadData::SetLrAssignmentMode(bool is_enabled) { - status.lr_assignment_mode.Assign(is_enabled); -} - -bool NPadData::GetLrAssignmentMode() const { - return status.lr_assignment_mode.As<bool>(); -} - -void NPadData::SetAssigningSingleOnSlSrPress(bool is_enabled) { - status.assigning_single_on_sl_sr_press.Assign(is_enabled); -} - -bool NPadData::GetAssigningSingleOnSlSrPress() const { - return status.assigning_single_on_sl_sr_press.As<bool>(); -} - -void NPadData::SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id) { - is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)] = is_enabled; -} - -bool NPadData::GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const { - return is_unintended_home_button_input_protection[NpadIdTypeToIndex(npad_id)]; -} - -void NPadData::SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, - std::size_t style_index) { - npad_button_assignment[style_index] = button_assignment; -} - -Core::HID::NpadButton NPadData::GetCaptureButtonAssignment(std::size_t style_index) const { - return npad_button_assignment[style_index]; -} - -std::size_t NPadData::GetNpadCaptureButtonAssignmentList( - std::span<Core::HID::NpadButton> out_list) const { - for (std::size_t i = 0; i < out_list.size(); i++) { - Core::HID::NpadStyleSet style_set = GetStylesetByIndex(i); - if ((style_set & supported_npad_style_set) == Core::HID::NpadStyleSet::None || - npad_button_assignment[i] == Core::HID::NpadButton::None) { - return i; - } - out_list[i] = npad_button_assignment[i]; - } - - return out_list.size(); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <array> -#include <span> - -#include "common/common_types.h" -#include "core/hid/hid_types.h" -#include "core/hle/result.h" -#include "core/hle/service/hid/controllers/types/npad_types.h" - -namespace Service::HID { - -struct NpadStatus { - union { - u32 raw{}; - - BitField<0, 1, u32> is_supported_styleset_set; - BitField<1, 1, u32> is_hold_type_set; - BitField<2, 1, u32> lr_assignment_mode; - BitField<3, 1, u32> assigning_single_on_sl_sr_press; - BitField<4, 1, u32> is_full_policy; - BitField<5, 1, u32> is_policy; - BitField<6, 1, u32> use_center_clamp; - BitField<7, 1, u32> system_ext_state; - }; -}; -static_assert(sizeof(NpadStatus) == 4, "NpadStatus is an invalid size"); - -/// Handles Npad request from HID interfaces -class NPadData final { -public: - explicit NPadData(); - ~NPadData(); - - NpadStatus GetNpadStatus() const; - - void SetNpadAnalogStickUseCenterClamp(bool is_enabled); - bool GetNpadAnalogStickUseCenterClamp() const; - - void SetNpadSystemExtStateEnabled(bool is_enabled); - bool GetNpadSystemExtState() const; - - Result SetSupportedNpadIdType(std::span<const Core::HID::NpadIdType> list); - std::size_t GetSupportedNpadIdType(std::span<Core::HID::NpadIdType> out_list) const; - bool IsNpadIdTypeSupported(Core::HID::NpadIdType npad_id) const; - - void SetNpadSystemCommonPolicy(bool is_full_policy); - void ClearNpadSystemCommonPolicy(); - - void SetNpadJoyHoldType(NpadJoyHoldType hold_type); - NpadJoyHoldType GetNpadJoyHoldType() const; - - void SetHandheldActivationMode(NpadHandheldActivationMode activation_mode); - NpadHandheldActivationMode GetHandheldActivationMode() const; - - void SetSupportedNpadStyleSet(Core::HID::NpadStyleSet style_set); - Core::HID::NpadStyleSet GetSupportedNpadStyleSet() const; - bool IsNpadStyleIndexSupported(Core::HID::NpadStyleIndex style_index) const; - - void SetLrAssignmentMode(bool is_enabled); - bool GetLrAssignmentMode() const; - - void SetAssigningSingleOnSlSrPress(bool is_enabled); - bool GetAssigningSingleOnSlSrPress() const; - - void SetHomeProtectionEnabled(bool is_enabled, Core::HID::NpadIdType npad_id); - bool GetHomeProtectionEnabled(Core::HID::NpadIdType npad_id) const; - - void SetCaptureButtonAssignment(Core::HID::NpadButton button_assignment, - std::size_t style_index); - Core::HID::NpadButton GetCaptureButtonAssignment(std::size_t style_index) const; - std::size_t GetNpadCaptureButtonAssignmentList(std::span<Core::HID::NpadButton> out_list) const; - -private: - NpadStatus status{}; - Core::HID::NpadStyleSet supported_npad_style_set{Core::HID::NpadStyleSet::All}; - NpadJoyHoldType npad_hold_type{NpadJoyHoldType::Vertical}; - NpadHandheldActivationMode handheld_activation_mode{}; - std::array<Core::HID::NpadIdType, MaxSupportedNpadIdTypes> supported_npad_id_types{}; - std::array<Core::HID::NpadButton, StyleIndexCount> npad_button_assignment{}; - std::size_t supported_npad_id_types_count{}; - std::array<bool, MaxSupportedNpadIdTypes> is_unintended_home_button_input_protection{}; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/hid/controllers/npad/npad_resource.h" -#include "core/hle/service/hid/controllers/types/npad_types.h" -#include "core/hle/service/hid/errors.h" -#include "core/hle/service/hid/hid_util.h" - -namespace Service::HID { - -NPadResource::NPadResource(KernelHelpers::ServiceContext& context) : service_context{context} {} - -NPadResource::~NPadResource() = default; - -Result NPadResource::RegisterAppletResourceUserId(u64 aruid) { - const auto aruid_index = GetIndexFromAruid(aruid); - if (aruid_index < AruidIndexMax) { - return ResultAruidAlreadyRegistered; - } - - std::size_t data_index = AruidIndexMax; - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (!state[i].flag.is_initialized) { - data_index = i; - break; - } - } - - if (data_index == AruidIndexMax) { - return ResultAruidNoAvailableEntries; - } - - auto& aruid_data = state[data_index]; - - aruid_data.aruid = aruid; - aruid_data.flag.is_initialized.Assign(true); - - data_index = AruidIndexMax; - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (registration_list.flag[i] == RegistrationStatus::Initialized) { - if (registration_list.aruid[i] != aruid) { - continue; - } - data_index = i; - break; - } - if (registration_list.flag[i] == RegistrationStatus::None) { - data_index = i; - break; - } - } - - if (data_index == AruidIndexMax) { - return ResultSuccess; - } - - registration_list.flag[data_index] = RegistrationStatus::Initialized; - registration_list.aruid[data_index] = aruid; - - return ResultSuccess; -} - -void NPadResource::UnregisterAppletResourceUserId(u64 aruid) { - const u64 aruid_index = GetIndexFromAruid(aruid); - - DestroyStyleSetUpdateEvents(aruid); - if (aruid_index < AruidIndexMax) { - state[aruid_index] = {}; - registration_list.flag[aruid_index] = RegistrationStatus::PendingDelete; - } -} - -void NPadResource::DestroyStyleSetUpdateEvents(u64 aruid) { - const u64 aruid_index = GetIndexFromAruid(aruid); - - if (aruid_index >= AruidIndexMax) { - return; - } - - for (auto& controller_state : state[aruid_index].controller_state) { - if (!controller_state.is_styleset_update_event_initialized) { - continue; - } - service_context.CloseEvent(controller_state.style_set_update_event); - controller_state.is_styleset_update_event_initialized = false; - } -} - -Result NPadResource::Activate(u64 aruid) { - const u64 aruid_index = GetIndexFromAruid(aruid); - - if (aruid_index >= AruidIndexMax) { - return ResultSuccess; - } - - auto& state_data = state[aruid_index]; - - if (state_data.flag.is_assigned) { - return ResultAruidAlreadyRegistered; - } - - state_data.flag.is_assigned.Assign(true); - state_data.data.ClearNpadSystemCommonPolicy(); - state_data.npad_revision = NpadRevision::Revision0; - state_data.button_config = {}; - - if (active_data_aruid == aruid) { - default_hold_type = active_data.GetNpadJoyHoldType(); - active_data.SetNpadJoyHoldType(default_hold_type); - } - return ResultSuccess; -} - -Result NPadResource::Activate() { - if (ref_counter == std::numeric_limits<s32>::max() - 1) { - return ResultAppletResourceOverflow; - } - if (ref_counter == 0) { - RegisterAppletResourceUserId(SystemAruid); - Activate(SystemAruid); - } - ref_counter++; - return ResultSuccess; -} - -Result NPadResource::Deactivate() { - if (ref_counter == 0) { - return ResultAppletResourceNotInitialized; - } - - UnregisterAppletResourceUserId(SystemAruid); - ref_counter--; - return ResultSuccess; -} - -NPadData* NPadResource::GetActiveData() { - return &active_data; -} - -u64 NPadResource::GetActiveDataAruid() { - return active_data_aruid; -} - -void NPadResource::SetAppletResourceUserId(u64 aruid) { - if (active_data_aruid == aruid) { - return; - } - - active_data_aruid = aruid; - default_hold_type = active_data.GetNpadJoyHoldType(); - const u64 aruid_index = GetIndexFromAruid(aruid); - - if (aruid_index >= AruidIndexMax) { - return; - } - - auto& data = state[aruid_index].data; - if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { - data.SetNpadJoyHoldType(default_hold_type); - } - - active_data = data; - if (data.GetNpadStatus().is_hold_type_set) { - active_data.SetNpadJoyHoldType(default_hold_type); - } -} - -std::size_t NPadResource::GetIndexFromAruid(u64 aruid) const { - for (std::size_t i = 0; i < AruidIndexMax; i++) { - if (registration_list.flag[i] == RegistrationStatus::Initialized && - registration_list.aruid[i] == aruid) { - return i; - } - } - return AruidIndexMax; -} - -Result NPadResource::ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - auto& data = state[aruid_index].data; - data.SetNpadSystemCommonPolicy(is_full_policy); - data.SetNpadJoyHoldType(default_hold_type); - if (active_data_aruid == aruid) { - active_data.SetNpadSystemCommonPolicy(is_full_policy); - active_data.SetNpadJoyHoldType(default_hold_type); - } - return ResultSuccess; -} - -Result NPadResource::ClearNpadSystemCommonPolicy(u64 aruid) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.ClearNpadSystemCommonPolicy(); - if (active_data_aruid == aruid) { - active_data.ClearNpadSystemCommonPolicy(); - } - return ResultSuccess; -} - -Result NPadResource::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - auto& data = state[aruid_index].data; - data.SetSupportedNpadStyleSet(style_set); - if (active_data_aruid == aruid) { - active_data.SetSupportedNpadStyleSet(style_set); - active_data.SetNpadJoyHoldType(data.GetNpadJoyHoldType()); - } - return ResultSuccess; -} - -Result NPadResource::GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, - u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - auto& data = state[aruid_index].data; - if (!data.GetNpadStatus().is_supported_styleset_set) { - return ResultUndefinedStyleset; - } - - out_style_Set = data.GetSupportedNpadStyleSet(); - return ResultSuccess; -} - -Result NPadResource::GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, - u64 aruid) const { - if (aruid == SystemAruid) { - out_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Palma | - Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; - return ResultSuccess; - } - - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - auto& data = state[aruid_index].data; - if (!data.GetNpadStatus().is_supported_styleset_set) { - return ResultUndefinedStyleset; - } - - Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; - out_style_set = data.GetSupportedNpadStyleSet(); - - switch (state[aruid_index].npad_revision) { - case NpadRevision::Revision1: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | - Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | - Core::HID::NpadStyleSet::System; - break; - case NpadRevision::Revision2: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | - Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | - Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; - break; - case NpadRevision::Revision3: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | - Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | - Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | - Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | - Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; - break; - default: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | - Core::HID::NpadStyleSet::System; - break; - } - - out_style_set = out_style_set & mask; - return ResultSuccess; -} - -Result NPadResource::GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - auto& data = state[aruid_index].data; - if (!data.GetNpadStatus().is_supported_styleset_set) { - return ResultUndefinedStyleset; - } - - Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None}; - out_style_set = data.GetSupportedNpadStyleSet(); - - switch (state[aruid_index].npad_revision) { - case NpadRevision::Revision1: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | - Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt | - Core::HID::NpadStyleSet::System; - break; - case NpadRevision::Revision2: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | - Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | - Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; - break; - case NpadRevision::Revision3: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc | - Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark | - Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia | - Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager | - Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System; - break; - default: - mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld | - Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft | - Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt | - Core::HID::NpadStyleSet::System; - break; - } - - out_style_set = out_style_set & mask; - return ResultSuccess; -} - -NpadRevision NPadResource::GetNpadRevision(u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return NpadRevision::Revision0; - } - - return state[aruid_index].npad_revision; -} - -Result NPadResource::IsSupportedNpadStyleSet(bool& is_set, u64 aruid) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - is_set = state[aruid_index].data.GetNpadStatus().is_supported_styleset_set.Value() != 0; - return ResultSuccess; -} - -Result NPadResource::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.SetNpadJoyHoldType(hold_type); - if (active_data_aruid == aruid) { - active_data.SetNpadJoyHoldType(hold_type); - } - return ResultSuccess; -} - -Result NPadResource::GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - auto& data = state[aruid_index].data; - if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) { - hold_type = active_data.GetNpadJoyHoldType(); - return ResultSuccess; - } - hold_type = data.GetNpadJoyHoldType(); - return ResultSuccess; -} - -Result NPadResource::SetNpadHandheldActivationMode(u64 aruid, - NpadHandheldActivationMode activation_mode) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.SetHandheldActivationMode(activation_mode); - if (active_data_aruid == aruid) { - active_data.SetHandheldActivationMode(activation_mode); - } - return ResultSuccess; -} - -Result NPadResource::GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, - u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - activation_mode = state[aruid_index].data.GetHandheldActivationMode(); - return ResultSuccess; -} - -Result NPadResource::SetSupportedNpadIdType( - u64 aruid, std::span<const Core::HID::NpadIdType> supported_npad_list) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { - return ResultInvalidArraySize; - } - - Result result = state[aruid_index].data.SetSupportedNpadIdType(supported_npad_list); - if (result.IsSuccess() && active_data_aruid == aruid) { - result = active_data.SetSupportedNpadIdType(supported_npad_list); - } - - return result; -} - -bool NPadResource::IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return false; - } - return state[aruid_index].data.IsNpadStyleIndexSupported(style_index); -} - -Result NPadResource::SetLrAssignmentMode(u64 aruid, bool is_enabled) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.SetLrAssignmentMode(is_enabled); - if (active_data_aruid == aruid) { - active_data.SetLrAssignmentMode(is_enabled); - } - return ResultSuccess; -} - -Result NPadResource::GetLrAssignmentMode(bool& is_enabled, u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - is_enabled = state[aruid_index].data.GetLrAssignmentMode(); - return ResultSuccess; -} - -Result NPadResource::SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.SetAssigningSingleOnSlSrPress(is_enabled); - if (active_data_aruid == aruid) { - active_data.SetAssigningSingleOnSlSrPress(is_enabled); - } - return ResultSuccess; -} - -Result NPadResource::IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - is_enabled = state[aruid_index].data.GetAssigningSingleOnSlSrPress(); - return ResultSuccess; -} - -Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, - Kernel::KReadableEvent** out_event, - Core::HID::NpadIdType npad_id) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - auto& controller_state = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; - if (!controller_state.is_styleset_update_event_initialized) { - // Auto clear = true - controller_state.style_set_update_event = - service_context.CreateEvent("NpadResource:StylesetUpdateEvent"); - - // Assume creating the event succeeds otherwise crash the system here - controller_state.is_styleset_update_event_initialized = true; - } - - *out_event = &controller_state.style_set_update_event->GetReadableEvent(); - - if (controller_state.is_styleset_update_event_initialized) { - controller_state.style_set_update_event->Signal(); - } - - return ResultSuccess; -} - -Result NPadResource::SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - auto controller = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; - if (controller.is_styleset_update_event_initialized) { - controller.style_set_update_event->Signal(); - } - return ResultSuccess; -} - -Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, - Core::HID::NpadIdType npad_id) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - is_enabled = state[aruid_index].data.GetHomeProtectionEnabled(npad_id); - return ResultSuccess; -} - -Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, - bool is_enabled) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.SetHomeProtectionEnabled(is_enabled, npad_id); - if (active_data_aruid == aruid) { - active_data.SetHomeProtectionEnabled(is_enabled, npad_id); - } - return ResultSuccess; -} - -Result NPadResource::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); - if (active_data_aruid == aruid) { - active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); - } - return ResultSuccess; -} - -Result NPadResource::SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, - Core::HID::NpadButton button_config) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index] = button_config; - return ResultSuccess; -} - -Core::HID::NpadButton NPadResource::GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t index, Core::HID::NpadButton mask, - bool is_enabled) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return Core::HID::NpadButton::None; - } - - auto& button_config = state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index]; - if (is_enabled) { - button_config = button_config | mask; - return button_config; - } - - button_config = Core::HID::NpadButton::None; - return Core::HID::NpadButton::None; -} - -void NPadResource::ResetButtonConfig() { - for (auto& selected_state : state) { - selected_state.button_config = {}; - } -} - -Result NPadResource::SetNpadCaptureButtonAssignment(u64 aruid, - Core::HID::NpadStyleSet npad_style_set, - Core::HID::NpadButton button_assignment) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - // Must be a power of two - const auto raw_styleset = static_cast<u32>(npad_style_set); - if (raw_styleset == 0 && (raw_styleset & (raw_styleset - 1)) != 0) { - return ResultMultipleStyleSetSelected; - } - - std::size_t style_index{}; - Core::HID::NpadStyleSet style_selected{}; - for (style_index = 0; style_index < StyleIndexCount; ++style_index) { - style_selected = GetStylesetByIndex(style_index); - if (npad_style_set == style_selected) { - break; - } - } - - if (style_selected == Core::HID::NpadStyleSet::None) { - return ResultMultipleStyleSetSelected; - } - - state[aruid_index].data.SetCaptureButtonAssignment(button_assignment, style_index); - if (active_data_aruid == aruid) { - active_data.SetCaptureButtonAssignment(button_assignment, style_index); - } - return ResultSuccess; -} - -Result NPadResource::ClearNpadCaptureButtonAssignment(u64 aruid) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - for (std::size_t i = 0; i < StyleIndexCount; i++) { - state[aruid_index].data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); - if (active_data_aruid == aruid) { - active_data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i); - } - } - return ResultSuccess; -} - -std::size_t NPadResource::GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list, - u64 aruid) const { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return 0; - } - return state[aruid_index].data.GetNpadCaptureButtonAssignmentList(out_list); -} - -void NPadResource::SetNpadRevision(u64 aruid, NpadRevision revision) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return; - } - - state[aruid_index].npad_revision = revision; -} - -Result NPadResource::SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled) { - const u64 aruid_index = GetIndexFromAruid(aruid); - if (aruid_index >= AruidIndexMax) { - return ResultNpadNotConnected; - } - - state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled); - if (active_data_aruid == aruid) { - active_data.SetNpadAnalogStickUseCenterClamp(is_enabled); - } - return ResultSuccess; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <array> -#include <mutex> -#include <span> - -#include "common/common_types.h" -#include "core/hid/hid_types.h" -#include "core/hle/result.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/npad/npad_data.h" -#include "core/hle/service/hid/controllers/types/npad_types.h" -#include "core/hle/service/kernel_helpers.h" - -namespace Core { -class System; -} - -namespace Kernel { -class KReadableEvent; -} - -namespace Service::HID { -struct DataStatusFlag; - -struct NpadControllerState { - bool is_styleset_update_event_initialized{}; - INSERT_PADDING_BYTES(0x7); - Kernel::KEvent* style_set_update_event{nullptr}; - INSERT_PADDING_BYTES(0x27); -}; - -struct NpadState { - DataStatusFlag flag{}; - u64 aruid{}; - NPadData data{}; - std::array<std::array<Core::HID::NpadButton, StyleIndexCount>, MaxSupportedNpadIdTypes> - button_config; - std::array<NpadControllerState, MaxSupportedNpadIdTypes> controller_state; - NpadRevision npad_revision; -}; - -/// Handles Npad request from HID interfaces -class NPadResource final { -public: - explicit NPadResource(KernelHelpers::ServiceContext& context); - ~NPadResource(); - - NPadData* GetActiveData(); - u64 GetActiveDataAruid(); - - Result RegisterAppletResourceUserId(u64 aruid); - void UnregisterAppletResourceUserId(u64 aruid); - - void DestroyStyleSetUpdateEvents(u64 aruid); - - Result Activate(u64 aruid); - Result Activate(); - Result Deactivate(); - - void SetAppletResourceUserId(u64 aruid); - std::size_t GetIndexFromAruid(u64 aruid) const; - - Result ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy); - Result ClearNpadSystemCommonPolicy(u64 aruid); - - Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set); - Result GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set, u64 aruid) const; - Result GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; - Result GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const; - - NpadRevision GetNpadRevision(u64 aruid) const; - void SetNpadRevision(u64 aruid, NpadRevision revision); - - Result IsSupportedNpadStyleSet(bool& is_set, u64 aruid); - - Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); - Result GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const; - - Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode activation_mode); - Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, - u64 aruid) const; - - Result SetSupportedNpadIdType(u64 aruid, - std::span<const Core::HID::NpadIdType> supported_npad_list); - bool IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const; - - Result SetLrAssignmentMode(u64 aruid, bool is_enabled); - Result GetLrAssignmentMode(bool& is_enabled, u64 aruid) const; - - Result SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled); - Result IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const; - - Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, - Core::HID::NpadIdType npad_id); - Result SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id); - - Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, - Core::HID::NpadIdType npad_id) const; - Result SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled); - - Result SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); - - Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, - Core::HID::NpadButton button_config); - Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t index, Core::HID::NpadButton mask, - bool is_enabled); - void ResetButtonConfig(); - - Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, - Core::HID::NpadButton button_assignment); - Result ClearNpadCaptureButtonAssignment(u64 aruid); - std::size_t GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list, - u64 aruid) const; - - Result SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled); - -private: - NPadData active_data{}; - AruidRegisterList registration_list{}; - std::array<NpadState, AruidIndexMax> state{}; - u64 active_data_aruid{}; - NpadJoyHoldType default_hold_type{}; - s32 ref_counter{}; - - KernelHelpers::ServiceContext& service_context; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/hid/controllers/palma.h" -#include "core/hle/service/kernel_helpers.h" - -namespace Service::HID { - -Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) - : ControllerBase{hid_core_}, service_context{service_context_} { - controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); - operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); -} - -Palma::~Palma() { - service_context.CloseEvent(operation_complete_event); -}; - -void Palma::OnInit() {} - -void Palma::OnRelease() {} - -void Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!IsControllerActivated()) { - return; - } -} - -Result Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, - PalmaConnectionHandle& handle) { - active_handle.npad_id = npad_id; - handle = active_handle; - return ResultSuccess; -} - -Result Palma::InitializePalma(const PalmaConnectionHandle& handle) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - Activate(); - return ResultSuccess; -} - -Kernel::KReadableEvent& Palma::AcquirePalmaOperationCompleteEvent( - const PalmaConnectionHandle& handle) const { - if (handle.npad_id != active_handle.npad_id) { - LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id); - } - return operation_complete_event->GetReadableEvent(); -} - -Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle, - PalmaOperationType& operation_type, - PalmaOperationData& data) const { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation_type = operation.operation; - data = operation.data; - return ResultSuccess; -} - -Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation.operation = PalmaOperationType::PlayActivity; - operation.result = PalmaResultSuccess; - operation.data = {}; - operation_complete_event->Signal(); - return ResultSuccess; -} - -Result Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - fr_mode = fr_mode_; - return ResultSuccess; -} - -Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation.operation = PalmaOperationType::ReadStep; - operation.result = PalmaResultSuccess; - operation.data = {}; - operation_complete_event->Signal(); - return ResultSuccess; -} - -Result Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - return ResultSuccess; -} - -Result Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - return ResultSuccess; -} - -void Palma::ReadPalmaApplicationSection() {} - -void Palma::WritePalmaApplicationSection() {} - -Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation.operation = PalmaOperationType::ReadUniqueCode; - operation.result = PalmaResultSuccess; - operation.data = {}; - operation_complete_event->Signal(); - return ResultSuccess; -} - -Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation.operation = PalmaOperationType::SetUniqueCodeInvalid; - operation.result = PalmaResultSuccess; - operation.data = {}; - operation_complete_event->Signal(); - return ResultSuccess; -} - -void Palma::WritePalmaActivityEntry() {} - -Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation.operation = PalmaOperationType::WriteRgbLedPatternEntry; - operation.result = PalmaResultSuccess; - operation.data = {}; - operation_complete_event->Signal(); - return ResultSuccess; -} - -Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, - Common::ProcessAddress t_mem, u64 size) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation.operation = PalmaOperationType::WriteWaveEntry; - operation.result = PalmaResultSuccess; - operation.data = {}; - operation_complete_event->Signal(); - return ResultSuccess; -} - -Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, - s32 database_id_version_) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - database_id_version = database_id_version_; - operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; - operation.result = PalmaResultSuccess; - operation.data[0] = {}; - operation_complete_event->Signal(); - return ResultSuccess; -} - -Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; - operation.result = PalmaResultSuccess; - operation.data = {}; - operation.data[0] = static_cast<u8>(database_id_version); - operation_complete_event->Signal(); - return ResultSuccess; -} - -void Palma::SuspendPalmaFeature() {} - -Result Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - return operation.result; -} -void Palma::ReadPalmaPlayLog() {} - -void Palma::ResetPalmaPlayLog() {} - -void Palma::SetIsPalmaAllConnectable(bool is_all_connectable) { - // If true controllers are able to be paired - is_connectable = is_all_connectable; -} - -void Palma::SetIsPalmaPairedConnectable() {} - -Result Palma::PairPalma(const PalmaConnectionHandle& handle) { - if (handle.npad_id != active_handle.npad_id) { - return InvalidPalmaHandle; - } - // TODO: Do something - return ResultSuccess; -} - -void Palma::SetPalmaBoostMode(bool boost_mode) {} - -void Palma::CancelWritePalmaWaveEntry() {} - -void Palma::EnablePalmaBoostMode() {} - -void Palma::GetPalmaBluetoothAddress() {} - -void Palma::SetDisallowedPalmaConnection() {} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include "common/common_funcs.h" -#include "common/typed_address.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/errors.h" - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Service::KernelHelpers { -class ServiceContext; -} - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::HID { -class Palma final : public ControllerBase { -public: - using PalmaOperationData = std::array<u8, 0x140>; - - // This is nn::hid::PalmaOperationType - enum class PalmaOperationType { - PlayActivity, - SetFrModeType, - ReadStep, - EnableStep, - ResetStep, - ReadApplicationSection, - WriteApplicationSection, - ReadUniqueCode, - SetUniqueCodeInvalid, - WriteActivityEntry, - WriteRgbLedPatternEntry, - WriteWaveEntry, - ReadDataBaseIdentificationVersion, - WriteDataBaseIdentificationVersion, - SuspendFeature, - ReadPlayLog, - ResetPlayLog, - }; - - // This is nn::hid::PalmaWaveSet - enum class PalmaWaveSet : u64 { - Small, - Medium, - Large, - }; - - // This is nn::hid::PalmaFrModeType - enum class PalmaFrModeType : u64 { - Off, - B01, - B02, - B03, - Downloaded, - }; - - // This is nn::hid::PalmaFeature - enum class PalmaFeature : u64 { - FrMode, - RumbleFeedback, - Step, - MuteSwitch, - }; - - // This is nn::hid::PalmaOperationInfo - struct PalmaOperationInfo { - PalmaOperationType operation{}; - Result result{PalmaResultSuccess}; - PalmaOperationData data{}; - }; - static_assert(sizeof(PalmaOperationInfo) == 0x148, "PalmaOperationInfo is an invalid size"); - - // This is nn::hid::PalmaActivityEntry - struct PalmaActivityEntry { - u32 rgb_led_pattern_index; - INSERT_PADDING_BYTES(2); - PalmaWaveSet wave_set; - u32 wave_index; - INSERT_PADDING_BYTES(12); - }; - static_assert(sizeof(PalmaActivityEntry) == 0x20, "PalmaActivityEntry is an invalid size"); - - struct PalmaConnectionHandle { - Core::HID::NpadIdType npad_id; - INSERT_PADDING_BYTES(4); // Unknown - }; - static_assert(sizeof(PalmaConnectionHandle) == 0x8, - "PalmaConnectionHandle has incorrect size."); - - explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_); - ~Palma() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - - Result GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, PalmaConnectionHandle& handle); - Result InitializePalma(const PalmaConnectionHandle& handle); - Kernel::KReadableEvent& AcquirePalmaOperationCompleteEvent( - const PalmaConnectionHandle& handle) const; - Result GetPalmaOperationInfo(const PalmaConnectionHandle& handle, - PalmaOperationType& operation_type, - PalmaOperationData& data) const; - Result PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity); - Result SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_); - Result ReadPalmaStep(const PalmaConnectionHandle& handle); - Result EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled); - Result ResetPalmaStep(const PalmaConnectionHandle& handle); - Result ReadPalmaUniqueCode(const PalmaConnectionHandle& handle); - Result SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle); - Result WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown); - Result WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, - Common::ProcessAddress t_mem, u64 size); - Result SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, - s32 database_id_version_); - Result GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle); - Result GetPalmaOperationResult(const PalmaConnectionHandle& handle) const; - void SetIsPalmaAllConnectable(bool is_all_connectable); - Result PairPalma(const PalmaConnectionHandle& handle); - void SetPalmaBoostMode(bool boost_mode); - -private: - void ReadPalmaApplicationSection(); - void WritePalmaApplicationSection(); - void WritePalmaActivityEntry(); - void SuspendPalmaFeature(); - void ReadPalmaPlayLog(); - void ResetPalmaPlayLog(); - void SetIsPalmaPairedConnectable(); - void CancelWritePalmaWaveEntry(); - void EnablePalmaBoostMode(); - void GetPalmaBluetoothAddress(); - void SetDisallowedPalmaConnection(); - - bool is_connectable{}; - s32 database_id_version{}; - PalmaOperationInfo operation{}; - PalmaFrModeType fr_mode{}; - PalmaConnectionHandle active_handle{}; - - Core::HID::EmulatedController* controller; - - Kernel::KEvent* operation_complete_event; - KernelHelpers::ServiceContext& service_context; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include <cstring> -#include "common/common_types.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/frontend/emu_window.h" -#include "core/hid/emulated_console.h" -#include "core/hid/emulated_devices.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/seven_six_axis.h" -#include "core/memory.h" - -namespace Service::HID { -SevenSixAxis::SevenSixAxis(Core::System& system_) - : ControllerBase{system_.HIDCore()}, system{system_} { - console = hid_core.GetEmulatedConsole(); -} - -SevenSixAxis::~SevenSixAxis() = default; - -void SevenSixAxis::OnInit() {} -void SevenSixAxis::OnRelease() {} - -void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!IsControllerActivated() || transfer_memory == 0) { - seven_sixaxis_lifo.buffer_count = 0; - seven_sixaxis_lifo.buffer_tail = 0; - return; - } - - const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state; - next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1; - - const auto motion_status = console->GetMotion(); - last_global_timestamp = core_timing.GetGlobalTimeNs().count(); - - // This value increments every time the switch goes to sleep - next_seven_sixaxis_state.unknown = 1; - next_seven_sixaxis_state.timestamp = last_global_timestamp - last_saved_timestamp; - next_seven_sixaxis_state.accel = motion_status.accel; - next_seven_sixaxis_state.gyro = motion_status.gyro; - next_seven_sixaxis_state.quaternion = { - { - motion_status.quaternion.xyz.y, - motion_status.quaternion.xyz.x, - -motion_status.quaternion.w, - }, - -motion_status.quaternion.xyz.z, - }; - - seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); - system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, - sizeof(seven_sixaxis_lifo)); -} - -void SevenSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { - transfer_memory = t_mem; -} - -void SevenSixAxis::ResetTimestamp() { - last_saved_timestamp = last_global_timestamp; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "common/quaternion.h" -#include "common/typed_address.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" - -namespace Core { -class System; -} // namespace Core - -namespace Core::HID { -class EmulatedConsole; -} // namespace Core::HID - -namespace Service::HID { -class SevenSixAxis final : public ControllerBase { -public: - explicit SevenSixAxis(Core::System& system_); - ~SevenSixAxis() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - - // Called on InitializeSevenSixAxisSensor - void SetTransferMemoryAddress(Common::ProcessAddress t_mem); - - // Called on ResetSevenSixAxisSensorTimestamp - void ResetTimestamp(); - -private: - struct SevenSixAxisState { - INSERT_PADDING_WORDS(2); // unused - u64 timestamp{}; - u64 sampling_number{}; - u64 unknown{}; - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Quaternion<f32> quaternion{}; - }; - static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size"); - - Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{}; - static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); - - u64 last_saved_timestamp{}; - u64 last_global_timestamp{}; - - SevenSixAxisState next_seven_sixaxis_state{}; - Common::ProcessAddress transfer_memory{}; - Core::HID::EmulatedConsole* console = nullptr; - - Core::System& system; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/core.h" -#include "core/hle/kernel/k_shared_memory.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/shared_memory_holder.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" -#include "core/hle/service/hid/errors.h" - -namespace Service::HID { -SharedMemoryHolder::SharedMemoryHolder() {} - -SharedMemoryHolder::~SharedMemoryHolder() { - Finalize(); -} - -Result SharedMemoryHolder::Initialize(Core::System& system) { - shared_memory = Kernel::KSharedMemory::Create(system.Kernel()); - const Result result = shared_memory->Initialize( - system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, - Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); - if (result.IsError()) { - return result; - } - Kernel::KSharedMemory::Register(system.Kernel(), shared_memory); - - is_created = true; - is_mapped = true; - address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer())); - return ResultSuccess; -} - -void SharedMemoryHolder::Finalize() { - if (address != nullptr) { - shared_memory->Close(); - } - is_created = false; - is_mapped = false; - address = nullptr; -} - -bool SharedMemoryHolder::IsMapped() { - return is_mapped; -} - -SharedMemoryFormat* SharedMemoryHolder::GetAddress() { - return address; -} - -Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() { - return shared_memory; -} -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "core/hle/result.h" - -namespace Core { -class System; -} - -namespace Kernel { -class KSharedMemory; -} - -namespace Service::HID { -struct SharedMemoryFormat; - -// This is nn::hid::detail::SharedMemoryHolder -class SharedMemoryHolder { -public: - SharedMemoryHolder(); - ~SharedMemoryHolder(); - - Result Initialize(Core::System& system); - void Finalize(); - - bool IsMapped(); - SharedMemoryFormat* GetAddress(); - Kernel::KSharedMemory* GetHandle(); - -private: - bool is_owner{}; - bool is_created{}; - bool is_mapped{}; - INSERT_PADDING_BYTES(0x5); - Kernel::KSharedMemory* shared_memory; - INSERT_PADDING_BYTES(0x38); - SharedMemoryFormat* address = nullptr; -}; -// Correct size is 0x50 bytes -static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size"); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "common/common_types.h" -#include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/controllers/six_axis.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" -#include "core/hle/service/hid/errors.h" -#include "core/hle/service/hid/hid_util.h" - -namespace Service::HID { - -SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_) - : ControllerBase{hid_core_}, npad{npad_} { - for (std::size_t i = 0; i < controller_data.size(); ++i) { - auto& controller = controller_data[i]; - controller.device = hid_core.GetEmulatedControllerByIndex(i); - } -} - -SixAxis::~SixAxis() = default; - -void SixAxis::OnInit() {} -void SixAxis::OnRelease() {} - -void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - if (!IsControllerActivated()) { - return; - } - - for (std::size_t i = 0; i < controller_data.size(); ++i) { - NpadSharedMemoryEntry& shared_memory = data->shared_memory_format->npad.npad_entry[i]; - auto& controller = controller_data[i]; - const auto& controller_type = controller.device->GetNpadStyleIndex(); - - if (controller_type == Core::HID::NpadStyleIndex::None || - !controller.device->IsConnected()) { - continue; - } - - const auto& motion_state = controller.device->GetMotions(); - auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; - auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; - auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state; - auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state; - auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state; - auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state; - - auto& sixaxis_fullkey_lifo = shared_memory.internal_state.sixaxis_fullkey_lifo; - auto& sixaxis_handheld_lifo = shared_memory.internal_state.sixaxis_handheld_lifo; - auto& sixaxis_dual_left_lifo = shared_memory.internal_state.sixaxis_dual_left_lifo; - auto& sixaxis_dual_right_lifo = shared_memory.internal_state.sixaxis_dual_right_lifo; - auto& sixaxis_left_lifo = shared_memory.internal_state.sixaxis_left_lifo; - auto& sixaxis_right_lifo = shared_memory.internal_state.sixaxis_right_lifo; - - // Clear previous state - sixaxis_fullkey_state = {}; - sixaxis_handheld_state = {}; - sixaxis_dual_left_state = {}; - sixaxis_dual_right_state = {}; - sixaxis_left_lifo_state = {}; - sixaxis_right_lifo_state = {}; - - if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) { - controller.sixaxis_at_rest = true; - for (std::size_t e = 0; e < motion_state.size(); ++e) { - controller.sixaxis_at_rest = - controller.sixaxis_at_rest && motion_state[e].is_at_rest; - } - } - - const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state, - const Core::HID::ControllerMotion& hid_state) { - using namespace std::literals::chrono_literals; - static constexpr Core::HID::SixAxisSensorState default_motion_state = { - .delta_time = std::chrono::nanoseconds(5ms).count(), - .accel = {0, 0, -1.0f}, - .orientation = - { - Common::Vec3f{1.0f, 0, 0}, - Common::Vec3f{0, 1.0f, 0}, - Common::Vec3f{0, 0, 1.0f}, - }, - .attribute = {1}, - }; - if (!controller.sixaxis_sensor_enabled) { - state = default_motion_state; - return; - } - if (!Settings::values.motion_enabled.GetValue()) { - state = default_motion_state; - return; - } - state.attribute.is_connected.Assign(1); - state.delta_time = std::chrono::nanoseconds(5ms).count(); - state.accel = hid_state.accel; - state.gyro = hid_state.gyro; - state.rotation = hid_state.rotation; - state.orientation = hid_state.orientation; - }; - - switch (controller_type) { - case Core::HID::NpadStyleIndex::None: - ASSERT(false); - break; - case Core::HID::NpadStyleIndex::ProController: - set_motion_state(sixaxis_fullkey_state, motion_state[0]); - break; - case Core::HID::NpadStyleIndex::Handheld: - set_motion_state(sixaxis_handheld_state, motion_state[0]); - break; - case Core::HID::NpadStyleIndex::JoyconDual: - set_motion_state(sixaxis_dual_left_state, motion_state[0]); - set_motion_state(sixaxis_dual_right_state, motion_state[1]); - break; - case Core::HID::NpadStyleIndex::JoyconLeft: - set_motion_state(sixaxis_left_lifo_state, motion_state[0]); - break; - case Core::HID::NpadStyleIndex::JoyconRight: - set_motion_state(sixaxis_right_lifo_state, motion_state[1]); - break; - case Core::HID::NpadStyleIndex::Pokeball: - using namespace std::literals::chrono_literals; - set_motion_state(sixaxis_fullkey_state, motion_state[0]); - sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count(); - break; - default: - break; - } - - sixaxis_fullkey_state.sampling_number = - sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; - sixaxis_handheld_state.sampling_number = - sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; - sixaxis_dual_left_state.sampling_number = - sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; - sixaxis_dual_right_state.sampling_number = - sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; - sixaxis_left_lifo_state.sampling_number = - sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; - sixaxis_right_lifo_state.sampling_number = - sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1; - - if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { - // This buffer only is updated on handheld on HW - sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state); - } else { - // Handheld doesn't update this buffer on HW - sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state); - } - - sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state); - sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state); - sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state); - sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state); - } -} - -Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::GyroscopeZeroDriftMode drift_mode) { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - auto& sixaxis = GetSixaxisState(sixaxis_handle); - auto& controller = GetControllerFromHandle(sixaxis_handle); - sixaxis.gyroscope_zero_drift_mode = drift_mode; - controller.device->SetGyroscopeZeroDriftMode(drift_mode); - - return ResultSuccess; -} - -Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::GyroscopeZeroDriftMode& drift_mode) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - const auto& sixaxis = GetSixaxisState(sixaxis_handle); - drift_mode = sixaxis.gyroscope_zero_drift_mode; - - return ResultSuccess; -} - -Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool& is_at_rest) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - const auto& controller = GetControllerFromHandle(sixaxis_handle); - is_at_rest = controller.sixaxis_at_rest; - return ResultSuccess; -} - -Result SixAxis::LoadSixAxisSensorCalibrationParameter( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorCalibrationParameter& calibration) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - // TODO: Request this data to the controller. On error return 0xd8ca - const auto& sixaxis = GetSixaxisState(sixaxis_handle); - calibration = sixaxis.calibration; - return ResultSuccess; -} - -Result SixAxis::GetSixAxisSensorIcInformation( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorIcInformation& ic_information) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - // TODO: Request this data to the controller. On error return 0xd8ca - const auto& sixaxis = GetSixaxisState(sixaxis_handle); - ic_information = sixaxis.ic_information; - return ResultSuccess; -} - -Result SixAxis::EnableSixAxisSensorUnalteredPassthrough( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - auto& sixaxis = GetSixaxisState(sixaxis_handle); - sixaxis.unaltered_passtrough = is_enabled; - return ResultSuccess; -} - -Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - const auto& sixaxis = GetSixaxisState(sixaxis_handle); - is_enabled = sixaxis.unaltered_passtrough; - return ResultSuccess; -} - -Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool sixaxis_status) { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - auto& controller = GetControllerFromHandle(sixaxis_handle); - controller.sixaxis_sensor_enabled = sixaxis_status; - return ResultSuccess; -} - -Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool& is_fusion_enabled) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - const auto& sixaxis = GetSixaxisState(sixaxis_handle); - is_fusion_enabled = sixaxis.is_fusion_enabled; - - return ResultSuccess; -} -Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool is_fusion_enabled) { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - auto& sixaxis = GetSixaxisState(sixaxis_handle); - sixaxis.is_fusion_enabled = is_fusion_enabled; - - return ResultSuccess; -} - -Result SixAxis::SetSixAxisFusionParameters( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - const auto param1 = sixaxis_fusion_parameters.parameter1; - if (param1 < 0.0f || param1 > 1.0f) { - return InvalidSixAxisFusionRange; - } - - auto& sixaxis = GetSixaxisState(sixaxis_handle); - sixaxis.fusion = sixaxis_fusion_parameters; - - return ResultSuccess; -} - -Result SixAxis::GetSixAxisFusionParameters( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorFusionParameters& parameters) const { - const auto is_valid = IsSixaxisHandleValid(sixaxis_handle); - if (is_valid.IsError()) { - LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); - return is_valid; - } - - const auto& sixaxis = GetSixaxisState(sixaxis_handle); - parameters = sixaxis.fusion; - - return ResultSuccess; -} - -SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( - const Core::HID::SixAxisSensorHandle& sixaxis_handle) { - auto& controller = GetControllerFromHandle(sixaxis_handle); - switch (sixaxis_handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Pokeball: - return controller.sixaxis_fullkey; - case Core::HID::NpadStyleIndex::Handheld: - return controller.sixaxis_handheld; - case Core::HID::NpadStyleIndex::JoyconDual: - if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { - return controller.sixaxis_dual_left; - } - return controller.sixaxis_dual_right; - case Core::HID::NpadStyleIndex::JoyconLeft: - return controller.sixaxis_left; - case Core::HID::NpadStyleIndex::JoyconRight: - return controller.sixaxis_right; - default: - return controller.sixaxis_unknown; - } -} - -const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState( - const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { - const auto& controller = GetControllerFromHandle(sixaxis_handle); - switch (sixaxis_handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Pokeball: - return controller.sixaxis_fullkey; - case Core::HID::NpadStyleIndex::Handheld: - return controller.sixaxis_handheld; - case Core::HID::NpadStyleIndex::JoyconDual: - if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) { - return controller.sixaxis_dual_left; - } - return controller.sixaxis_dual_right; - case Core::HID::NpadStyleIndex::JoyconLeft: - return controller.sixaxis_left; - case Core::HID::NpadStyleIndex::JoyconRight: - return controller.sixaxis_right; - default: - return controller.sixaxis_unknown; - } -} - -SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle) { - const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); - return GetControllerFromNpadIdType(npad_id); -} - -const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle) const { - const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); - return GetControllerFromNpadIdType(npad_id); -} - -SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - npad_id = Core::HID::NpadIdType::Player1; - } - const auto npad_index = NpadIdTypeToIndex(npad_id); - return controller_data[npad_index]; -} - -const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType( - Core::HID::NpadIdType npad_id) const { - if (!IsNpadIdValid(npad_id)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); - npad_id = Core::HID::NpadIdType::Player1; - } - const auto npad_index = NpadIdTypeToIndex(npad_id); - return controller_data[npad_index]; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hid/hid_types.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/ring_lifo.h" - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::HID { -class NPad; - -class SixAxis final : public ControllerBase { -public: - explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_); - ~SixAxis() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - - Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::GyroscopeZeroDriftMode drift_mode); - Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::GyroscopeZeroDriftMode& drift_mode) const; - Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool& is_at_rest) const; - Result EnableSixAxisSensorUnalteredPassthrough( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled); - Result IsSixAxisSensorUnalteredPassthroughEnabled( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const; - Result LoadSixAxisSensorCalibrationParameter( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorCalibrationParameter& calibration) const; - Result GetSixAxisSensorIcInformation( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorIcInformation& ic_information) const; - Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool sixaxis_status); - Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool& is_fusion_enabled) const; - Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - bool is_fusion_enabled); - Result SetSixAxisFusionParameters( - const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); - Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle, - Core::HID::SixAxisSensorFusionParameters& parameters) const; - -private: - static constexpr std::size_t NPAD_COUNT = 10; - - struct SixaxisParameters { - bool is_fusion_enabled{true}; - bool unaltered_passtrough{false}; - Core::HID::SixAxisSensorFusionParameters fusion{}; - Core::HID::SixAxisSensorCalibrationParameter calibration{}; - Core::HID::SixAxisSensorIcInformation ic_information{}; - Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{ - Core::HID::GyroscopeZeroDriftMode::Standard}; - }; - - struct NpadControllerData { - Core::HID::EmulatedController* device = nullptr; - - // Motion parameters - bool sixaxis_at_rest{true}; - bool sixaxis_sensor_enabled{true}; - SixaxisParameters sixaxis_fullkey{}; - SixaxisParameters sixaxis_handheld{}; - SixaxisParameters sixaxis_dual_left{}; - SixaxisParameters sixaxis_dual_right{}; - SixaxisParameters sixaxis_left{}; - SixaxisParameters sixaxis_right{}; - SixaxisParameters sixaxis_unknown{}; - - // Current pad state - Core::HID::SixAxisSensorState sixaxis_fullkey_state{}; - Core::HID::SixAxisSensorState sixaxis_handheld_state{}; - Core::HID::SixAxisSensorState sixaxis_dual_left_state{}; - Core::HID::SixAxisSensorState sixaxis_dual_right_state{}; - Core::HID::SixAxisSensorState sixaxis_left_lifo_state{}; - Core::HID::SixAxisSensorState sixaxis_right_lifo_state{}; - int callback_key{}; - }; - - SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle); - const SixaxisParameters& GetSixaxisState( - const Core::HID::SixAxisSensorHandle& device_handle) const; - - NpadControllerData& GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle); - const NpadControllerData& GetControllerFromHandle( - const Core::HID::SixAxisSensorHandle& device_handle) const; - NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); - const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; - - std::shared_ptr<NPad> npad; - std::array<NpadControllerData, NPAD_COUNT> controller_data{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/sleep_button.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -SleepButton::SleepButton(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} - -SleepButton::~SleepButton() = default; - -void SleepButton::OnInit() {} - -void SleepButton::OnRelease() {} - -void SleepButton::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - - std::scoped_lock shared_lock{*shared_mutex}; - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - auto& header = data->shared_memory_format->capture_button.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Service::HID { - -class SleepButton final : public ControllerBase { -public: - explicit SleepButton(Core::HID::HIDCore& hid_core_); - ~SleepButton() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - bool smart_update{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include "common/common_types.h" -#include "common/settings.h" -#include "core/core_timing.h" -#include "core/frontend/emu_window.h" -#include "core/hid/emulated_console.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/touchscreen.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" - -namespace Service::HID { - -TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_) - : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width), - touchscreen_height(Layout::ScreenUndocked::Height) { - console = hid_core.GetEmulatedConsole(); -} - -TouchScreen::~TouchScreen() = default; - -void TouchScreen::OnInit() {} - -void TouchScreen::OnRelease() {} - -void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - TouchScreenSharedMemoryFormat& shared_memory = data->shared_memory_format->touch_screen; - shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); - - if (!IsControllerActivated()) { - shared_memory.touch_screen_lifo.buffer_count = 0; - shared_memory.touch_screen_lifo.buffer_tail = 0; - return; - } - - const auto touch_status = console->GetTouch(); - for (std::size_t id = 0; id < MAX_FINGERS; id++) { - const auto& current_touch = touch_status[id]; - auto& finger = fingers[id]; - finger.id = current_touch.id; - - if (finger.attribute.start_touch) { - finger.attribute.raw = 0; - continue; - } - - if (finger.attribute.end_touch) { - finger.attribute.raw = 0; - finger.pressed = false; - continue; - } - - if (!finger.pressed && current_touch.pressed) { - // Ignore all touch fingers if disabled - if (!Settings::values.touchscreen.enabled) { - continue; - } - - finger.attribute.start_touch.Assign(1); - finger.pressed = true; - finger.position = current_touch.position; - continue; - } - - if (finger.pressed && !current_touch.pressed) { - finger.attribute.raw = 0; - finger.attribute.end_touch.Assign(1); - continue; - } - - // Only update position if touch is not on a special frame - finger.position = current_touch.position; - } - - std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers; - const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), - [](const auto& finger) { return finger.pressed; }); - const auto active_fingers_count = - static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); - - const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count()); - const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state; - - next_state.sampling_number = last_entry.sampling_number + 1; - next_state.entry_count = static_cast<s32>(active_fingers_count); - - for (std::size_t id = 0; id < MAX_FINGERS; ++id) { - auto& touch_entry = next_state.states[id]; - if (id < active_fingers_count) { - const auto& [active_x, active_y] = active_fingers[id].position; - touch_entry.position = { - .x = static_cast<u16>(active_x * static_cast<float>(touchscreen_width)), - .y = static_cast<u16>(active_y * static_cast<float>(touchscreen_height)), - }; - touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; - touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; - touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; - touch_entry.delta_time = timestamp - active_fingers[id].last_touch; - fingers[active_fingers[id].id].last_touch = timestamp; - touch_entry.finger = active_fingers[id].id; - touch_entry.attribute.raw = active_fingers[id].attribute.raw; - } else { - // Clear touch entry - touch_entry.attribute.raw = 0; - touch_entry.position = {}; - touch_entry.diameter_x = 0; - touch_entry.diameter_y = 0; - touch_entry.rotation_angle = 0; - touch_entry.delta_time = 0; - touch_entry.finger = 0; - } - } - - shared_memory.touch_screen_lifo.WriteNextEntry(next_state); -} - -void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) { - touchscreen_width = width; - touchscreen_height = height; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> - -#include "core/hid/hid_types.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/controllers/types/touch_types.h" - -namespace Core::HID { -class EmulatedConsole; -} // namespace Core::HID - -namespace Service::HID { -struct TouchScreenSharedMemoryFormat; - -class TouchScreen final : public ControllerBase { -public: - explicit TouchScreen(Core::HID::HIDCore& hid_core_); - ~TouchScreen() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - - void SetTouchscreenDimensions(u32 width, u32 height); - -private: - TouchScreenState next_state{}; - Core::HID::EmulatedConsole* console = nullptr; - - std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{}; - u32 touchscreen_width; - u32 touchscreen_height; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/bit_field.h" -#include "common/common_types.h" -#include "core/hid/hid_types.h" - -namespace Service::HID { - -// This is nn::hid::DebugPadAttribute -struct DebugPadAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> connected; - }; -}; -static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size"); - -// This is nn::hid::DebugPadState -struct DebugPadState { - s64 sampling_number{}; - DebugPadAttribute attribute{}; - Core::HID::DebugPadButton pad_state{}; - Core::HID::AnalogStickState r_stick{}; - Core::HID::AnalogStickState l_stick{}; -}; -static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <array> -#include "common/bit_field.h" -#include "common/common_types.h" -#include "common/point.h" - -namespace Service::HID { -static constexpr size_t MAX_FINGERS = 16; -static constexpr size_t MAX_POINTS = 4; - -// This is nn::hid::GestureType -enum class GestureType : u32 { - Idle, // Nothing touching the screen - Complete, // Set at the end of a touch event - Cancel, // Set when the number of fingers change - Touch, // A finger just touched the screen - Press, // Set if last type is touch and the finger hasn't moved - Tap, // Fast press then release - Pan, // All points moving together across the screen - Swipe, // Fast press movement and release of a single point - Pinch, // All points moving away/closer to the midpoint - Rotate, // All points rotating from the midpoint -}; - -// This is nn::hid::GestureDirection -enum class GestureDirection : u32 { - None, - Left, - Up, - Right, - Down, -}; - -// This is nn::hid::GestureAttribute -struct GestureAttribute { - union { - u32 raw{}; - - BitField<4, 1, u32> is_new_touch; - BitField<8, 1, u32> is_double_tap; - }; -}; -static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); - -// This is nn::hid::GestureState -struct GestureState { - s64 sampling_number{}; - s64 detection_count{}; - GestureType type{GestureType::Idle}; - GestureDirection direction{GestureDirection::None}; - Common::Point<s32> pos{}; - Common::Point<s32> delta{}; - f32 vel_x{}; - f32 vel_y{}; - GestureAttribute attributes{}; - f32 scale{}; - f32 rotation_angle{}; - s32 point_count{}; - std::array<Common::Point<s32>, 4> points{}; -}; -static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); - -struct GestureProperties { - std::array<Common::Point<s32>, MAX_POINTS> points{}; - std::size_t active_points{}; - Common::Point<s32> mid_point{}; - s64 detection_count{}; - u64 delta_time{}; - f32 average_distance{}; - f32 angle{}; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hid/hid_types.h" - -namespace Service::HID { - -// This is nn::hid::detail::KeyboardState -struct KeyboardState { - s64 sampling_number{}; - Core::HID::KeyboardModifier modifier{}; - Core::HID::KeyboardAttribute attribute{}; - Core::HID::KeyboardKey key{}; -}; -static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" - -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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/bit_field.h" -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "core/hid/hid_types.h" - -namespace Service::HID { -static constexpr std::size_t MaxSupportedNpadIdTypes = 10; -static constexpr std::size_t StyleIndexCount = 7; - -// This is nn::hid::NpadJoyHoldType -enum class NpadJoyHoldType : u64 { - Vertical = 0, - Horizontal = 1, -}; - -// This is nn::hid::NpadJoyAssignmentMode -enum class NpadJoyAssignmentMode : u32 { - Dual = 0, - Single = 1, -}; - -// This is nn::hid::NpadJoyDeviceType -enum class NpadJoyDeviceType : s64 { - Left = 0, - Right = 1, -}; - -// This is nn::hid::NpadHandheldActivationMode -enum class NpadHandheldActivationMode : u64 { - Dual = 0, - Single = 1, - None = 2, - MaxActivationMode = 3, -}; - -// This is nn::hid::system::AppletFooterUiAttributesSet -struct AppletFooterUiAttributes { - INSERT_PADDING_BYTES(0x4); -}; - -// This is nn::hid::system::AppletFooterUiType -enum class AppletFooterUiType : u8 { - None = 0, - HandheldNone = 1, - HandheldJoyConLeftOnly = 2, - HandheldJoyConRightOnly = 3, - HandheldJoyConLeftJoyConRight = 4, - JoyDual = 5, - JoyDualLeftOnly = 6, - JoyDualRightOnly = 7, - JoyLeftHorizontal = 8, - JoyLeftVertical = 9, - JoyRightHorizontal = 10, - JoyRightVertical = 11, - SwitchProController = 12, - CompatibleProController = 13, - CompatibleJoyCon = 14, - LarkHvc1 = 15, - LarkHvc2 = 16, - LarkNesLeft = 17, - LarkNesRight = 18, - Lucia = 19, - Verification = 20, - Lagon = 21, -}; - -using AppletFooterUiVariant = u8; - -// This is "nn::hid::system::AppletDetailedUiType". -struct AppletDetailedUiType { - AppletFooterUiVariant ui_variant; - INSERT_PADDING_BYTES(0x2); - AppletFooterUiType footer; -}; -static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size"); -// This is nn::hid::NpadCommunicationMode -enum class NpadCommunicationMode : u64 { - Mode_5ms = 0, - Mode_10ms = 1, - Mode_15ms = 2, - Default = 3, -}; - -enum class NpadRevision : u32 { - Revision0 = 0, - Revision1 = 1, - Revision2 = 2, - Revision3 = 3, -}; - -// This is nn::hid::detail::ColorAttribute -enum class ColorAttribute : u32 { - Ok = 0, - ReadError = 1, - NoController = 2, -}; -static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size"); - -// This is nn::hid::detail::NpadFullKeyColorState -struct NpadFullKeyColorState { - ColorAttribute attribute{ColorAttribute::NoController}; - Core::HID::NpadControllerColor fullkey{}; -}; -static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size"); - -// This is nn::hid::detail::NpadJoyColorState -struct NpadJoyColorState { - ColorAttribute attribute{ColorAttribute::NoController}; - Core::HID::NpadControllerColor left{}; - Core::HID::NpadControllerColor right{}; -}; -static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size"); - -// This is nn::hid::NpadAttribute -struct NpadAttribute { - union { - u32 raw{}; - BitField<0, 1, u32> is_connected; - BitField<1, 1, u32> is_wired; - BitField<2, 1, u32> is_left_connected; - BitField<3, 1, u32> is_left_wired; - BitField<4, 1, u32> is_right_connected; - BitField<5, 1, u32> is_right_wired; - }; -}; -static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size"); - -// This is nn::hid::NpadFullKeyState -// This is nn::hid::NpadHandheldState -// This is nn::hid::NpadJoyDualState -// This is nn::hid::NpadJoyLeftState -// This is nn::hid::NpadJoyRightState -// This is nn::hid::NpadPalmaState -// This is nn::hid::NpadSystemExtState -struct NPadGenericState { - s64_le sampling_number{}; - Core::HID::NpadButtonState npad_buttons{}; - Core::HID::AnalogStickState l_stick{}; - Core::HID::AnalogStickState r_stick{}; - NpadAttribute connection_status{}; - INSERT_PADDING_BYTES(4); // Reserved -}; -static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); - -// This is nn::hid::server::NpadGcTriggerState -struct NpadGcTriggerState { - s64 sampling_number{}; - s32 l_analog{}; - s32 r_analog{}; -}; -static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); - -// This is nn::hid::NpadSystemProperties -struct NPadSystemProperties { - union { - s64 raw{}; - BitField<0, 1, s64> is_charging_joy_dual; - BitField<1, 1, s64> is_charging_joy_left; - BitField<2, 1, s64> is_charging_joy_right; - BitField<3, 1, s64> is_powered_joy_dual; - BitField<4, 1, s64> is_powered_joy_left; - BitField<5, 1, s64> is_powered_joy_right; - BitField<9, 1, s64> is_system_unsupported_button; - BitField<10, 1, s64> is_system_ext_unsupported_button; - BitField<11, 1, s64> is_vertical; - BitField<12, 1, s64> is_horizontal; - BitField<13, 1, s64> use_plus; - BitField<14, 1, s64> use_minus; - BitField<15, 1, s64> use_directional_buttons; - }; -}; -static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size"); - -// This is nn::hid::NpadSystemButtonProperties -struct NpadSystemButtonProperties { - union { - s32 raw{}; - BitField<0, 1, s32> is_home_button_protection_enabled; - }; -}; -static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size"); - -// This is nn::hid::system::DeviceType -struct DeviceType { - union { - u32 raw{}; - BitField<0, 1, s32> fullkey; - BitField<1, 1, s32> debug_pad; - BitField<2, 1, s32> handheld_left; - BitField<3, 1, s32> handheld_right; - BitField<4, 1, s32> joycon_left; - BitField<5, 1, s32> joycon_right; - BitField<6, 1, s32> palma; - BitField<7, 1, s32> lark_hvc_left; - BitField<8, 1, s32> lark_hvc_right; - BitField<9, 1, s32> lark_nes_left; - BitField<10, 1, s32> lark_nes_right; - BitField<11, 1, s32> handheld_lark_hvc_left; - BitField<12, 1, s32> handheld_lark_hvc_right; - BitField<13, 1, s32> handheld_lark_nes_left; - BitField<14, 1, s32> handheld_lark_nes_right; - BitField<15, 1, s32> lucia; - BitField<16, 1, s32> lagon; - BitField<17, 1, s32> lager; - BitField<31, 1, s32> system; - }; -}; - -// This is nn::hid::detail::NfcXcdDeviceHandleStateImpl -struct NfcXcdDeviceHandleStateImpl { - u64 handle{}; - bool is_available{}; - bool is_activated{}; - INSERT_PADDING_BYTES(0x6); // Reserved - u64 sampling_number{}; -}; -static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, - "NfcXcdDeviceHandleStateImpl is an invalid size"); - -// This is nn::hid::NpadLarkType -enum class NpadLarkType : u32 { - Invalid, - H1, - H2, - NL, - NR, -}; - -// This is nn::hid::NpadLuciaType -enum class NpadLuciaType : u32 { - Invalid, - J, - E, - U, -}; - -// This is nn::hid::NpadLagonType -enum class NpadLagonType : u32 { - Invalid, -}; - -// This is nn::hid::NpadLagerType -enum class NpadLagerType : u32 { - Invalid, - J, - E, - U, -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/vector_math.h" -#include "core/hid/hid_types.h" -#include "core/hle/service/hid//controllers/types/debug_pad_types.h" -#include "core/hle/service/hid//controllers/types/keyboard_types.h" -#include "core/hle/service/hid//controllers/types/mouse_types.h" -#include "core/hle/service/hid//controllers/types/npad_types.h" -#include "core/hle/service/hid//controllers/types/touch_types.h" -#include "core/hle/service/hid/ring_lifo.h" - -namespace Service::HID { -static const std::size_t HidEntryCount = 17; - -struct CommonHeader { - s64 timestamp{}; - s64 total_entry_count{}; - s64 last_entry_index{}; - s64 entry_count{}; -}; -static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); - -// This is nn::hid::detail::DebugPadSharedMemoryFormat -struct DebugPadSharedMemoryFormat { - // This is nn::hid::detail::DebugPadLifo - Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{}; - static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x4E); -}; -static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400, - "DebugPadSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::TouchScreenSharedMemoryFormat -struct TouchScreenSharedMemoryFormat { - // This is nn::hid::detail::TouchScreenLifo - Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{}; - static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); - INSERT_PADDING_WORDS(0xF2); -}; -static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000, - "TouchScreenSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::MouseSharedMemoryFormat -struct MouseSharedMemoryFormat { - // This is nn::hid::detail::MouseLifo - Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{}; - static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x2C); -}; -static_assert(sizeof(MouseSharedMemoryFormat) == 0x400, - "MouseSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::KeyboardSharedMemoryFormat -struct KeyboardSharedMemoryFormat { - // This is nn::hid::detail::KeyboardLifo - Lifo<KeyboardState, HidEntryCount> keyboard_lifo{}; - static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); - INSERT_PADDING_WORDS(0xA); -}; -static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400, - "KeyboardSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::DigitizerSharedMemoryFormat -struct DigitizerSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0xFE0); -}; -static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000, - "DigitizerSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::HomeButtonSharedMemoryFormat -struct HomeButtonSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x1E0); -}; -static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200, - "HomeButtonSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::SleepButtonSharedMemoryFormat -struct SleepButtonSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x1E0); -}; -static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200, - "SleepButtonSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::CaptureButtonSharedMemoryFormat -struct CaptureButtonSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x1E0); -}; -static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200, - "CaptureButtonSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::InputDetectorSharedMemoryFormat -struct InputDetectorSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x7E0); -}; -static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800, - "InputDetectorSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::UniquePadSharedMemoryFormat -struct UniquePadSharedMemoryFormat { - CommonHeader header; - INSERT_PADDING_BYTES(0x3FE0); -}; -static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000, - "UniquePadSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::NpadSixAxisSensorLifo -struct NpadSixAxisSensorLifo { - Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo; -}; - -// This is nn::hid::detail::NpadInternalState -struct NpadInternalState { - Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; - NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual}; - NpadFullKeyColorState fullkey_color{}; - NpadJoyColorState joycon_color{}; - Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{}; - Lifo<NPadGenericState, HidEntryCount> handheld_lifo{}; - Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{}; - Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{}; - Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{}; - Lifo<NPadGenericState, HidEntryCount> palma_lifo{}; - Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{}; - NpadSixAxisSensorLifo sixaxis_fullkey_lifo{}; - NpadSixAxisSensorLifo sixaxis_handheld_lifo{}; - NpadSixAxisSensorLifo sixaxis_dual_left_lifo{}; - NpadSixAxisSensorLifo sixaxis_dual_right_lifo{}; - NpadSixAxisSensorLifo sixaxis_left_lifo{}; - NpadSixAxisSensorLifo sixaxis_right_lifo{}; - DeviceType device_type{}; - INSERT_PADDING_BYTES(0x4); // Reserved - NPadSystemProperties system_properties{}; - NpadSystemButtonProperties button_properties{}; - Core::HID::NpadBatteryLevel battery_level_dual{}; - Core::HID::NpadBatteryLevel battery_level_left{}; - Core::HID::NpadBatteryLevel battery_level_right{}; - AppletFooterUiAttributes applet_footer_attributes{}; - AppletFooterUiType applet_footer_type{AppletFooterUiType::None}; - INSERT_PADDING_BYTES(0x5B); // Reserved - INSERT_PADDING_BYTES(0x20); // Unknown - Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{}; - NpadLarkType lark_type_l_and_main{}; - NpadLarkType lark_type_r{}; - NpadLuciaType lucia_type{}; - NpadLagerType lager_type{}; - Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties; - Core::HID::SixAxisSensorProperties sixaxis_handheld_properties; - Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties; - Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties; - Core::HID::SixAxisSensorProperties sixaxis_left_properties; - Core::HID::SixAxisSensorProperties sixaxis_right_properties; -}; -static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size"); - -// This is nn::hid::detail::NpadSharedMemoryEntry -struct NpadSharedMemoryEntry { - NpadInternalState internal_state; - INSERT_PADDING_BYTES(0xC08); -}; -static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size"); - -// This is nn::hid::detail::NpadSharedMemoryFormat -struct NpadSharedMemoryFormat { - std::array<NpadSharedMemoryEntry, MaxSupportedNpadIdTypes> npad_entry; -}; -static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000, - "NpadSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::GestureSharedMemoryFormat -struct GestureSharedMemoryFormat { - // This is nn::hid::detail::GestureLifo - Lifo<GestureState, HidEntryCount> gesture_lifo{}; - static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x3E); -}; -static_assert(sizeof(GestureSharedMemoryFormat) == 0x800, - "GestureSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat -struct ConsoleSixAxisSensorSharedMemoryFormat { - u64 sampling_number{}; - bool is_seven_six_axis_sensor_at_rest{}; - INSERT_PADDING_BYTES(3); // padding - f32 verticalization_error{}; - Common::Vec3f gyro_bias{}; - INSERT_PADDING_BYTES(4); // padding -}; -static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20, - "ConsoleSixAxisSensorSharedMemoryFormat is an invalid size"); - -// This is nn::hid::detail::SharedMemoryFormat -struct SharedMemoryFormat { - void Initialize() {} - - DebugPadSharedMemoryFormat debug_pad; - TouchScreenSharedMemoryFormat touch_screen; - MouseSharedMemoryFormat mouse; - KeyboardSharedMemoryFormat keyboard; - DigitizerSharedMemoryFormat digitizer; - HomeButtonSharedMemoryFormat home_button; - SleepButtonSharedMemoryFormat sleep_button; - CaptureButtonSharedMemoryFormat capture_button; - InputDetectorSharedMemoryFormat input_detector; - UniquePadSharedMemoryFormat unique_pad; - NpadSharedMemoryFormat npad; - GestureSharedMemoryFormat gesture; - ConsoleSixAxisSensorSharedMemoryFormat console; - INSERT_PADDING_BYTES(0x19E0); - MouseSharedMemoryFormat debug_mouse; - INSERT_PADDING_BYTES(0x2000); -}; -static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00, - "sleep_button has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000, - "capture_button has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200, - "input_detector has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset"); -static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset"); -static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size"); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <array> - -#include <array> -#include "common/bit_field.h" -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/point.h" -#include "core/hid/hid_types.h" - -namespace Service::HID { -static constexpr std::size_t MAX_FINGERS = 16; -static constexpr size_t MAX_POINTS = 4; - -// This is nn::hid::GestureType -enum class GestureType : u32 { - Idle, // Nothing touching the screen - Complete, // Set at the end of a touch event - Cancel, // Set when the number of fingers change - Touch, // A finger just touched the screen - Press, // Set if last type is touch and the finger hasn't moved - Tap, // Fast press then release - Pan, // All points moving together across the screen - Swipe, // Fast press movement and release of a single point - Pinch, // All points moving away/closer to the midpoint - Rotate, // All points rotating from the midpoint -}; - -// This is nn::hid::GestureDirection -enum class GestureDirection : u32 { - None, - Left, - Up, - Right, - Down, -}; - -// This is nn::hid::GestureAttribute -struct GestureAttribute { - union { - u32 raw{}; - - BitField<4, 1, u32> is_new_touch; - BitField<8, 1, u32> is_double_tap; - }; -}; -static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size"); - -// This is nn::hid::GestureState -struct GestureState { - s64 sampling_number{}; - s64 detection_count{}; - GestureType type{GestureType::Idle}; - GestureDirection direction{GestureDirection::None}; - Common::Point<s32> pos{}; - Common::Point<s32> delta{}; - f32 vel_x{}; - f32 vel_y{}; - GestureAttribute attributes{}; - f32 scale{}; - f32 rotation_angle{}; - s32 point_count{}; - std::array<Common::Point<s32>, 4> points{}; -}; -static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); - -struct GestureProperties { - std::array<Common::Point<s32>, MAX_POINTS> points{}; - std::size_t active_points{}; - Common::Point<s32> mid_point{}; - s64 detection_count{}; - u64 delta_time{}; - f32 average_distance{}; - f32 angle{}; -}; - -// This is nn::hid::TouchScreenState -struct TouchScreenState { - s64 sampling_number{}; - s32 entry_count{}; - INSERT_PADDING_BYTES(4); // Reserved - std::array<Core::HID::TouchState, MAX_FINGERS> states{}; -}; -static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core_timing.h" -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" -#include "core/hle/service/hid/controllers/unique_pad.h" - -namespace Service::HID { - -UniquePad::UniquePad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} - -UniquePad::~UniquePad() = default; - -void UniquePad::OnInit() {} - -void UniquePad::OnRelease() {} - -void UniquePad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { - if (!smart_update) { - return; - } - - const u64 aruid = applet_resource->GetActiveAruid(); - auto* data = applet_resource->GetAruidData(aruid); - - if (data == nullptr || !data->flag.is_assigned) { - return; - } - - auto& header = data->shared_memory_format->capture_button.header; - header.timestamp = core_timing.GetGlobalTimeNs().count(); - header.total_entry_count = 17; - header.entry_count = 0; - header.last_entry_index = 0; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hid/controllers/controller_base.h" - -namespace Service::HID { - -class UniquePad final : public ControllerBase { -public: - explicit UniquePad(Core::HID::HIDCore& hid_core_); - ~UniquePad() override; - - // Called when the controller is initialized - void OnInit() override; - - // When the controller is released - void OnRelease() override; - - // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; - -private: - bool smart_update{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/result.h" - -namespace Service::HID { - -constexpr Result PalmaResultSuccess{ErrorModule::HID, 0}; -constexpr Result NpadInvalidHandle{ErrorModule::HID, 100}; -constexpr Result NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; - -constexpr Result ResultVibrationNotInitialized{ErrorModule::HID, 121}; -constexpr Result ResultVibrationInvalidStyleIndex{ErrorModule::HID, 122}; -constexpr Result ResultVibrationInvalidNpadId{ErrorModule::HID, 123}; -constexpr Result ResultVibrationDeviceIndexOutOfRange{ErrorModule::HID, 124}; -constexpr Result ResultVibrationStrenghtOutOfRange{ErrorModule::HID, 126}; -constexpr Result ResultVibrationArraySizeMismatch{ErrorModule::HID, 131}; - -constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423}; - -constexpr Result ResultNfcIsNotReady{ErrorModule::HID, 461}; -constexpr Result ResultNfcXcdHandleIsNotInitialized{ErrorModule::HID, 464}; -constexpr Result ResultIrSensorIsNotReady{ErrorModule::HID, 501}; -constexpr Result ResultMcuIsNotReady{ErrorModule::HID, 541}; - -constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601}; -constexpr Result NpadIsSameType{ErrorModule::HID, 602}; -constexpr Result ResultNpadIsNotProController{ErrorModule::HID, 604}; - -constexpr Result ResultInvalidNpadId{ErrorModule::HID, 709}; -constexpr Result ResultNpadNotConnected{ErrorModule::HID, 710}; -constexpr Result ResultNpadHandlerOverflow{ErrorModule::HID, 711}; -constexpr Result ResultNpadHandlerNotInitialized{ErrorModule::HID, 712}; -constexpr Result ResultInvalidArraySize{ErrorModule::HID, 715}; -constexpr Result ResultUndefinedStyleset{ErrorModule::HID, 716}; -constexpr Result ResultMultipleStyleSetSelected{ErrorModule::HID, 717}; - -constexpr Result ResultAppletResourceOverflow{ErrorModule::HID, 1041}; -constexpr Result ResultAppletResourceNotInitialized{ErrorModule::HID, 1042}; -constexpr Result ResultSharedMemoryNotInitialized{ErrorModule::HID, 1043}; -constexpr Result ResultAruidNoAvailableEntries{ErrorModule::HID, 1044}; -constexpr Result ResultAruidAlreadyRegistered{ErrorModule::HID, 1046}; -constexpr Result ResultAruidNotRegistered{ErrorModule::HID, 1047}; - -constexpr Result ResultNpadResourceOverflow{ErrorModule::HID, 2001}; -constexpr Result ResultNpadResourceNotInitialized{ErrorModule::HID, 2002}; - -constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302}; - -} // namespace Service::HID - -namespace Service::IRS { - -constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78}; -constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204}; - -} // 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 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/service/hid/hid.h" #include "core/hle/service/hid/hid_debug_server.h" -#include "core/hle/service/hid/hid_firmware_settings.h" #include "core/hle/service/hid/hid_server.h" #include "core/hle/service/hid/hid_system_server.h" #include "core/hle/service/hid/hidbus.h" #include "core/hle/service/hid/irs.h" -#include "core/hle/service/hid/resource_manager.h" #include "core/hle/service/hid/xcd.h" #include "core/hle/service/server_manager.h" +#include "hid_core/resource_manager.h" +#include "hid_core/resources/hid_firmware_settings.h" namespace Service::HID { 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 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "core/hle/service/hid/hid_debug_server.h" -#include "core/hle/service/hid/resource_manager.h" #include "core/hle/service/ipc_helpers.h" +#include "hid_core/resource_manager.h" namespace Service::HID { 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/hle/service/hid/hid_firmware_settings.h" - -namespace Service::HID { - -HidFirmwareSettings::HidFirmwareSettings() { - LoadSettings(true); -} - -void HidFirmwareSettings::Reload() { - LoadSettings(true); -} - -void HidFirmwareSettings::LoadSettings(bool reload_config) { - if (is_initalized && !reload_config) { - return; - } - - // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values - - is_debug_pad_enabled = true; - is_device_managed = true; - is_touch_i2c_managed = is_device_managed; - is_future_devices_emulated = false; - is_mcu_hardware_error_emulated = false; - is_rail_enabled = true; - is_firmware_update_failure_emulated = false; - is_firmware_update_failure = {}; - is_ble_disabled = false; - is_dscale_disabled = false; - is_handheld_forced = true; - features_per_id_disabled = {}; - is_touch_firmware_auto_update_disabled = false; - is_initalized = true; -} - -bool HidFirmwareSettings::IsDebugPadEnabled() { - LoadSettings(false); - return is_debug_pad_enabled; -} - -bool HidFirmwareSettings::IsDeviceManaged() { - LoadSettings(false); - return is_device_managed; -} - -bool HidFirmwareSettings::IsEmulateFutureDevice() { - LoadSettings(false); - return is_future_devices_emulated; -} - -bool HidFirmwareSettings::IsTouchI2cManaged() { - LoadSettings(false); - return is_touch_i2c_managed; -} - -bool HidFirmwareSettings::IsHandheldForced() { - LoadSettings(false); - return is_handheld_forced; -} - -bool HidFirmwareSettings::IsRailEnabled() { - LoadSettings(false); - return is_rail_enabled; -} - -bool HidFirmwareSettings::IsHardwareErrorEmulated() { - LoadSettings(false); - return is_mcu_hardware_error_emulated; -} - -bool HidFirmwareSettings::IsBleDisabled() { - LoadSettings(false); - return is_ble_disabled; -} - -bool HidFirmwareSettings::IsDscaleDisabled() { - LoadSettings(false); - return is_dscale_disabled; -} - -bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() { - LoadSettings(false); - return is_touch_firmware_auto_update_disabled; -} - -HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() { - LoadSettings(false); - return is_firmware_update_failure; -} - -HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() { - LoadSettings(false); - return features_per_id_disabled; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" - -namespace Service::HID { - -/// Loads firmware config from nn::settings::fwdbg -class HidFirmwareSettings { -public: - using FirmwareSetting = std::array<u8, 4>; - using FeaturesPerId = std::array<bool, 0xA8>; - - HidFirmwareSettings(); - - void Reload(); - void LoadSettings(bool reload_config); - - bool IsDebugPadEnabled(); - bool IsDeviceManaged(); - bool IsEmulateFutureDevice(); - bool IsTouchI2cManaged(); - bool IsHandheldForced(); - bool IsRailEnabled(); - bool IsHardwareErrorEmulated(); - bool IsBleDisabled(); - bool IsDscaleDisabled(); - bool IsTouchAutoUpdateDisabled(); - - FirmwareSetting GetFirmwareUpdateFailure(); - FeaturesPerId FeaturesDisabledPerId(); - -private: - bool is_initalized{}; - - // Debug settings - bool is_debug_pad_enabled{}; - bool is_device_managed{}; - bool is_touch_i2c_managed{}; - bool is_future_devices_emulated{}; - bool is_mcu_hardware_error_emulated{}; - bool is_rail_enabled{}; - bool is_firmware_update_failure_emulated{}; - bool is_ble_disabled{}; - bool is_dscale_disabled{}; - bool is_handheld_forced{}; - bool is_touch_firmware_auto_update_disabled{}; - FirmwareSetting is_firmware_update_failure{}; - FeaturesPerId features_per_id_disabled{}; -}; - -} // 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 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "common/settings.h" -#include "core/hid/hid_core.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/service/hid/errors.h" -#include "core/hle/service/hid/hid_firmware_settings.h" #include "core/hle/service/hid/hid_server.h" -#include "core/hle/service/hid/hid_util.h" -#include "core/hle/service/hid/resource_manager.h" #include "core/hle/service/ipc_helpers.h" #include "core/memory.h" - -#include "core/hle/service/hid/controllers/console_six_axis.h" -#include "core/hle/service/hid/controllers/controller_base.h" -#include "core/hle/service/hid/controllers/debug_pad.h" -#include "core/hle/service/hid/controllers/gesture.h" -#include "core/hle/service/hid/controllers/keyboard.h" -#include "core/hle/service/hid/controllers/mouse.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/controllers/palma.h" -#include "core/hle/service/hid/controllers/seven_six_axis.h" -#include "core/hle/service/hid/controllers/six_axis.h" -#include "core/hle/service/hid/controllers/touchscreen.h" -#include "core/hle/service/hid/controllers/types/npad_types.h" +#include "hid_core/hid_result.h" +#include "hid_core/hid_util.h" +#include "hid_core/resource_manager.h" +#include "hid_core/resources/hid_firmware_settings.h" + +#include "hid_core/resources/controller_base.h" +#include "hid_core/resources/debug_pad/debug_pad.h" +#include "hid_core/resources/keyboard/keyboard.h" +#include "hid_core/resources/mouse/mouse.h" +#include "hid_core/resources/npad/npad.h" +#include "hid_core/resources/npad/npad_types.h" +#include "hid_core/resources/palma/palma.h" +#include "hid_core/resources/six_axis/console_six_axis.h" +#include "hid_core/resources/six_axis/seven_six_axis.h" +#include "hid_core/resources/six_axis/six_axis.h" +#include "hid_core/resources/touch_screen/gesture.h" +#include "hid_core/resources/touch_screen/touch_screen.h" namespace Service::HID { 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 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/controllers/palma.h" -#include "core/hle/service/hid/controllers/touchscreen.h" -#include "core/hle/service/hid/controllers/types/npad_types.h" -#include "core/hle/service/hid/errors.h" #include "core/hle/service/hid/hid_system_server.h" -#include "core/hle/service/hid/resource_manager.h" #include "core/hle/service/ipc_helpers.h" +#include "hid_core/hid_result.h" +#include "hid_core/resource_manager.h" +#include "hid_core/resources/npad/npad.h" +#include "hid_core/resources/npad/npad_types.h" +#include "hid_core/resources/palma/palma.h" +#include "hid_core/resources/touch_screen/touch_screen.h" namespace Service::HID { @@ -270,7 +269,7 @@ void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushEnum(system.HIDCore().GetLastActiveController()); + rb.Push(0); // Dont forget to fix this } 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "core/hid/hid_types.h" -#include "core/hle/service/hid/errors.h" - -namespace Service::HID { - -constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) { - switch (npad_id) { - case Core::HID::NpadIdType::Player1: - case Core::HID::NpadIdType::Player2: - case Core::HID::NpadIdType::Player3: - case Core::HID::NpadIdType::Player4: - case Core::HID::NpadIdType::Player5: - case Core::HID::NpadIdType::Player6: - case Core::HID::NpadIdType::Player7: - case Core::HID::NpadIdType::Player8: - case Core::HID::NpadIdType::Other: - case Core::HID::NpadIdType::Handheld: - return true; - default: - return false; - } -} - -constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) { - const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id)); - const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex; - - if (!npad_id) { - return ResultInvalidNpadId; - } - if (!device_index) { - return NpadDeviceIndexOutOfRange; - } - - return ResultSuccess; -} - -constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) { - switch (handle.npad_type) { - case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::Handheld: - case Core::HID::NpadStyleIndex::JoyconDual: - case Core::HID::NpadStyleIndex::JoyconLeft: - case Core::HID::NpadStyleIndex::JoyconRight: - case Core::HID::NpadStyleIndex::GameCube: - case Core::HID::NpadStyleIndex::N64: - case Core::HID::NpadStyleIndex::SystemExt: - case Core::HID::NpadStyleIndex::System: - // These support vibration - break; - default: - return ResultVibrationInvalidStyleIndex; - } - - if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) { - return ResultVibrationInvalidNpadId; - } - - if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) { - return ResultVibrationDeviceIndexOutOfRange; - } - - return ResultSuccess; -} - -/// Converts a Core::HID::NpadIdType to an array index. -constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) { - switch (npad_id_type) { - case Core::HID::NpadIdType::Player1: - return 0; - case Core::HID::NpadIdType::Player2: - return 1; - case Core::HID::NpadIdType::Player3: - return 2; - case Core::HID::NpadIdType::Player4: - return 3; - case Core::HID::NpadIdType::Player5: - return 4; - case Core::HID::NpadIdType::Player6: - return 5; - case Core::HID::NpadIdType::Player7: - return 6; - case Core::HID::NpadIdType::Player8: - return 7; - case Core::HID::NpadIdType::Handheld: - return 8; - case Core::HID::NpadIdType::Other: - return 9; - default: - return 8; - } -} - -/// Converts an array index to a Core::HID::NpadIdType -constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) { - switch (index) { - case 0: - return Core::HID::NpadIdType::Player1; - case 1: - return Core::HID::NpadIdType::Player2; - case 2: - return Core::HID::NpadIdType::Player3; - case 3: - return Core::HID::NpadIdType::Player4; - case 4: - return Core::HID::NpadIdType::Player5; - case 5: - return Core::HID::NpadIdType::Player6; - case 6: - return Core::HID::NpadIdType::Player7; - case 7: - return Core::HID::NpadIdType::Player8; - case 8: - return Core::HID::NpadIdType::Handheld; - case 9: - return Core::HID::NpadIdType::Other; - default: - return Core::HID::NpadIdType::Invalid; - } -} - -constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) { - switch (index) { - case 0: - return Core::HID::NpadStyleSet::Fullkey; - case 1: - return Core::HID::NpadStyleSet::Handheld; - case 2: - return Core::HID::NpadStyleSet::JoyDual; - case 3: - return Core::HID::NpadStyleSet::JoyLeft; - case 4: - return Core::HID::NpadStyleSet::JoyRight; - case 5: - return Core::HID::NpadStyleSet::Palma; - default: - return Core::HID::NpadStyleSet::None; - } -} - -} // 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 @@ #include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/service/hid/hidbus.h" -#include "core/hle/service/hid/hidbus/ringcon.h" -#include "core/hle/service/hid/hidbus/starlink.h" -#include "core/hle/service/hid/hidbus/stubbed.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/service.h" #include "core/memory.h" +#include "hid_core/hid_types.h" +#include "hid_core/hidbus/ringcon.h" +#include "hid_core/hidbus/starlink.h" +#include "hid_core/hidbus/stubbed.h" namespace Service::HID { // (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 @@ #include <functional> -#include "core/hle/service/hid/hidbus/hidbus_base.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/service.h" +#include "hid_core/hidbus/hidbus_base.h" namespace Core::Timing { 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hid/hid_core.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/hid/hidbus/hidbus_base.h" -#include "core/hle/service/kernel_helpers.h" - -namespace Service::HID { - -HidbusBase::HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_) - : system(system_), service_context(service_context_) { - send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent"); -} - -HidbusBase::~HidbusBase() { - service_context.CloseEvent(send_command_async_event); -}; - -void HidbusBase::ActivateDevice() { - if (is_activated) { - return; - } - is_activated = true; - OnInit(); -} - -void HidbusBase::DeactivateDevice() { - if (is_activated) { - OnRelease(); - } - is_activated = false; -} - -bool HidbusBase::IsDeviceActivated() const { - return is_activated; -} - -void HidbusBase::Enable(bool enable) { - device_enabled = enable; -} - -bool HidbusBase::IsEnabled() const { - return device_enabled; -} - -bool HidbusBase::IsPollingMode() const { - return polling_mode_enabled; -} - -JoyPollingMode HidbusBase::GetPollingMode() const { - return polling_mode; -} - -void HidbusBase::SetPollingMode(JoyPollingMode mode) { - polling_mode = mode; - polling_mode_enabled = true; -} - -void HidbusBase::DisablePollingMode() { - polling_mode_enabled = false; -} - -void HidbusBase::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { - transfer_memory = t_mem; -} - -Kernel::KReadableEvent& HidbusBase::GetSendCommandAsycEvent() const { - return send_command_async_event->GetReadableEvent(); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <span> -#include "common/typed_address.h" -#include "core/hle/result.h" - -namespace Core { -class System; -} - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Service::KernelHelpers { -class ServiceContext; -} - -namespace Service::HID { - -// This is nn::hidbus::JoyPollingMode -enum class JoyPollingMode : u32 { - SixAxisSensorDisable, - SixAxisSensorEnable, - ButtonOnly, -}; - -struct DataAccessorHeader { - Result result{ResultUnknown}; - INSERT_PADDING_WORDS(0x1); - std::array<u8, 0x18> unused{}; - u64 latest_entry{}; - u64 total_entries{}; -}; -static_assert(sizeof(DataAccessorHeader) == 0x30, "DataAccessorHeader is an invalid size"); - -struct JoyDisableSixAxisPollingData { - std::array<u8, 0x26> data; - u8 out_size; - INSERT_PADDING_BYTES(0x1); - u64 sampling_number; -}; -static_assert(sizeof(JoyDisableSixAxisPollingData) == 0x30, - "JoyDisableSixAxisPollingData is an invalid size"); - -struct JoyEnableSixAxisPollingData { - std::array<u8, 0x8> data; - u8 out_size; - INSERT_PADDING_BYTES(0x7); - u64 sampling_number; -}; -static_assert(sizeof(JoyEnableSixAxisPollingData) == 0x18, - "JoyEnableSixAxisPollingData is an invalid size"); - -struct JoyButtonOnlyPollingData { - std::array<u8, 0x2c> data; - u8 out_size; - INSERT_PADDING_BYTES(0x3); - u64 sampling_number; -}; -static_assert(sizeof(JoyButtonOnlyPollingData) == 0x38, - "JoyButtonOnlyPollingData is an invalid size"); - -struct JoyDisableSixAxisPollingEntry { - u64 sampling_number; - JoyDisableSixAxisPollingData polling_data; -}; -static_assert(sizeof(JoyDisableSixAxisPollingEntry) == 0x38, - "JoyDisableSixAxisPollingEntry is an invalid size"); - -struct JoyEnableSixAxisPollingEntry { - u64 sampling_number; - JoyEnableSixAxisPollingData polling_data; -}; -static_assert(sizeof(JoyEnableSixAxisPollingEntry) == 0x20, - "JoyEnableSixAxisPollingEntry is an invalid size"); - -struct JoyButtonOnlyPollingEntry { - u64 sampling_number; - JoyButtonOnlyPollingData polling_data; -}; -static_assert(sizeof(JoyButtonOnlyPollingEntry) == 0x40, - "JoyButtonOnlyPollingEntry is an invalid size"); - -struct JoyDisableSixAxisDataAccessor { - DataAccessorHeader header{}; - std::array<JoyDisableSixAxisPollingEntry, 0xb> entries{}; -}; -static_assert(sizeof(JoyDisableSixAxisDataAccessor) == 0x298, - "JoyDisableSixAxisDataAccessor is an invalid size"); - -struct JoyEnableSixAxisDataAccessor { - DataAccessorHeader header{}; - std::array<JoyEnableSixAxisPollingEntry, 0xb> entries{}; -}; -static_assert(sizeof(JoyEnableSixAxisDataAccessor) == 0x190, - "JoyEnableSixAxisDataAccessor is an invalid size"); - -struct ButtonOnlyPollingDataAccessor { - DataAccessorHeader header; - std::array<JoyButtonOnlyPollingEntry, 0xb> entries; -}; -static_assert(sizeof(ButtonOnlyPollingDataAccessor) == 0x2F0, - "ButtonOnlyPollingDataAccessor is an invalid size"); - -class HidbusBase { -public: - explicit HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& service_context_); - virtual ~HidbusBase(); - - void ActivateDevice(); - - void DeactivateDevice(); - - bool IsDeviceActivated() const; - - // Enables/disables the device - void Enable(bool enable); - - // returns true if device is enabled - bool IsEnabled() const; - - // returns true if polling mode is enabled - bool IsPollingMode() const; - - // returns polling mode - JoyPollingMode GetPollingMode() const; - - // Sets and enables JoyPollingMode - void SetPollingMode(JoyPollingMode mode); - - // Disables JoyPollingMode - void DisablePollingMode(); - - // Called on EnableJoyPollingReceiveMode - void SetTransferMemoryAddress(Common::ProcessAddress t_mem); - - Kernel::KReadableEvent& GetSendCommandAsycEvent() const; - - virtual void OnInit() {} - - virtual void OnRelease() {} - - // Updates device transfer memory - virtual void OnUpdate() {} - - // Returns the device ID of the joycon - virtual u8 GetDeviceId() const { - return {}; - } - - // Assigns a command from data - virtual bool SetCommand(std::span<const u8> data) { - return {}; - } - - // Returns a reply from a command - virtual std::vector<u8> GetReply() const { - return {}; - } - -protected: - bool is_activated{}; - bool device_enabled{}; - bool polling_mode_enabled{}; - JoyPollingMode polling_mode = {}; - // TODO(German77): All data accessors need to be replaced with a ring lifo object - JoyDisableSixAxisDataAccessor disable_sixaxis_data{}; - JoyEnableSixAxisDataAccessor enable_sixaxis_data{}; - ButtonOnlyPollingDataAccessor button_only_data{}; - - Common::ProcessAddress transfer_memory{}; - - Core::System& system; - Kernel::KEvent* send_command_async_event; - KernelHelpers::ServiceContext& service_context; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/core.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/hid/hidbus/ringcon.h" -#include "core/memory.h" - -namespace Service::HID { - -RingController::RingController(Core::System& system_, - KernelHelpers::ServiceContext& service_context_) - : HidbusBase(system_, service_context_) { - input = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); -} - -RingController::~RingController() = default; - -void RingController::OnInit() { - input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Ring); - return; -} - -void RingController::OnRelease() { - input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Active); - return; -}; - -void RingController::OnUpdate() { - if (!is_activated) { - return; - } - - if (!device_enabled) { - return; - } - - if (!polling_mode_enabled || transfer_memory == 0) { - return; - } - - // TODO: Increment multitasking counters from motion and sensor data - - switch (polling_mode) { - case JoyPollingMode::SixAxisSensorEnable: { - enable_sixaxis_data.header.total_entries = 10; - enable_sixaxis_data.header.result = ResultSuccess; - const auto& last_entry = - enable_sixaxis_data.entries[enable_sixaxis_data.header.latest_entry]; - - enable_sixaxis_data.header.latest_entry = - (enable_sixaxis_data.header.latest_entry + 1) % 10; - auto& curr_entry = enable_sixaxis_data.entries[enable_sixaxis_data.header.latest_entry]; - - curr_entry.sampling_number = last_entry.sampling_number + 1; - curr_entry.polling_data.sampling_number = curr_entry.sampling_number; - - const RingConData ringcon_value = GetSensorValue(); - curr_entry.polling_data.out_size = sizeof(ringcon_value); - std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value)); - - system.ApplicationMemory().WriteBlock(transfer_memory, &enable_sixaxis_data, - sizeof(enable_sixaxis_data)); - break; - } - default: - LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); - break; - } -} - -RingController::RingConData RingController::GetSensorValue() const { - RingConData ringcon_sensor_value{ - .status = DataValid::Valid, - .data = 0, - }; - - const f32 force_value = input->GetRingSensorForce().force * range; - ringcon_sensor_value.data = static_cast<s16>(force_value) + idle_value; - - return ringcon_sensor_value; -} - -u8 RingController::GetDeviceId() const { - return device_id; -} - -std::vector<u8> RingController::GetReply() const { - const RingConCommands current_command = command; - - switch (current_command) { - case RingConCommands::GetFirmwareVersion: - return GetFirmwareVersionReply(); - case RingConCommands::ReadId: - return GetReadIdReply(); - case RingConCommands::c20105: - return GetC020105Reply(); - case RingConCommands::ReadUnkCal: - return GetReadUnkCalReply(); - case RingConCommands::ReadFactoryCal: - return GetReadFactoryCalReply(); - case RingConCommands::ReadUserCal: - return GetReadUserCalReply(); - case RingConCommands::ReadRepCount: - return GetReadRepCountReply(); - case RingConCommands::ReadTotalPushCount: - return GetReadTotalPushCountReply(); - case RingConCommands::ResetRepCount: - return GetResetRepCountReply(); - case RingConCommands::SaveCalData: - return GetSaveDataReply(); - default: - return GetErrorReply(); - } -} - -bool RingController::SetCommand(std::span<const u8> data) { - if (data.size() < 4) { - LOG_ERROR(Service_HID, "Command size not supported {}", data.size()); - command = RingConCommands::Error; - return false; - } - - std::memcpy(&command, data.data(), sizeof(RingConCommands)); - - switch (command) { - case RingConCommands::GetFirmwareVersion: - case RingConCommands::ReadId: - case RingConCommands::c20105: - case RingConCommands::ReadUnkCal: - case RingConCommands::ReadFactoryCal: - case RingConCommands::ReadUserCal: - case RingConCommands::ReadRepCount: - case RingConCommands::ReadTotalPushCount: - ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); - send_command_async_event->Signal(); - return true; - case RingConCommands::ResetRepCount: - ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); - total_rep_count = 0; - send_command_async_event->Signal(); - return true; - case RingConCommands::SaveCalData: { - ASSERT_MSG(data.size() == 0x14, "data.size is not 0x14 bytes"); - - SaveCalData save_info{}; - std::memcpy(&save_info, data.data(), sizeof(SaveCalData)); - user_calibration = save_info.calibration; - send_command_async_event->Signal(); - return true; - } - default: - LOG_ERROR(Service_HID, "Command not implemented {}", command); - command = RingConCommands::Error; - // Signal a reply to avoid softlocking the game - send_command_async_event->Signal(); - return false; - } -} - -std::vector<u8> RingController::GetFirmwareVersionReply() const { - const FirmwareVersionReply reply{ - .status = DataValid::Valid, - .firmware = version, - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetReadIdReply() const { - // The values are hardcoded from a real joycon - const ReadIdReply reply{ - .status = DataValid::Valid, - .id_l_x0 = 8, - .id_l_x0_2 = 41, - .id_l_x4 = 22294, - .id_h_x0 = 19777, - .id_h_x0_2 = 13621, - .id_h_x4 = 8245, - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetC020105Reply() const { - const Cmd020105Reply reply{ - .status = DataValid::Valid, - .data = 1, - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetReadUnkCalReply() const { - const ReadUnkCalReply reply{ - .status = DataValid::Valid, - .data = 0, - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetReadFactoryCalReply() const { - const ReadFactoryCalReply reply{ - .status = DataValid::Valid, - .calibration = factory_calibration, - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetReadUserCalReply() const { - const ReadUserCalReply reply{ - .status = DataValid::Valid, - .calibration = user_calibration, - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetReadRepCountReply() const { - const GetThreeByteReply reply{ - .status = DataValid::Valid, - .data = {total_rep_count, 0, 0}, - .crc = GetCrcValue({total_rep_count, 0, 0, 0}), - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetReadTotalPushCountReply() const { - const GetThreeByteReply reply{ - .status = DataValid::Valid, - .data = {total_push_count, 0, 0}, - .crc = GetCrcValue({total_push_count, 0, 0, 0}), - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetResetRepCountReply() const { - return GetReadRepCountReply(); -} - -std::vector<u8> RingController::GetSaveDataReply() const { - const StatusReply reply{ - .status = DataValid::Valid, - }; - - return GetDataVector(reply); -} - -std::vector<u8> RingController::GetErrorReply() const { - const ErrorReply reply{ - .status = DataValid::BadCRC, - }; - - return GetDataVector(reply); -} - -u8 RingController::GetCrcValue(const std::vector<u8>& data) const { - u8 crc = 0; - for (std::size_t index = 0; index < data.size(); index++) { - for (u8 i = 0x80; i > 0; i >>= 1) { - bool bit = (crc & 0x80) != 0; - if ((data[index] & i) != 0) { - bit = !bit; - } - crc <<= 1; - if (bit) { - crc ^= 0x8d; - } - } - } - return crc; -} - -template <typename T> -std::vector<u8> RingController::GetDataVector(const T& reply) const { - static_assert(std::is_trivially_copyable_v<T>); - std::vector<u8> data; - data.resize(sizeof(reply)); - std::memcpy(data.data(), &reply, sizeof(reply)); - return data; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <span> - -#include "common/common_types.h" -#include "core/hle/service/hid/hidbus/hidbus_base.h" - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::HID { - -class RingController final : public HidbusBase { -public: - explicit RingController(Core::System& system_, KernelHelpers::ServiceContext& service_context_); - ~RingController() override; - - void OnInit() override; - - void OnRelease() override; - - // Updates ringcon transfer memory - void OnUpdate() override; - - // Returns the device ID of the joycon - u8 GetDeviceId() const override; - - // Assigns a command from data - bool SetCommand(std::span<const u8> data) override; - - // Returns a reply from a command - std::vector<u8> GetReply() const override; - -private: - // These values are obtained from a real ring controller - static constexpr s16 idle_value = 2280; - static constexpr s16 idle_deadzone = 120; - static constexpr s16 range = 2500; - - // Most missing command names are leftovers from other firmware versions - enum class RingConCommands : u32 { - GetFirmwareVersion = 0x00020000, - ReadId = 0x00020100, - JoyPolling = 0x00020101, - Unknown1 = 0x00020104, - c20105 = 0x00020105, - Unknown2 = 0x00020204, - Unknown3 = 0x00020304, - Unknown4 = 0x00020404, - ReadUnkCal = 0x00020504, - ReadFactoryCal = 0x00020A04, - Unknown5 = 0x00021104, - Unknown6 = 0x00021204, - Unknown7 = 0x00021304, - ReadUserCal = 0x00021A04, - ReadRepCount = 0x00023104, - ReadTotalPushCount = 0x00023204, - ResetRepCount = 0x04013104, - Unknown8 = 0x04011104, - Unknown9 = 0x04011204, - Unknown10 = 0x04011304, - SaveCalData = 0x10011A04, - Error = 0xFFFFFFFF, - }; - - enum class DataValid : u32 { - Valid, - BadCRC, - Cal, - }; - - struct FirmwareVersion { - u8 sub; - u8 main; - }; - static_assert(sizeof(FirmwareVersion) == 0x2, "FirmwareVersion is an invalid size"); - - struct FactoryCalibration { - s32_le os_max; - s32_le hk_max; - s32_le zero_min; - s32_le zero_max; - }; - static_assert(sizeof(FactoryCalibration) == 0x10, "FactoryCalibration is an invalid size"); - - struct CalibrationValue { - s16 value; - u16 crc; - }; - static_assert(sizeof(CalibrationValue) == 0x4, "CalibrationValue is an invalid size"); - - struct UserCalibration { - CalibrationValue os_max; - CalibrationValue hk_max; - CalibrationValue zero; - }; - static_assert(sizeof(UserCalibration) == 0xC, "UserCalibration is an invalid size"); - - struct SaveCalData { - RingConCommands command; - UserCalibration calibration; - INSERT_PADDING_BYTES_NOINIT(4); - }; - static_assert(sizeof(SaveCalData) == 0x14, "SaveCalData is an invalid size"); - static_assert(std::is_trivially_copyable_v<SaveCalData>, - "SaveCalData must be trivially copyable"); - - struct FirmwareVersionReply { - DataValid status; - FirmwareVersion firmware; - INSERT_PADDING_BYTES(0x2); - }; - static_assert(sizeof(FirmwareVersionReply) == 0x8, "FirmwareVersionReply is an invalid size"); - - struct Cmd020105Reply { - DataValid status; - u8 data; - INSERT_PADDING_BYTES(0x3); - }; - static_assert(sizeof(Cmd020105Reply) == 0x8, "Cmd020105Reply is an invalid size"); - - struct StatusReply { - DataValid status; - }; - static_assert(sizeof(StatusReply) == 0x4, "StatusReply is an invalid size"); - - struct GetThreeByteReply { - DataValid status; - std::array<u8, 3> data; - u8 crc; - }; - static_assert(sizeof(GetThreeByteReply) == 0x8, "GetThreeByteReply is an invalid size"); - - struct ReadUnkCalReply { - DataValid status; - u16 data; - INSERT_PADDING_BYTES(0x2); - }; - static_assert(sizeof(ReadUnkCalReply) == 0x8, "ReadUnkCalReply is an invalid size"); - - struct ReadFactoryCalReply { - DataValid status; - FactoryCalibration calibration; - }; - static_assert(sizeof(ReadFactoryCalReply) == 0x14, "ReadFactoryCalReply is an invalid size"); - - struct ReadUserCalReply { - DataValid status; - UserCalibration calibration; - INSERT_PADDING_BYTES(0x4); - }; - static_assert(sizeof(ReadUserCalReply) == 0x14, "ReadUserCalReply is an invalid size"); - - struct ReadIdReply { - DataValid status; - u16 id_l_x0; - u16 id_l_x0_2; - u16 id_l_x4; - u16 id_h_x0; - u16 id_h_x0_2; - u16 id_h_x4; - }; - static_assert(sizeof(ReadIdReply) == 0x10, "ReadIdReply is an invalid size"); - - struct ErrorReply { - DataValid status; - INSERT_PADDING_BYTES(0x3); - }; - static_assert(sizeof(ErrorReply) == 0x8, "ErrorReply is an invalid size"); - - struct RingConData { - DataValid status; - s16_le data; - INSERT_PADDING_BYTES(0x2); - }; - static_assert(sizeof(RingConData) == 0x8, "RingConData is an invalid size"); - - // Returns RingConData struct with pressure sensor values - RingConData GetSensorValue() const; - - // Returns 8 byte reply with firmware version - std::vector<u8> GetFirmwareVersionReply() const; - - // Returns 16 byte reply with ID values - std::vector<u8> GetReadIdReply() const; - - // (STUBBED) Returns 8 byte reply - std::vector<u8> GetC020105Reply() const; - - // (STUBBED) Returns 8 byte empty reply - std::vector<u8> GetReadUnkCalReply() const; - - // Returns 20 byte reply with factory calibration values - std::vector<u8> GetReadFactoryCalReply() const; - - // Returns 20 byte reply with user calibration values - std::vector<u8> GetReadUserCalReply() const; - - // Returns 8 byte reply - std::vector<u8> GetReadRepCountReply() const; - - // Returns 8 byte reply - std::vector<u8> GetReadTotalPushCountReply() const; - - // Returns 8 byte reply - std::vector<u8> GetResetRepCountReply() const; - - // Returns 4 byte save data reply - std::vector<u8> GetSaveDataReply() const; - - // Returns 8 byte error reply - std::vector<u8> GetErrorReply() const; - - // Returns 8 bit redundancy check from provided data - u8 GetCrcValue(const std::vector<u8>& data) const; - - // Converts structs to an u8 vector equivalent - template <typename T> - std::vector<u8> GetDataVector(const T& reply) const; - - RingConCommands command{RingConCommands::Error}; - - // These counters are used in multitasking mode while the switch is sleeping - // Total steps taken - u8 total_rep_count = 0; - // Total times the ring was pushed - u8 total_push_count = 0; - - const u8 device_id = 0x20; - const FirmwareVersion version = { - .sub = 0x0, - .main = 0x2c, - }; - const FactoryCalibration factory_calibration = { - .os_max = idle_value + range + idle_deadzone, - .hk_max = idle_value - range - idle_deadzone, - .zero_min = idle_value - idle_deadzone, - .zero_max = idle_value + idle_deadzone, - }; - UserCalibration user_calibration = { - .os_max = {.value = range, .crc = 228}, - .hk_max = {.value = -range, .crc = 239}, - .zero = {.value = idle_value, .crc = 225}, - }; - - Core::HID::EmulatedController* input; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/hidbus/starlink.h" - -namespace Service::HID { -constexpr u8 DEVICE_ID = 0x28; - -Starlink::Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_) - : HidbusBase(system_, service_context_) {} -Starlink::~Starlink() = default; - -void Starlink::OnInit() { - return; -} - -void Starlink::OnRelease() { - return; -}; - -void Starlink::OnUpdate() { - if (!is_activated) { - return; - } - if (!device_enabled) { - return; - } - if (!polling_mode_enabled || transfer_memory == 0) { - return; - } - - LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); -} - -u8 Starlink::GetDeviceId() const { - return DEVICE_ID; -} - -std::vector<u8> Starlink::GetReply() const { - return {}; -} - -bool Starlink::SetCommand(std::span<const u8> data) { - LOG_ERROR(Service_HID, "Command not implemented"); - return false; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hle/service/hid/hidbus/hidbus_base.h" - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::HID { - -class Starlink final : public HidbusBase { -public: - explicit Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_); - ~Starlink() override; - - void OnInit() override; - - void OnRelease() override; - - // Updates ringcon transfer memory - void OnUpdate() override; - - // Returns the device ID of the joycon - u8 GetDeviceId() const override; - - // Assigns a command from data - bool SetCommand(std::span<const u8> data) override; - - // Returns a reply from a command - std::vector<u8> GetReply() const override; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/hidbus/stubbed.h" - -namespace Service::HID { -constexpr u8 DEVICE_ID = 0xFF; - -HidbusStubbed::HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_) - : HidbusBase(system_, service_context_) {} -HidbusStubbed::~HidbusStubbed() = default; - -void HidbusStubbed::OnInit() { - return; -} - -void HidbusStubbed::OnRelease() { - return; -}; - -void HidbusStubbed::OnUpdate() { - if (!is_activated) { - return; - } - if (!device_enabled) { - return; - } - if (!polling_mode_enabled || transfer_memory == 0) { - return; - } - - LOG_ERROR(Service_HID, "Polling mode not supported {}", polling_mode); -} - -u8 HidbusStubbed::GetDeviceId() const { - return DEVICE_ID; -} - -std::vector<u8> HidbusStubbed::GetReply() const { - return {}; -} - -bool HidbusStubbed::SetCommand(std::span<const u8> data) { - LOG_ERROR(Service_HID, "Command not implemented"); - return false; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hle/service/hid/hidbus/hidbus_base.h" - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::HID { - -class HidbusStubbed final : public HidbusBase { -public: - explicit HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_); - ~HidbusStubbed() override; - - void OnInit() override; - - void OnRelease() override; - - // Updates ringcon transfer memory - void OnUpdate() override; - - // Returns the device ID of the joycon - u8 GetDeviceId() const override; - - // Assigns a command from data - bool SetCommand(std::span<const u8> data) override; - - // Returns a reply from a command - std::vector<u8> GetReply() const override; -}; - -} // 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 @@ #include "core/core.h" #include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/service/hid/errors.h" -#include "core/hle/service/hid/hid_util.h" #include "core/hle/service/hid/irs.h" -#include "core/hle/service/hid/irsensor/clustering_processor.h" -#include "core/hle/service/hid/irsensor/image_transfer_processor.h" -#include "core/hle/service/hid/irsensor/ir_led_processor.h" -#include "core/hle/service/hid/irsensor/moment_processor.h" -#include "core/hle/service/hid/irsensor/pointing_processor.h" -#include "core/hle/service/hid/irsensor/tera_plugin_processor.h" #include "core/hle/service/ipc_helpers.h" #include "core/memory.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" +#include "hid_core/hid_result.h" +#include "hid_core/hid_util.h" +#include "hid_core/irsensor/clustering_processor.h" +#include "hid_core/irsensor/image_transfer_processor.h" +#include "hid_core/irsensor/ir_led_processor.h" +#include "hid_core/irsensor/moment_processor.h" +#include "hid_core/irsensor/pointing_processor.h" +#include "hid_core/irsensor/tera_plugin_processor.h" namespace Service::IRS { 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 @@ #pragma once #include "core/core.h" -#include "core/hid/hid_types.h" -#include "core/hid/irs_types.h" -#include "core/hle/service/hid/irsensor/processor_base.h" #include "core/hle/service/service.h" +#include "hid_core/hid_types.h" +#include "hid_core/irsensor/irs_types.h" +#include "hid_core/irsensor/processor_base.h" namespace Core::HID { 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include <array> - -#include "common/common_types.h" - -namespace Service::IRS { - -template <typename State, std::size_t max_buffer_size> -struct Lifo { - s64 sampling_number{}; - s64 buffer_count{}; - std::array<State, max_buffer_size> entries{}; - - const State& ReadCurrentEntry() const { - return entries[GetBufferTail()]; - } - - const State& ReadPreviousEntry() const { - return entries[GetPreviousEntryIndex()]; - } - - s64 GetBufferTail() const { - return sampling_number % max_buffer_size; - } - - std::size_t GetPreviousEntryIndex() const { - return static_cast<size_t>((GetBufferTail() + max_buffer_size - 1) % max_buffer_size); - } - - std::size_t GetNextEntryIndex() const { - return static_cast<size_t>((GetBufferTail() + 1) % max_buffer_size); - } - - void WriteNextEntry(const State& new_state) { - if (buffer_count < static_cast<s64>(max_buffer_size)) { - buffer_count++; - } - sampling_number++; - entries[GetBufferTail()] = new_state; - } -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include <queue> - -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/irsensor/clustering_processor.h" - -namespace Service::IRS { -ClusteringProcessor::ClusteringProcessor(Core::System& system_, - Core::IrSensor::DeviceFormat& device_format, - std::size_t npad_index) - : device{device_format}, system{system_} { - npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); - - device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; - device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; - SetDefaultConfig(); - - shared_memory = std::construct_at( - reinterpret_cast<ClusteringSharedMemory*>(&device_format.state.processor_raw_data)); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, - .is_npad_service = true, - }; - callback_key = npad_device->SetCallback(engine_callback); -} - -ClusteringProcessor::~ClusteringProcessor() { - npad_device->DeleteCallback(callback_key); -}; - -void ClusteringProcessor::StartProcessor() { - device.camera_status = Core::IrSensor::IrCameraStatus::Available; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; -} - -void ClusteringProcessor::SuspendProcessor() {} - -void ClusteringProcessor::StopProcessor() {} - -void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { - if (type != Core::HID::ControllerTriggerType::IrSensor) { - return; - } - - next_state = {}; - const auto& camera_data = npad_device->GetCamera(); - auto filtered_image = camera_data.data; - - RemoveLowIntensityData(filtered_image); - - const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x); - const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y); - const auto window_end_x = - window_start_x + static_cast<std::size_t>(current_config.window_of_interest.width); - const auto window_end_y = - window_start_y + static_cast<std::size_t>(current_config.window_of_interest.height); - - for (std::size_t y = window_start_y; y < window_end_y; y++) { - for (std::size_t x = window_start_x; x < window_end_x; x++) { - u8 pixel = GetPixel(filtered_image, x, y); - if (pixel == 0) { - continue; - } - const auto cluster = GetClusterProperties(filtered_image, x, y); - if (cluster.pixel_count > current_config.pixel_count_max) { - continue; - } - if (cluster.pixel_count < current_config.pixel_count_min) { - continue; - } - // Cluster object limit reached - if (next_state.object_count >= next_state.data.size()) { - continue; - } - next_state.data[next_state.object_count] = cluster; - next_state.object_count++; - } - } - - next_state.sampling_number = camera_data.sample; - next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); - next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; - shared_memory->clustering_lifo.WriteNextEntry(next_state); - - if (!IsProcessorActive()) { - StartProcessor(); - } -} - -void ClusteringProcessor::RemoveLowIntensityData(std::vector<u8>& data) { - for (u8& pixel : data) { - if (pixel < current_config.pixel_count_min) { - pixel = 0; - } - } -} - -ClusteringProcessor::ClusteringData ClusteringProcessor::GetClusterProperties(std::vector<u8>& data, - std::size_t x, - std::size_t y) { - using DataPoint = Common::Point<std::size_t>; - std::queue<DataPoint> search_points{}; - ClusteringData current_cluster = GetPixelProperties(data, x, y); - SetPixel(data, x, y, 0); - search_points.emplace<DataPoint>({x, y}); - - while (!search_points.empty()) { - const auto point = search_points.front(); - search_points.pop(); - - // Avoid negative numbers - if (point.x == 0 || point.y == 0) { - continue; - } - - std::array<DataPoint, 4> new_points{ - DataPoint{point.x - 1, point.y}, - {point.x, point.y - 1}, - {point.x + 1, point.y}, - {point.x, point.y + 1}, - }; - - for (const auto new_point : new_points) { - if (new_point.x >= width) { - continue; - } - if (new_point.y >= height) { - continue; - } - if (GetPixel(data, new_point.x, new_point.y) < current_config.object_intensity_min) { - continue; - } - const ClusteringData cluster = GetPixelProperties(data, new_point.x, new_point.y); - current_cluster = MergeCluster(current_cluster, cluster); - SetPixel(data, new_point.x, new_point.y, 0); - search_points.emplace<DataPoint>({new_point.x, new_point.y}); - } - } - - return current_cluster; -} - -ClusteringProcessor::ClusteringData ClusteringProcessor::GetPixelProperties( - const std::vector<u8>& data, std::size_t x, std::size_t y) const { - return { - .average_intensity = GetPixel(data, x, y) / 255.0f, - .centroid = - { - .x = static_cast<f32>(x), - .y = static_cast<f32>(y), - - }, - .pixel_count = 1, - .bound = - { - .x = static_cast<s16>(x), - .y = static_cast<s16>(y), - .width = 1, - .height = 1, - }, - }; -} - -ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster( - const ClusteringData a, const ClusteringData b) const { - const f32 a_pixel_count = static_cast<f32>(a.pixel_count); - const f32 b_pixel_count = static_cast<f32>(b.pixel_count); - const f32 pixel_count = a_pixel_count + b_pixel_count; - const f32 average_intensity = - (a.average_intensity * a_pixel_count + b.average_intensity * b_pixel_count) / pixel_count; - const Core::IrSensor::IrsCentroid centroid = { - .x = (a.centroid.x * a_pixel_count + b.centroid.x * b_pixel_count) / pixel_count, - .y = (a.centroid.y * a_pixel_count + b.centroid.y * b_pixel_count) / pixel_count, - }; - s16 bound_start_x = a.bound.x < b.bound.x ? a.bound.x : b.bound.x; - s16 bound_start_y = a.bound.y < b.bound.y ? a.bound.y : b.bound.y; - s16 a_bound_end_x = a.bound.x + a.bound.width; - s16 a_bound_end_y = a.bound.y + a.bound.height; - s16 b_bound_end_x = b.bound.x + b.bound.width; - s16 b_bound_end_y = b.bound.y + b.bound.height; - - const Core::IrSensor::IrsRect bound = { - .x = bound_start_x, - .y = bound_start_y, - .width = a_bound_end_x > b_bound_end_x ? static_cast<s16>(a_bound_end_x - bound_start_x) - : static_cast<s16>(b_bound_end_x - bound_start_x), - .height = a_bound_end_y > b_bound_end_y ? static_cast<s16>(a_bound_end_y - bound_start_y) - : static_cast<s16>(b_bound_end_y - bound_start_y), - }; - - return { - .average_intensity = average_intensity, - .centroid = centroid, - .pixel_count = static_cast<u32>(pixel_count), - .bound = bound, - }; -} - -u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { - if ((y * width) + x >= data.size()) { - return 0; - } - return data[(y * width) + x]; -} - -void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) { - if ((y * width) + x >= data.size()) { - return; - } - data[(y * width) + x] = value; -} - -void ClusteringProcessor::SetDefaultConfig() { - using namespace std::literals::chrono_literals; - current_config.camera_config.exposure_time = std::chrono::microseconds(200ms).count(); - current_config.camera_config.gain = 2; - current_config.camera_config.is_negative_used = false; - current_config.camera_config.light_target = Core::IrSensor::CameraLightTarget::BrightLeds; - current_config.window_of_interest = { - .x = 0, - .y = 0, - .width = width, - .height = height, - }; - current_config.pixel_count_min = 3; - current_config.pixel_count_max = static_cast<u32>(GetDataSize(format)); - current_config.is_external_light_filter_enabled = true; - current_config.object_intensity_min = 150; - - npad_device->SetCameraFormat(format); -} - -void ClusteringProcessor::SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config) { - current_config.camera_config.exposure_time = config.camera_config.exposure_time; - current_config.camera_config.gain = config.camera_config.gain; - current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; - current_config.camera_config.light_target = - static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); - current_config.window_of_interest = config.window_of_interest; - current_config.pixel_count_min = config.pixel_count_min; - current_config.pixel_count_max = config.pixel_count_max; - current_config.is_external_light_filter_enabled = config.is_external_light_filter_enabled; - current_config.object_intensity_min = config.object_intensity_min; - - LOG_INFO(Service_IRS, - "Processor config, exposure_time={}, gain={}, is_negative_used={}, " - "light_target={}, window_of_interest=({}, {}, {}, {}), pixel_count_min={}, " - "pixel_count_max={}, is_external_light_filter_enabled={}, object_intensity_min={}", - current_config.camera_config.exposure_time, current_config.camera_config.gain, - current_config.camera_config.is_negative_used, - current_config.camera_config.light_target, current_config.window_of_interest.x, - current_config.window_of_interest.y, current_config.window_of_interest.width, - current_config.window_of_interest.height, current_config.pixel_count_min, - current_config.pixel_count_max, current_config.is_external_light_filter_enabled, - current_config.object_intensity_min); - - npad_device->SetCameraFormat(format); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hid/irs_types.h" -#include "core/hle/service/hid/irs_ring_lifo.h" -#include "core/hle/service/hid/irsensor/processor_base.h" - -namespace Core { -class System; -} - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::IRS { -class ClusteringProcessor final : public ProcessorBase { -public: - explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, - std::size_t npad_index); - ~ClusteringProcessor() override; - - // Called when the processor is initialized - void StartProcessor() override; - - // Called when the processor is suspended - void SuspendProcessor() override; - - // Called when the processor is stopped - void StopProcessor() override; - - // Sets config parameters of the camera - void SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config); - -private: - static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size320x240; - static constexpr std::size_t width = 320; - static constexpr std::size_t height = 240; - - // This is nn::irsensor::ClusteringProcessorConfig - struct ClusteringProcessorConfig { - Core::IrSensor::CameraConfig camera_config; - Core::IrSensor::IrsRect window_of_interest; - u32 pixel_count_min; - u32 pixel_count_max; - u32 object_intensity_min; - bool is_external_light_filter_enabled; - INSERT_PADDING_BYTES(3); - }; - static_assert(sizeof(ClusteringProcessorConfig) == 0x30, - "ClusteringProcessorConfig is an invalid size"); - - // This is nn::irsensor::AdaptiveClusteringProcessorConfig - struct AdaptiveClusteringProcessorConfig { - Core::IrSensor::AdaptiveClusteringMode mode; - Core::IrSensor::AdaptiveClusteringTargetDistance target_distance; - }; - static_assert(sizeof(AdaptiveClusteringProcessorConfig) == 0x8, - "AdaptiveClusteringProcessorConfig is an invalid size"); - - // This is nn::irsensor::ClusteringData - struct ClusteringData { - f32 average_intensity; - Core::IrSensor::IrsCentroid centroid; - u32 pixel_count; - Core::IrSensor::IrsRect bound; - }; - static_assert(sizeof(ClusteringData) == 0x18, "ClusteringData is an invalid size"); - - // This is nn::irsensor::ClusteringProcessorState - struct ClusteringProcessorState { - s64 sampling_number; - u64 timestamp; - u8 object_count; - INSERT_PADDING_BYTES(3); - Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; - std::array<ClusteringData, 0x10> data; - }; - static_assert(sizeof(ClusteringProcessorState) == 0x198, - "ClusteringProcessorState is an invalid size"); - - struct ClusteringSharedMemory { - Service::IRS::Lifo<ClusteringProcessorState, 6> clustering_lifo; - static_assert(sizeof(clustering_lifo) == 0x9A0, "clustering_lifo is an invalid size"); - INSERT_PADDING_WORDS(0x11F); - }; - static_assert(sizeof(ClusteringSharedMemory) == 0xE20, - "ClusteringSharedMemory is an invalid size"); - - void OnControllerUpdate(Core::HID::ControllerTriggerType type); - void RemoveLowIntensityData(std::vector<u8>& data); - ClusteringData GetClusterProperties(std::vector<u8>& data, std::size_t x, std::size_t y); - ClusteringData GetPixelProperties(const std::vector<u8>& data, std::size_t x, - std::size_t y) const; - ClusteringData MergeCluster(const ClusteringData a, const ClusteringData b) const; - u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const; - void SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value); - - // Sets config parameters of the camera - void SetDefaultConfig(); - - ClusteringSharedMemory* shared_memory = nullptr; - ClusteringProcessorState next_state{}; - - ClusteringProcessorConfig current_config{}; - Core::IrSensor::DeviceFormat& device; - Core::HID::EmulatedController* npad_device; - int callback_key{}; - - Core::System& system; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/core.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/irsensor/image_transfer_processor.h" -#include "core/memory.h" - -namespace Service::IRS { -ImageTransferProcessor::ImageTransferProcessor(Core::System& system_, - Core::IrSensor::DeviceFormat& device_format, - std::size_t npad_index) - : device{device_format}, system{system_} { - npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, - .is_npad_service = true, - }; - callback_key = npad_device->SetCallback(engine_callback); - - device.mode = Core::IrSensor::IrSensorMode::ImageTransferProcessor; - device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; -} - -ImageTransferProcessor::~ImageTransferProcessor() { - npad_device->DeleteCallback(callback_key); -}; - -void ImageTransferProcessor::StartProcessor() { - is_active = true; - device.camera_status = Core::IrSensor::IrCameraStatus::Available; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; - processor_state.sampling_number = 0; - processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; -} - -void ImageTransferProcessor::SuspendProcessor() {} - -void ImageTransferProcessor::StopProcessor() {} - -void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { - if (type != Core::HID::ControllerTriggerType::IrSensor) { - return; - } - if (transfer_memory == 0) { - return; - } - - const auto& camera_data = npad_device->GetCamera(); - - // This indicates how much ambient light is present - processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; - processor_state.sampling_number = camera_data.sample; - - if (camera_data.format != current_config.origin_format) { - LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, - current_config.origin_format); - system.ApplicationMemory().ZeroBlock(transfer_memory, - GetDataSize(current_config.trimming_format)); - return; - } - - if (current_config.origin_format > current_config.trimming_format) { - LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", - current_config.origin_format, current_config.trimming_format); - system.ApplicationMemory().ZeroBlock(transfer_memory, - GetDataSize(current_config.trimming_format)); - return; - } - - std::vector<u8> window_data{}; - const auto origin_width = GetDataWidth(current_config.origin_format); - const auto origin_height = GetDataHeight(current_config.origin_format); - const auto trimming_width = GetDataWidth(current_config.trimming_format); - const auto trimming_height = GetDataHeight(current_config.trimming_format); - window_data.resize(GetDataSize(current_config.trimming_format)); - - if (trimming_width + current_config.trimming_start_x > origin_width || - trimming_height + current_config.trimming_start_y > origin_height) { - LOG_WARNING(Service_IRS, - "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", - current_config.trimming_start_x, current_config.trimming_start_y, - trimming_width, trimming_height, origin_width, origin_height); - system.ApplicationMemory().ZeroBlock(transfer_memory, - GetDataSize(current_config.trimming_format)); - return; - } - - for (std::size_t y = 0; y < trimming_height; y++) { - for (std::size_t x = 0; x < trimming_width; x++) { - const std::size_t window_index = (y * trimming_width) + x; - const std::size_t origin_index = - ((y + current_config.trimming_start_y) * origin_width) + x + - current_config.trimming_start_x; - window_data[window_index] = camera_data.data[origin_index]; - } - } - - system.ApplicationMemory().WriteBlock(transfer_memory, window_data.data(), - GetDataSize(current_config.trimming_format)); - - if (!IsProcessorActive()) { - StartProcessor(); - } -} - -void ImageTransferProcessor::SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config) { - current_config.camera_config.exposure_time = config.camera_config.exposure_time; - current_config.camera_config.gain = config.camera_config.gain; - current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; - current_config.camera_config.light_target = - static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); - current_config.origin_format = - static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); - current_config.trimming_format = - static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); - current_config.trimming_start_x = 0; - current_config.trimming_start_y = 0; - - npad_device->SetCameraFormat(current_config.origin_format); -} - -void ImageTransferProcessor::SetConfig( - Core::IrSensor::PackedImageTransferProcessorExConfig config) { - current_config.camera_config.exposure_time = config.camera_config.exposure_time; - current_config.camera_config.gain = config.camera_config.gain; - current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; - current_config.camera_config.light_target = - static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); - current_config.origin_format = - static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.origin_format); - current_config.trimming_format = - static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.trimming_format); - current_config.trimming_start_x = config.trimming_start_x; - current_config.trimming_start_y = config.trimming_start_y; - - npad_device->SetCameraFormat(current_config.origin_format); -} - -void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { - transfer_memory = t_mem; -} - -Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( - std::vector<u8>& data) const { - const auto size = GetDataSize(current_config.trimming_format); - data.resize(size); - system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size); - return processor_state; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/typed_address.h" -#include "core/hid/irs_types.h" -#include "core/hle/service/hid/irsensor/processor_base.h" - -namespace Core { -class System; -} - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::IRS { -class ImageTransferProcessor final : public ProcessorBase { -public: - explicit ImageTransferProcessor(Core::System& system_, - Core::IrSensor::DeviceFormat& device_format, - std::size_t npad_index); - ~ImageTransferProcessor() override; - - // Called when the processor is initialized - void StartProcessor() override; - - // Called when the processor is suspended - void SuspendProcessor() override; - - // Called when the processor is stopped - void StopProcessor() override; - - // Sets config parameters of the camera - void SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config); - void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); - - // Transfer memory where the image data will be stored - void SetTransferMemoryAddress(Common::ProcessAddress t_mem); - - Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; - -private: - // This is nn::irsensor::ImageTransferProcessorConfig - struct ImageTransferProcessorConfig { - Core::IrSensor::CameraConfig camera_config; - Core::IrSensor::ImageTransferProcessorFormat format; - }; - static_assert(sizeof(ImageTransferProcessorConfig) == 0x20, - "ImageTransferProcessorConfig is an invalid size"); - - // This is nn::irsensor::ImageTransferProcessorExConfig - struct ImageTransferProcessorExConfig { - Core::IrSensor::CameraConfig camera_config; - Core::IrSensor::ImageTransferProcessorFormat origin_format; - Core::IrSensor::ImageTransferProcessorFormat trimming_format; - u16 trimming_start_x; - u16 trimming_start_y; - bool is_external_light_filter_enabled; - INSERT_PADDING_BYTES(3); - }; - static_assert(sizeof(ImageTransferProcessorExConfig) == 0x28, - "ImageTransferProcessorExConfig is an invalid size"); - - void OnControllerUpdate(Core::HID::ControllerTriggerType type); - - ImageTransferProcessorExConfig current_config{}; - Core::IrSensor::ImageTransferProcessorState processor_state{}; - Core::IrSensor::DeviceFormat& device; - Core::HID::EmulatedController* npad_device; - int callback_key{}; - - Core::System& system; - Common::ProcessAddress transfer_memory{}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/hle/service/hid/irsensor/ir_led_processor.h" - -namespace Service::IRS { -IrLedProcessor::IrLedProcessor(Core::IrSensor::DeviceFormat& device_format) - : device(device_format) { - device.mode = Core::IrSensor::IrSensorMode::IrLedProcessor; - device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; -} - -IrLedProcessor::~IrLedProcessor() = default; - -void IrLedProcessor::StartProcessor() {} - -void IrLedProcessor::SuspendProcessor() {} - -void IrLedProcessor::StopProcessor() {} - -void IrLedProcessor::SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config) { - current_config.light_target = - static_cast<Core::IrSensor::CameraLightTarget>(config.light_target); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/bit_field.h" -#include "common/common_types.h" -#include "core/hid/irs_types.h" -#include "core/hle/service/hid/irsensor/processor_base.h" - -namespace Service::IRS { -class IrLedProcessor final : public ProcessorBase { -public: - explicit IrLedProcessor(Core::IrSensor::DeviceFormat& device_format); - ~IrLedProcessor() override; - - // Called when the processor is initialized - void StartProcessor() override; - - // Called when the processor is suspended - void SuspendProcessor() override; - - // Called when the processor is stopped - void StopProcessor() override; - - // Sets config parameters of the camera - void SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config); - -private: - // This is nn::irsensor::IrLedProcessorConfig - struct IrLedProcessorConfig { - Core::IrSensor::CameraLightTarget light_target; - }; - static_assert(sizeof(IrLedProcessorConfig) == 0x4, "IrLedProcessorConfig is an invalid size"); - - struct IrLedProcessorState { - s64 sampling_number; - u64 timestamp; - std::array<u8, 0x8> data; - }; - static_assert(sizeof(IrLedProcessorState) == 0x18, "IrLedProcessorState is an invalid size"); - - IrLedProcessorConfig current_config{}; - Core::IrSensor::DeviceFormat& device; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hle/service/hid/irsensor/moment_processor.h" - -namespace Service::IRS { -static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30; -static constexpr std::size_t ImageWidth = 40; -static constexpr std::size_t ImageHeight = 30; - -MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, - std::size_t npad_index) - : device(device_format), system{system_} { - npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); - - device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; - device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; - - shared_memory = std::construct_at( - reinterpret_cast<MomentSharedMemory*>(&device_format.state.processor_raw_data)); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, - .is_npad_service = true, - }; - callback_key = npad_device->SetCallback(engine_callback); -} - -MomentProcessor::~MomentProcessor() { - npad_device->DeleteCallback(callback_key); -}; - -void MomentProcessor::StartProcessor() { - device.camera_status = Core::IrSensor::IrCameraStatus::Available; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; -} - -void MomentProcessor::SuspendProcessor() {} - -void MomentProcessor::StopProcessor() {} - -void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { - if (type != Core::HID::ControllerTriggerType::IrSensor) { - return; - } - - next_state = {}; - const auto& camera_data = npad_device->GetCamera(); - - const auto window_width = static_cast<std::size_t>(current_config.window_of_interest.width); - const auto window_height = static_cast<std::size_t>(current_config.window_of_interest.height); - const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x); - const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y); - - const std::size_t block_width = window_width / Columns; - const std::size_t block_height = window_height / Rows; - - for (std::size_t row = 0; row < Rows; row++) { - for (std::size_t column = 0; column < Columns; column++) { - const size_t x_pos = (column * block_width) + window_start_x; - const size_t y_pos = (row * block_height) + window_start_y; - auto& statistic = next_state.statistic[column + (row * Columns)]; - statistic = GetStatistic(camera_data.data, x_pos, y_pos, block_width, block_height); - } - } - - next_state.sampling_number = camera_data.sample; - next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); - next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; - shared_memory->moment_lifo.WriteNextEntry(next_state); - - if (!IsProcessorActive()) { - StartProcessor(); - } -} - -u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { - if ((y * ImageWidth) + x >= data.size()) { - return 0; - } - return data[(y * ImageWidth) + x]; -} - -MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector<u8>& data, - std::size_t start_x, - std::size_t start_y, - std::size_t width, - std::size_t height) const { - // The actual implementation is always 320x240 - static constexpr std::size_t RealWidth = 320; - static constexpr std::size_t RealHeight = 240; - static constexpr std::size_t Threshold = 30; - MomentStatistic statistic{}; - std::size_t active_points{}; - - // Sum all data points on the block that meet with the threshold - for (std::size_t y = 0; y < width; y++) { - for (std::size_t x = 0; x < height; x++) { - const size_t x_pos = x + start_x; - const size_t y_pos = y + start_y; - const auto pixel = - GetPixel(data, x_pos * ImageWidth / RealWidth, y_pos * ImageHeight / RealHeight); - - if (pixel < Threshold) { - continue; - } - - statistic.average_intensity += pixel; - - statistic.centroid.x += static_cast<float>(x_pos); - statistic.centroid.y += static_cast<float>(y_pos); - - active_points++; - } - } - - // Return an empty field if no points were available - if (active_points == 0) { - return {}; - } - - // Finally calculate the actual centroid and average intensity - statistic.centroid.x /= static_cast<float>(active_points); - statistic.centroid.y /= static_cast<float>(active_points); - statistic.average_intensity /= static_cast<f32>(width * height); - - return statistic; -} - -void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) { - current_config.camera_config.exposure_time = config.camera_config.exposure_time; - current_config.camera_config.gain = config.camera_config.gain; - current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; - current_config.camera_config.light_target = - static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); - current_config.window_of_interest = config.window_of_interest; - current_config.preprocess = - static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); - current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; - - npad_device->SetCameraFormat(format); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/bit_field.h" -#include "common/common_types.h" -#include "core/hid/irs_types.h" -#include "core/hle/service/hid/irs_ring_lifo.h" -#include "core/hle/service/hid/irsensor/processor_base.h" - -namespace Core { -class System; -} - -namespace Core::HID { -class EmulatedController; -} // namespace Core::HID - -namespace Service::IRS { -class MomentProcessor final : public ProcessorBase { -public: - explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, - std::size_t npad_index); - ~MomentProcessor() override; - - // Called when the processor is initialized - void StartProcessor() override; - - // Called when the processor is suspended - void SuspendProcessor() override; - - // Called when the processor is stopped - void StopProcessor() override; - - // Sets config parameters of the camera - void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); - -private: - static constexpr std::size_t Columns = 8; - static constexpr std::size_t Rows = 6; - - // This is nn::irsensor::MomentProcessorConfig - struct MomentProcessorConfig { - Core::IrSensor::CameraConfig camera_config; - Core::IrSensor::IrsRect window_of_interest; - Core::IrSensor::MomentProcessorPreprocess preprocess; - u32 preprocess_intensity_threshold; - }; - static_assert(sizeof(MomentProcessorConfig) == 0x28, - "MomentProcessorConfig is an invalid size"); - - // This is nn::irsensor::MomentStatistic - struct MomentStatistic { - f32 average_intensity; - Core::IrSensor::IrsCentroid centroid; - }; - static_assert(sizeof(MomentStatistic) == 0xC, "MomentStatistic is an invalid size"); - - // This is nn::irsensor::MomentProcessorState - struct MomentProcessorState { - s64 sampling_number; - u64 timestamp; - Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; - INSERT_PADDING_BYTES(4); - std::array<MomentStatistic, Columns * Rows> statistic; - }; - static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); - - struct MomentSharedMemory { - Service::IRS::Lifo<MomentProcessorState, 6> moment_lifo; - }; - static_assert(sizeof(MomentSharedMemory) == 0xE20, "MomentSharedMemory is an invalid size"); - - void OnControllerUpdate(Core::HID::ControllerTriggerType type); - u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const; - MomentStatistic GetStatistic(const std::vector<u8>& data, std::size_t start_x, - std::size_t start_y, std::size_t width, std::size_t height) const; - - MomentSharedMemory* shared_memory = nullptr; - MomentProcessorState next_state{}; - - MomentProcessorConfig current_config{}; - Core::IrSensor::DeviceFormat& device; - Core::HID::EmulatedController* npad_device; - int callback_key{}; - - Core::System& system; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/hle/service/hid/irsensor/pointing_processor.h" - -namespace Service::IRS { -PointingProcessor::PointingProcessor(Core::IrSensor::DeviceFormat& device_format) - : device(device_format) { - device.mode = Core::IrSensor::IrSensorMode::PointingProcessorMarker; - device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; -} - -PointingProcessor::~PointingProcessor() = default; - -void PointingProcessor::StartProcessor() {} - -void PointingProcessor::SuspendProcessor() {} - -void PointingProcessor::StopProcessor() {} - -void PointingProcessor::SetConfig(Core::IrSensor::PackedPointingProcessorConfig config) { - current_config.window_of_interest = config.window_of_interest; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hid/irs_types.h" -#include "core/hle/service/hid/irsensor/processor_base.h" - -namespace Service::IRS { -class PointingProcessor final : public ProcessorBase { -public: - explicit PointingProcessor(Core::IrSensor::DeviceFormat& device_format); - ~PointingProcessor() override; - - // Called when the processor is initialized - void StartProcessor() override; - - // Called when the processor is suspended - void SuspendProcessor() override; - - // Called when the processor is stopped - void StopProcessor() override; - - // Sets config parameters of the camera - void SetConfig(Core::IrSensor::PackedPointingProcessorConfig config); - -private: - // This is nn::irsensor::PointingProcessorConfig - struct PointingProcessorConfig { - Core::IrSensor::IrsRect window_of_interest; - }; - static_assert(sizeof(PointingProcessorConfig) == 0x8, - "PointingProcessorConfig is an invalid size"); - - struct PointingProcessorMarkerData { - u8 pointing_status; - INSERT_PADDING_BYTES(3); - u32 unknown; - float unknown_float1; - float position_x; - float position_y; - float unknown_float2; - Core::IrSensor::IrsRect window_of_interest; - }; - static_assert(sizeof(PointingProcessorMarkerData) == 0x20, - "PointingProcessorMarkerData is an invalid size"); - - struct PointingProcessorMarkerState { - s64 sampling_number; - u64 timestamp; - std::array<PointingProcessorMarkerData, 0x3> data; - }; - static_assert(sizeof(PointingProcessorMarkerState) == 0x70, - "PointingProcessorMarkerState is an invalid size"); - - PointingProcessorConfig current_config{}; - Core::IrSensor::DeviceFormat& device; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/hle/service/hid/irsensor/processor_base.h" - -namespace Service::IRS { - -ProcessorBase::ProcessorBase() {} -ProcessorBase::~ProcessorBase() = default; - -bool ProcessorBase::IsProcessorActive() const { - return is_active; -} - -std::size_t ProcessorBase::GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const { - switch (format) { - case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: - return 320 * 240; - case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: - return 160 * 120; - case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: - return 80 * 60; - case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: - return 40 * 30; - case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: - return 20 * 15; - default: - return 0; - } -} - -std::size_t ProcessorBase::GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const { - switch (format) { - case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: - return 320; - case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: - return 160; - case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: - return 80; - case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: - return 40; - case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: - return 20; - default: - return 0; - } -} - -std::size_t ProcessorBase::GetDataHeight( - Core::IrSensor::ImageTransferProcessorFormat format) const { - switch (format) { - case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: - return 240; - case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: - return 120; - case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: - return 60; - case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: - return 30; - case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: - return 15; - default: - return 0; - } -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/common_types.h" -#include "core/hid/irs_types.h" - -namespace Service::IRS { -class ProcessorBase { -public: - explicit ProcessorBase(); - virtual ~ProcessorBase(); - - virtual void StartProcessor() = 0; - virtual void SuspendProcessor() = 0; - virtual void StopProcessor() = 0; - - bool IsProcessorActive() const; - -protected: - /// Returns the number of bytes the image uses - std::size_t GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const; - - /// Returns the width of the image - std::size_t GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const; - - /// Returns the height of the image - std::size_t GetDataHeight(Core::IrSensor::ImageTransferProcessorFormat format) const; - - bool is_active{false}; -}; -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "core/hle/service/hid/irsensor/tera_plugin_processor.h" - -namespace Service::IRS { -TeraPluginProcessor::TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format) - : device(device_format) { - device.mode = Core::IrSensor::IrSensorMode::TeraPluginProcessor; - device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; - device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; -} - -TeraPluginProcessor::~TeraPluginProcessor() = default; - -void TeraPluginProcessor::StartProcessor() {} - -void TeraPluginProcessor::SuspendProcessor() {} - -void TeraPluginProcessor::StopProcessor() {} - -void TeraPluginProcessor::SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config) { - current_config.mode = config.mode; - current_config.unknown_1 = config.unknown_1; - current_config.unknown_2 = config.unknown_2; - current_config.unknown_3 = config.unknown_3; -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "common/bit_field.h" -#include "common/common_types.h" -#include "core/hid/irs_types.h" -#include "core/hle/service/hid/irsensor/processor_base.h" - -namespace Service::IRS { -class TeraPluginProcessor final : public ProcessorBase { -public: - explicit TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format); - ~TeraPluginProcessor() override; - - // Called when the processor is initialized - void StartProcessor() override; - - // Called when the processor is suspended - void SuspendProcessor() override; - - // Called when the processor is stopped - void StopProcessor() override; - - // Sets config parameters of the camera - void SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config); - -private: - // This is nn::irsensor::TeraPluginProcessorConfig - struct TeraPluginProcessorConfig { - u8 mode; - u8 unknown_1; - u8 unknown_2; - u8 unknown_3; - }; - static_assert(sizeof(TeraPluginProcessorConfig) == 0x4, - "TeraPluginProcessorConfig is an invalid size"); - - struct TeraPluginProcessorState { - s64 sampling_number; - u64 timestamp; - Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; - std::array<u8, 0x12c> data; - }; - static_assert(sizeof(TeraPluginProcessorState) == 0x140, - "TeraPluginProcessorState is an invalid size"); - - TeraPluginProcessorConfig current_config{}; - Core::IrSensor::DeviceFormat& device; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "common/logging/log.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hid/hid_core.h" -#include "core/hle/kernel/k_shared_memory.h" -#include "core/hle/service/hid/resource_manager.h" -#include "core/hle/service/ipc_helpers.h" - -#include "core/hle/service/hid/controllers/applet_resource.h" -#include "core/hle/service/hid/controllers/capture_button.h" -#include "core/hle/service/hid/controllers/console_six_axis.h" -#include "core/hle/service/hid/controllers/debug_mouse.h" -#include "core/hle/service/hid/controllers/debug_pad.h" -#include "core/hle/service/hid/controllers/digitizer.h" -#include "core/hle/service/hid/controllers/gesture.h" -#include "core/hle/service/hid/controllers/home_button.h" -#include "core/hle/service/hid/controllers/keyboard.h" -#include "core/hle/service/hid/controllers/mouse.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/controllers/palma.h" -#include "core/hle/service/hid/controllers/seven_six_axis.h" -#include "core/hle/service/hid/controllers/six_axis.h" -#include "core/hle/service/hid/controllers/sleep_button.h" -#include "core/hle/service/hid/controllers/touchscreen.h" -#include "core/hle/service/hid/controllers/types/shared_memory_format.h" -#include "core/hle/service/hid/controllers/unique_pad.h" - -namespace Service::HID { - -// Updating period for each HID device. -// Period time is obtained by measuring the number of samples in a second on HW using a homebrew -// Correct npad_update_ns is 4ms this is overclocked to lower input lag -constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz) -constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz) -constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) -constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) - -ResourceManager::ResourceManager(Core::System& system_) - : system{system_}, service_context{system_, "hid"} { - applet_resource = std::make_shared<AppletResource>(system); -} - -ResourceManager::~ResourceManager() = default; - -void ResourceManager::Initialize() { - if (is_initialized) { - return; - } - - system.HIDCore().ReloadInputDevices(); - - InitializeHidCommonSampler(); - InitializeTouchScreenSampler(); - InitializeConsoleSixAxisSampler(); - InitializeAHidSampler(); - - is_initialized = true; -} - -std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const { - return applet_resource; -} - -std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const { - return capture_button; -} - -std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const { - return console_six_axis; -} - -std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const { - return debug_mouse; -} - -std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const { - return debug_pad; -} - -std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const { - return digitizer; -} - -std::shared_ptr<Gesture> ResourceManager::GetGesture() const { - return gesture; -} - -std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const { - return home_button; -} - -std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const { - return keyboard; -} - -std::shared_ptr<Mouse> ResourceManager::GetMouse() const { - return mouse; -} - -std::shared_ptr<NPad> ResourceManager::GetNpad() const { - return npad; -} - -std::shared_ptr<Palma> ResourceManager::GetPalma() const { - return palma; -} - -std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const { - return seven_six_axis; -} - -std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const { - return six_axis; -} - -std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const { - return sleep_button; -} - -std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const { - return touch_screen; -} - -std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const { - return unique_pad; -} - -Result ResourceManager::CreateAppletResource(u64 aruid) { - if (aruid == SystemAruid) { - const auto result = RegisterCoreAppletResource(); - if (result.IsError()) { - return result; - } - return GetNpad()->ActivateNpadResource(); - } - - const auto result = CreateAppletResourceImpl(aruid); - if (result.IsError()) { - return result; - } - - // Homebrew doesn't try to activate some controllers, so we activate them by default - npad->Activate(); - six_axis->Activate(); - touch_screen->Activate(); - - return GetNpad()->ActivateNpadResource(aruid); -} - -Result ResourceManager::CreateAppletResourceImpl(u64 aruid) { - std::scoped_lock lock{shared_mutex}; - return applet_resource->CreateAppletResource(aruid); -} - -void ResourceManager::InitializeHidCommonSampler() { - debug_pad = std::make_shared<DebugPad>(system.HIDCore()); - mouse = std::make_shared<Mouse>(system.HIDCore()); - debug_mouse = std::make_shared<DebugMouse>(system.HIDCore()); - keyboard = std::make_shared<Keyboard>(system.HIDCore()); - unique_pad = std::make_shared<UniquePad>(system.HIDCore()); - npad = std::make_shared<NPad>(system.HIDCore(), service_context); - gesture = std::make_shared<Gesture>(system.HIDCore()); - home_button = std::make_shared<HomeButton>(system.HIDCore()); - sleep_button = std::make_shared<SleepButton>(system.HIDCore()); - capture_button = std::make_shared<CaptureButton>(system.HIDCore()); - digitizer = std::make_shared<Digitizer>(system.HIDCore()); - - palma = std::make_shared<Palma>(system.HIDCore(), service_context); - six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad); - - debug_pad->SetAppletResource(applet_resource, &shared_mutex); - digitizer->SetAppletResource(applet_resource, &shared_mutex); - keyboard->SetAppletResource(applet_resource, &shared_mutex); - npad->SetNpadExternals(applet_resource, &shared_mutex); - six_axis->SetAppletResource(applet_resource, &shared_mutex); - mouse->SetAppletResource(applet_resource, &shared_mutex); - debug_mouse->SetAppletResource(applet_resource, &shared_mutex); - home_button->SetAppletResource(applet_resource, &shared_mutex); - sleep_button->SetAppletResource(applet_resource, &shared_mutex); - capture_button->SetAppletResource(applet_resource, &shared_mutex); -} - -void ResourceManager::InitializeTouchScreenSampler() { - gesture = std::make_shared<Gesture>(system.HIDCore()); - touch_screen = std::make_shared<TouchScreen>(system.HIDCore()); - - touch_screen->SetAppletResource(applet_resource, &shared_mutex); - gesture->SetAppletResource(applet_resource, &shared_mutex); -} - -void ResourceManager::InitializeConsoleSixAxisSampler() { - console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore()); - seven_six_axis = std::make_shared<SevenSixAxis>(system); - - console_six_axis->SetAppletResource(applet_resource, &shared_mutex); -} - -void ResourceManager::InitializeAHidSampler() { - // TODO -} - -Result ResourceManager::RegisterCoreAppletResource() { - std::scoped_lock lock{shared_mutex}; - return applet_resource->RegisterCoreAppletResource(); -} - -Result ResourceManager::UnregisterCoreAppletResource() { - std::scoped_lock lock{shared_mutex}; - return applet_resource->UnregisterCoreAppletResource(); -} - -Result ResourceManager::RegisterAppletResourceUserId(u64 aruid, bool bool_value) { - std::scoped_lock lock{shared_mutex}; - auto result = applet_resource->RegisterAppletResourceUserId(aruid, bool_value); - if (result.IsSuccess()) { - result = npad->RegisterAppletResourceUserId(aruid); - } - return result; -} - -void ResourceManager::UnregisterAppletResourceUserId(u64 aruid) { - std::scoped_lock lock{shared_mutex}; - applet_resource->UnregisterAppletResourceUserId(aruid); -} - -Result ResourceManager::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid) { - std::scoped_lock lock{shared_mutex}; - return applet_resource->GetSharedMemoryHandle(out_handle, aruid); -} - -void ResourceManager::FreeAppletResourceId(u64 aruid) { - std::scoped_lock lock{shared_mutex}; - applet_resource->FreeAppletResourceId(aruid); -} - -void ResourceManager::EnableInput(u64 aruid, bool is_enabled) { - std::scoped_lock lock{shared_mutex}; - applet_resource->EnableInput(aruid, is_enabled); -} - -void ResourceManager::EnableSixAxisSensor(u64 aruid, bool is_enabled) { - std::scoped_lock lock{shared_mutex}; - applet_resource->EnableSixAxisSensor(aruid, is_enabled); -} - -void ResourceManager::EnablePadInput(u64 aruid, bool is_enabled) { - std::scoped_lock lock{shared_mutex}; - applet_resource->EnablePadInput(aruid, is_enabled); -} - -void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) { - std::scoped_lock lock{shared_mutex}; - applet_resource->EnableTouchScreen(aruid, is_enabled); -} - -void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { - auto& core_timing = system.CoreTiming(); - debug_pad->OnUpdate(core_timing); - digitizer->OnUpdate(core_timing); - unique_pad->OnUpdate(core_timing); - gesture->OnUpdate(core_timing); - touch_screen->OnUpdate(core_timing); - palma->OnUpdate(core_timing); - home_button->OnUpdate(core_timing); - sleep_button->OnUpdate(core_timing); - capture_button->OnUpdate(core_timing); -} - -void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) { - auto& core_timing = system.CoreTiming(); - npad->OnUpdate(core_timing); -} - -void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) { - auto& core_timing = system.CoreTiming(); - mouse->OnUpdate(core_timing); - debug_mouse->OnUpdate(core_timing); - keyboard->OnUpdate(core_timing); -} - -void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) { - auto& core_timing = system.CoreTiming(); - six_axis->OnUpdate(core_timing); - seven_six_axis->OnUpdate(core_timing); - console_six_axis->OnUpdate(core_timing); -} - -IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, - u64 applet_resource_user_id) - : ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id}, - resource_manager{resource} { - static const FunctionInfo functions[] = { - {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, - }; - RegisterHandlers(functions); - - // Register update callbacks - npad_update_event = Core::Timing::CreateEvent( - "HID::UpdatePadCallback", - [this, resource]( - s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - const auto guard = LockService(); - resource->UpdateNpad(ns_late); - return std::nullopt; - }); - default_update_event = Core::Timing::CreateEvent( - "HID::UpdateDefaultCallback", - [this, resource]( - s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - const auto guard = LockService(); - resource->UpdateControllers(ns_late); - return std::nullopt; - }); - mouse_keyboard_update_event = Core::Timing::CreateEvent( - "HID::UpdateMouseKeyboardCallback", - [this, resource]( - s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - const auto guard = LockService(); - resource->UpdateMouseKeyboard(ns_late); - return std::nullopt; - }); - motion_update_event = Core::Timing::CreateEvent( - "HID::UpdateMotionCallback", - [this, resource]( - s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - const auto guard = LockService(); - resource->UpdateMotion(ns_late); - return std::nullopt; - }); - - system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event); - system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns, - default_update_event); - system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns, - mouse_keyboard_update_event); - system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns, - motion_update_event); -} - -IAppletResource::~IAppletResource() { - system.CoreTiming().UnscheduleEvent(npad_update_event); - system.CoreTiming().UnscheduleEvent(default_update_event); - system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event); - system.CoreTiming().UnscheduleEvent(motion_update_event); - resource_manager->FreeAppletResourceId(aruid); -} - -void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) { - Kernel::KSharedMemory* handle; - const auto result = resource_manager->GetSharedMemoryHandle(&handle, aruid); - - LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result=0x{:X}", aruid, result.raw); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(result); - rb.PushCopyObjects(handle); -} - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Core::Timing { -struct EventType; -} - -namespace Kernel { -class KSharedMemory; -} - -namespace Service::HID { -class AppletResource; -class CaptureButton; -class Controller_Stubbed; -class ConsoleSixAxis; -class DebugMouse; -class DebugPad; -class Digitizer; -class Gesture; -class HomeButton; -class Keyboard; -class Mouse; -class NPad; -class Palma; -class SevenSixAxis; -class SixAxis; -class SleepButton; -class TouchScreen; -class UniquePad; - -class ResourceManager { - -public: - explicit ResourceManager(Core::System& system_); - ~ResourceManager(); - - void Initialize(); - - std::shared_ptr<AppletResource> GetAppletResource() const; - std::shared_ptr<CaptureButton> GetCaptureButton() const; - std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const; - std::shared_ptr<DebugMouse> GetDebugMouse() const; - std::shared_ptr<DebugPad> GetDebugPad() const; - std::shared_ptr<Digitizer> GetDigitizer() const; - std::shared_ptr<Gesture> GetGesture() const; - std::shared_ptr<HomeButton> GetHomeButton() const; - std::shared_ptr<Keyboard> GetKeyboard() const; - std::shared_ptr<Mouse> GetMouse() const; - std::shared_ptr<NPad> GetNpad() const; - std::shared_ptr<Palma> GetPalma() const; - std::shared_ptr<SevenSixAxis> GetSevenSixAxis() const; - std::shared_ptr<SixAxis> GetSixAxis() const; - std::shared_ptr<SleepButton> GetSleepButton() const; - std::shared_ptr<TouchScreen> GetTouchScreen() const; - std::shared_ptr<UniquePad> GetUniquePad() const; - - Result CreateAppletResource(u64 aruid); - - Result RegisterCoreAppletResource(); - Result UnregisterCoreAppletResource(); - Result RegisterAppletResourceUserId(u64 aruid, bool bool_value); - void UnregisterAppletResourceUserId(u64 aruid); - - Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid); - void FreeAppletResourceId(u64 aruid); - - void EnableInput(u64 aruid, bool is_enabled); - void EnableSixAxisSensor(u64 aruid, bool is_enabled); - void EnablePadInput(u64 aruid, bool is_enabled); - void EnableTouchScreen(u64 aruid, bool is_enabled); - - void UpdateControllers(std::chrono::nanoseconds ns_late); - void UpdateNpad(std::chrono::nanoseconds ns_late); - void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); - void UpdateMotion(std::chrono::nanoseconds ns_late); - -private: - Result CreateAppletResourceImpl(u64 aruid); - void InitializeHidCommonSampler(); - void InitializeTouchScreenSampler(); - void InitializeConsoleSixAxisSampler(); - void InitializeAHidSampler(); - - bool is_initialized{false}; - - mutable std::recursive_mutex shared_mutex; - std::shared_ptr<AppletResource> applet_resource = nullptr; - - std::shared_ptr<CaptureButton> capture_button = nullptr; - std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr; - std::shared_ptr<DebugMouse> debug_mouse = nullptr; - std::shared_ptr<DebugPad> debug_pad = nullptr; - std::shared_ptr<Digitizer> digitizer = nullptr; - std::shared_ptr<Gesture> gesture = nullptr; - std::shared_ptr<HomeButton> home_button = nullptr; - std::shared_ptr<Keyboard> keyboard = nullptr; - std::shared_ptr<Mouse> mouse = nullptr; - std::shared_ptr<NPad> npad = nullptr; - std::shared_ptr<Palma> palma = nullptr; - std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr; - std::shared_ptr<SixAxis> six_axis = nullptr; - std::shared_ptr<SleepButton> sleep_button = nullptr; - std::shared_ptr<TouchScreen> touch_screen = nullptr; - std::shared_ptr<UniquePad> unique_pad = nullptr; - - // TODO: Create these resources - // std::shared_ptr<AudioControl> audio_control = nullptr; - // std::shared_ptr<ButtonConfig> button_config = nullptr; - // std::shared_ptr<Config> config = nullptr; - // std::shared_ptr<Connection> connection = nullptr; - // std::shared_ptr<CustomConfig> custom_config = nullptr; - // std::shared_ptr<Digitizer> digitizer = nullptr; - // std::shared_ptr<Hdls> hdls = nullptr; - // std::shared_ptr<PlayReport> play_report = nullptr; - // std::shared_ptr<Rail> rail = nullptr; - - Core::System& system; - KernelHelpers::ServiceContext service_context; -}; - -class IAppletResource final : public ServiceFramework<IAppletResource> { -public: - explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource, - u64 applet_resource_user_id); - ~IAppletResource() override; - -private: - void GetSharedMemoryHandle(HLERequestContext& ctx); - - std::shared_ptr<Core::Timing::EventType> npad_update_event; - std::shared_ptr<Core::Timing::EventType> default_update_event; - std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event; - std::shared_ptr<Core::Timing::EventType> motion_update_event; - - u64 aruid; - std::shared_ptr<ResourceManager> resource_manager; -}; - -} // 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 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> - -#include "common/common_types.h" - -namespace Service::HID { - -template <typename State> -struct AtomicStorage { - s64 sampling_number; - State state; -}; - -template <typename State, std::size_t max_buffer_size> -struct Lifo { - s64 timestamp{}; - s64 total_buffer_count = static_cast<s64>(max_buffer_size); - s64 buffer_tail{}; - s64 buffer_count{}; - std::array<AtomicStorage<State>, max_buffer_size> entries{}; - - const AtomicStorage<State>& ReadCurrentEntry() const { - return entries[buffer_tail]; - } - - const AtomicStorage<State>& ReadPreviousEntry() const { - return entries[GetPreviousEntryIndex()]; - } - - std::size_t GetPreviousEntryIndex() const { - return static_cast<size_t>((buffer_tail + max_buffer_size - 1) % max_buffer_size); - } - - std::size_t GetNextEntryIndex() const { - return static_cast<size_t>((buffer_tail + 1) % max_buffer_size); - } - - void WriteNextEntry(const State& new_state) { - if (buffer_count < static_cast<s64>(max_buffer_size) - 1) { - buffer_count++; - } - buffer_tail = GetNextEntryIndex(); - const auto& previous_entry = ReadPreviousEntry(); - entries[buffer_tail].sampling_number = previous_entry.sampling_number + 1; - entries[buffer_tail].state = new_state; - } -}; - -} // 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 @@ #include "common/string_util.h" #include "common/tiny_mt.h" #include "core/core.h" -#include "core/hid/emulated_controller.h" -#include "core/hid/hid_core.h" -#include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/mii/mii_manager.h" @@ -33,6 +30,9 @@ #include "core/hle/service/nfc/mifare_result.h" #include "core/hle/service/nfc/nfc_result.h" #include "core/hle/service/time/time_manager.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" +#include "hid_core/hid_types.h" namespace Service::NFC { 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 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" -#include "core/hle/service/hid/hid_util.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nfc/common/device.h" #include "core/hle/service/nfc/common/device_manager.h" #include "core/hle/service/nfc/nfc_result.h" #include "core/hle/service/time/clock_types.h" #include "core/hle/service/time/time_manager.h" +#include "hid_core/hid_types.h" +#include "hid_core/hid_util.h" namespace Service::NFC { 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 @@ #include <optional> #include <span> -#include "core/hid/hid_types.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nfc/mifare_types.h" #include "core/hle/service/nfc/nfc_types.h" #include "core/hle/service/nfp/nfp_types.h" #include "core/hle/service/service.h" #include "core/hle/service/time/clock_types.h" +#include "hid_core/hid_types.h" namespace Service::NFC { 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 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nfc/common/device.h" @@ -15,6 +14,7 @@ #include "core/hle/service/nfc/nfc_types.h" #include "core/hle/service/nfp/nfp_result.h" #include "core/hle/service/time/clock_types.h" +#include "hid_core/hid_types.h" namespace Service::NFC { 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 @@ #include "common/logging/log.h" #include "core/core.h" -#include "core/hid/hid_types.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/nfc/common/device.h" @@ -12,6 +11,7 @@ #include "core/hle/service/nfp/nfp_interface.h" #include "core/hle/service/nfp/nfp_result.h" #include "core/hle/service/nfp/nfp_types.h" +#include "hid_core/hid_types.h" namespace Service::NFP { 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 @@ #include "core/core_timing.h" #include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/k_process.h" -#include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/hid_server.h" -#include "core/hle/service/hid/resource_manager.h" #include "core/hle/service/sm/sm.h" #include "core/memory.h" #include "core/memory/cheat_engine.h" +#include "hid_core/resource_manager.h" +#include "hid_core/resources/npad/npad.h" namespace Core::Memory { namespace { |