From ee847f8ff0b1b0aec39c1b78c010bc0c08a0a613 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 4 Jan 2024 20:37:43 -0600 Subject: hid_core: Move hid to it's own subproject --- src/hid_core/frontend/emulated_controller.h | 619 ++++++++++++++++++++++++++++ 1 file changed, 619 insertions(+) create mode 100644 src/hid_core/frontend/emulated_controller.h (limited to 'src/hid_core/frontend/emulated_controller.h') diff --git a/src/hid_core/frontend/emulated_controller.h b/src/hid_core/frontend/emulated_controller.h new file mode 100644 index 000000000..94798164d --- /dev/null +++ b/src/hid_core/frontend/emulated_controller.h @@ -0,0 +1,619 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "common/common_types.h" +#include "common/input.h" +#include "common/param_package.h" +#include "common/settings.h" +#include "common/vector_math.h" +#include "hid_core/frontend/motion_input.h" +#include "hid_core/hid_types.h" +#include "hid_core/irsensor/irs_types.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, Settings::NativeButton::NumButtons>; +using StickDevices = + std::array, Settings::NativeAnalog::NumAnalogs>; +using ControllerMotionDevices = + std::array, Settings::NativeMotion::NumMotions>; +using TriggerDevices = + std::array, Settings::NativeTrigger::NumTriggers>; +using ColorDevices = + std::array, max_emulated_controllers>; +using BatteryDevices = + std::array, max_emulated_controllers>; +using CameraDevices = + std::array, max_emulated_controllers>; +using RingAnalogDevices = + std::array, max_emulated_controllers>; +using NfcDevices = + std::array, max_emulated_controllers>; +using OutputDevices = std::array, output_devices_size>; + +using ButtonParams = std::array; +using StickParams = std::array; +using ControllerMotionParams = std::array; +using TriggerParams = std::array; +using ColorParams = std::array; +using BatteryParams = std::array; +using CameraParams = std::array; +using RingAnalogParams = std::array; +using NfcParams = std::array; +using OutputParams = std::array; + +using ButtonValues = std::array; +using SticksValues = std::array; +using TriggerValues = + std::array; +using ControllerMotionValues = std::array; +using ColorValues = std::array; +using BatteryValues = std::array; +using CameraValues = Common::Input::CameraStatus; +using RingAnalogValue = Common::Input::AnalogStatus; +using NfcValues = Common::Input::NfcStatus; +using VibrationValues = std::array; + +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 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 orientation{}; + bool is_at_rest{}; +}; + +enum EmulatedDeviceIndex : u8 { + LeftIndex, + RightIndex, + DualIndex, + AllDevices, +}; + +using MotionState = std::array; + +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 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 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& data); + + /// Returns true if the nfc tag was written + bool WriteNfc(const std::vector& 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 callback_list; + int last_callback_key = 0; + + // Stores the current status of all controller input + ControllerStatus controller; +}; + +} // namespace Core::HID -- cgit v1.2.3