446 lines
15 KiB
C++
446 lines
15 KiB
C++
// Copyright 2021 yuzu Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <unordered_map>
|
|
|
|
#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/motion_input.h"
|
|
|
|
namespace Core::HID {
|
|
const std::size_t max_emulated_controllers = 2;
|
|
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 BatteryDevices =
|
|
std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
|
|
using OutputDevices =
|
|
std::array<std::unique_ptr<Common::Input::OutputDevice>, max_emulated_controllers>;
|
|
|
|
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 BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>;
|
|
using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>;
|
|
|
|
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 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 ControllerMotion {
|
|
Common::Vec3f accel{};
|
|
Common::Vec3f gyro{};
|
|
Common::Vec3f rotation{};
|
|
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{};
|
|
|
|
// Data for HID serices
|
|
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{};
|
|
};
|
|
|
|
enum class ControllerTriggerType {
|
|
Button,
|
|
Stick,
|
|
Trigger,
|
|
Motion,
|
|
Color,
|
|
Battery,
|
|
Vibration,
|
|
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;
|
|
|
|
/// Returns true if vibration is enabled
|
|
bool IsVibrationEnabled() 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();
|
|
|
|
/// 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(EmulatedDeviceIndex device_index) 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);
|
|
|
|
/// 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 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;
|
|
|
|
/**
|
|
* 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 successfull
|
|
*/
|
|
bool TestVibration(std::size_t device_index);
|
|
|
|
/**
|
|
* Sets the desired data to be polled from a controller
|
|
* @param polling_mode type of input desired buttons, gyro, nfc, ir, etc.
|
|
* @return true if SetPollingMode was successfull
|
|
*/
|
|
bool SetPollingMode(Common::Input::PollingMode polling_mode);
|
|
|
|
/// Returns the led pattern corresponding to this emulated controller
|
|
LedPattern GetLedPattern() const;
|
|
|
|
/// Asks the output device to change the player led pattern
|
|
void SetLedPattern();
|
|
|
|
/**
|
|
* 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);
|
|
|
|
private:
|
|
/// creates input devices from params
|
|
void LoadDevices();
|
|
|
|
/// Set the params for TAS devices
|
|
void LoadTASParams();
|
|
|
|
/**
|
|
* @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 battery status of the controller
|
|
* @param callback A CallbackStatus containing the battery status
|
|
* @param index Button ID of the to be updated
|
|
*/
|
|
void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index);
|
|
|
|
/**
|
|
* 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);
|
|
|
|
const NpadIdType npad_id_type;
|
|
NpadStyleIndex npad_type{NpadStyleIndex::None};
|
|
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
|
bool is_connected{false};
|
|
bool is_configuring{false};
|
|
bool system_buttons_enabled{true};
|
|
f32 motion_sensitivity{0.01f};
|
|
bool force_update_motion{false};
|
|
|
|
// 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;
|
|
OutputParams output_params;
|
|
|
|
ButtonDevices button_devices;
|
|
StickDevices stick_devices;
|
|
ControllerMotionDevices motion_devices;
|
|
TriggerDevices trigger_devices;
|
|
BatteryDevices battery_devices;
|
|
OutputDevices output_devices;
|
|
|
|
// TAS related variables
|
|
ButtonParams tas_button_params;
|
|
StickParams tas_stick_params;
|
|
ButtonDevices tas_button_devices;
|
|
StickDevices tas_stick_devices;
|
|
|
|
mutable std::mutex mutex;
|
|
mutable std::mutex callback_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
|