yuzu-android/src/core/hid/emulated_controller.h

445 lines
15 KiB
C++
Raw Normal View History

// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2021-09-20 17:43:16 -07:00
#pragma once
#include <array>
2021-09-20 17:43:16 -07:00
#include <functional>
#include <memory>
2021-09-20 17:43:16 -07:00
#include <mutex>
#include <unordered_map>
#include "common/common_types.h"
2021-09-20 17:43:16 -07:00
#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 {
2021-10-24 21:23:54 -07:00
const std::size_t max_emulated_controllers = 2;
2021-09-20 17:43:16 -07:00
struct ControllerMotionInfo {
Common::Input::MotionStatus raw_status{};
2021-09-20 17:43:16 -07:00
MotionInput emulated{};
};
using ButtonDevices =
std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeButton::NumButtons>;
2021-09-20 17:43:16 -07:00
using StickDevices =
std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>;
2021-09-20 17:43:16 -07:00
using ControllerMotionDevices =
std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>;
2021-09-20 17:43:16 -07:00
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>;
2021-09-20 17:43:16 -07:00
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>;
2021-10-24 21:23:54 -07:00
using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>;
using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>;
2021-09-20 17:43:16 -07:00
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>;
2021-09-20 17:43:16 -07:00
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>;
2021-09-20 17:43:16 -07:00
struct AnalogSticks {
2021-10-22 21:04:06 -07:00
AnalogStickState left{};
AnalogStickState right{};
2021-09-20 17:43:16 -07:00
};
struct ControllerColors {
2021-10-22 21:04:06 -07:00
NpadControllerColor fullkey{};
NpadControllerColor left{};
NpadControllerColor right{};
2021-09-20 17:43:16 -07:00
};
struct BatteryLevelState {
2021-10-22 21:04:06 -07:00
NpadPowerInfo dual{};
NpadPowerInfo left{};
NpadPowerInfo right{};
2021-09-20 17:43:16 -07:00
};
struct ControllerMotion {
Common::Vec3f accel{};
Common::Vec3f gyro{};
Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{};
2021-10-22 21:04:06 -07:00
bool is_at_rest{};
2021-09-20 17:43:16 -07:00
};
enum EmulatedDeviceIndex : u8 {
2021-10-24 21:23:54 -07:00
LeftIndex,
RightIndex,
DualIndex,
AllDevices,
};
2021-09-20 17:43:16 -07:00
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{};
2021-10-16 22:33:00 -07:00
// Data for HID serices
HomeButtonState home_button_state{};
CaptureButtonState capture_button_state{};
2021-09-20 17:43:16 -07:00
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{};
};
2021-10-10 22:43:11 -07:00
2021-09-20 17:43:16 -07:00
enum class ControllerTriggerType {
Button,
Stick,
Trigger,
Motion,
Color,
Battery,
Vibration,
Connected,
Disconnected,
Type,
All,
};
struct ControllerUpdateCallback {
std::function<void(ControllerTriggerType)> on_change;
2021-10-22 21:04:06 -07:00
bool is_npad_service;
2021-09-20 17:43:16 -07:00
};
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
2021-09-20 17:43:16 -07:00
*/
explicit EmulatedController(NpadIdType npad_id_type_);
~EmulatedController();
YUZU_NON_COPYABLE(EmulatedController);
YUZU_NON_MOVEABLE(EmulatedController);
2021-10-16 22:33:00 -07:00
/// Converts the controller type from settings to npad type
static NpadStyleIndex MapSettingsTypeToNPad(Settings::ControllerType type);
2021-10-16 22:33:00 -07:00
/// Converts npad type to the equivalent of controller type from settings
static Settings::ControllerType MapNPadToSettingsType(NpadStyleIndex type);
2021-09-20 17:43:16 -07:00
2021-10-16 22:33:00 -07:00
/// Gets the NpadIdType for this controller
2021-09-20 17:43:16 -07:00
NpadIdType GetNpadIdType() const;
/// Sets the NpadStyleIndex for this controller
void SetNpadStyleIndex(NpadStyleIndex npad_type_);
2021-09-20 17:43:16 -07:00
/**
* 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;
2021-09-20 17:43:16 -07:00
/**
* 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);
2021-10-16 22:33:00 -07:00
/// Sets the connected status to false
2021-09-20 17:43:16 -07:00
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;
2021-10-16 22:33:00 -07:00
/// Returns true if vibration is enabled
2021-09-20 17:43:16 -07:00
bool IsVibrationEnabled() const;
2021-10-16 22:33:00 -07:00
/// Removes all callbacks created from input devices
2021-09-20 17:43:16 -07:00
void UnloadInput();
/**
* Sets the emulated controller into configuring mode
* This prevents the modification of the HID state of the emulated controller by input commands
*/
2021-09-20 17:43:16 -07:00
void EnableConfiguration();
2021-10-16 22:33:00 -07:00
/// Returns the emulated controller into normal mode, allowing the modification of the HID state
2021-09-20 17:43:16 -07:00
void DisableConfiguration();
2021-10-16 22:33:00 -07:00
2021-11-15 15:57:41 -08:00
/// 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
2021-09-20 17:43:16 -07:00
bool IsConfiguring() const;
2021-10-16 22:33:00 -07:00
/// 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
2021-09-20 17:43:16 -07:00
void SaveCurrentConfig();
2021-10-16 22:33:00 -07:00
/// Reverts any mapped changes made that weren't saved
2021-09-20 17:43:16 -07:00
void RestoreConfig();
2021-10-16 22:33:00 -07:00
/// Returns a vector of mapped devices from the mapped button and stick parameters
std::vector<Common::ParamPackage> GetMappedDevices(EmulatedDeviceIndex device_index) const;
2021-09-20 17:43:16 -07:00
2021-10-16 22:33:00 -07:00
// Returns the current mapped button device
2021-09-20 17:43:16 -07:00
Common::ParamPackage GetButtonParam(std::size_t index) const;
2021-10-16 22:33:00 -07:00
// Returns the current mapped stick device
2021-09-20 17:43:16 -07:00
Common::ParamPackage GetStickParam(std::size_t index) const;
2021-10-16 22:33:00 -07:00
// Returns the current mapped motion device
2021-09-20 17:43:16 -07:00
Common::ParamPackage GetMotionParam(std::size_t index) const;
2021-10-16 22:33:00 -07:00
/**
* Updates the current mapped button device
* @param param ParamPackage with controller data to be mapped
2021-10-16 22:33:00 -07:00
*/
2021-09-20 17:43:16 -07:00
void SetButtonParam(std::size_t index, Common::ParamPackage param);
2021-10-16 22:33:00 -07:00
/**
* Updates the current mapped stick device
* @param param ParamPackage with controller data to be mapped
2021-10-16 22:33:00 -07:00
*/
2021-09-20 17:43:16 -07:00
void SetStickParam(std::size_t index, Common::ParamPackage param);
2021-10-16 22:33:00 -07:00
/**
* Updates the current mapped motion device
* @param param ParamPackage with controller data to be mapped
2021-10-16 22:33:00 -07:00
*/
2021-09-20 17:43:16 -07:00
void SetMotionParam(std::size_t index, Common::ParamPackage param);
2021-10-16 22:33:00 -07:00
/// Returns the latest button status from the controller with parameters
2021-09-20 17:43:16 -07:00
ButtonValues GetButtonsValues() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest analog stick status from the controller with parameters
2021-09-20 17:43:16 -07:00
SticksValues GetSticksValues() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest trigger status from the controller with parameters
2021-09-20 17:43:16 -07:00
TriggerValues GetTriggersValues() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest motion status from the controller with parameters
2021-09-20 17:43:16 -07:00
ControllerMotionValues GetMotionValues() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest color status from the controller with parameters
2021-09-20 17:43:16 -07:00
ColorValues GetColorsValues() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest battery status from the controller with parameters
2021-09-20 17:43:16 -07:00
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
2021-09-20 17:43:16 -07:00
NpadButtonState GetNpadButtons() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest status of button input for the debug pad service
2021-09-20 17:43:16 -07:00
DebugPadButton GetDebugPadButtons() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest status of stick input from the mouse
2021-09-20 17:43:16 -07:00
AnalogSticks GetSticks() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest status of trigger input from the mouse
2021-09-20 17:43:16 -07:00
NpadGcTriggerState GetTriggers() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest status of motion input from the mouse
2021-09-20 17:43:16 -07:00
MotionState GetMotions() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest color value from the controller
2021-09-20 17:43:16 -07:00
ControllerColors GetColors() const;
2021-10-16 22:33:00 -07:00
/// Returns the latest battery status from the controller
2021-09-20 17:43:16 -07:00
BatteryLevelState GetBattery() const;
/**
2021-10-16 22:33:00 -07:00
* Sends a specific vibration to the output device
2022-02-10 08:58:37 -08:00
* @return true if vibration had no errors
2021-10-16 22:33:00 -07:00
*/
2021-09-20 17:43:16 -07:00
bool SetVibration(std::size_t device_index, VibrationValue vibration);
2021-10-16 22:33:00 -07:00
/**
2021-10-16 22:33:00 -07:00
* Sends a small vibration to the output device
2022-02-10 08:58:37 -08:00
* @return true if SetVibration was successfull
2021-10-16 22:33:00 -07:00
*/
2021-10-10 22:43:11 -07:00
bool TestVibration(std::size_t device_index);
2022-02-10 08:58:37 -08:00
/**
* 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
*/
2021-06-16 20:09:38 -07:00
bool SetPollingMode(Common::Input::PollingMode polling_mode);
2021-10-16 22:33:00 -07:00
/// Returns the led pattern corresponding to this emulated controller
LedPattern GetLedPattern() const;
/// Asks the output device to change the player led pattern
2021-10-10 22:43:11 -07:00
void SetLedPattern();
2021-09-20 17:43:16 -07:00
2021-10-16 22:33:00 -07:00
/**
* Adds a callback to the list of events
* @param update_callback A ConsoleUpdateCallback that will be triggered
2021-10-16 22:33:00 -07:00
* @return an unique key corresponding to the callback index in the list
*/
2021-09-20 17:43:16 -07:00
int SetCallback(ControllerUpdateCallback update_callback);
2021-10-16 22:33:00 -07:00
/**
* Removes a callback from the list stopping any future events to this object
* @param key Key corresponding to the callback index in the list
2021-10-16 22:33:00 -07:00
*/
2021-09-20 17:43:16 -07:00
void DeleteCallback(int key);
private:
2021-10-24 21:23:54 -07:00
/// creates input devices from params
void LoadDevices();
2021-10-26 22:20:28 -07:00
/// 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;
2021-09-20 17:43:16 -07:00
/**
2021-10-16 22:33:00 -07:00
* Updates the button status of the controller
* @param callback A CallbackStatus containing the button status
* @param index Button ID of the to be updated
2021-09-20 17:43:16 -07:00
*/
void SetButton(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid);
2021-10-16 22:33:00 -07:00
/**
* 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
2021-10-16 22:33:00 -07:00
*/
void SetStick(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid);
2021-10-16 22:33:00 -07:00
/**
* Updates the trigger status of the controller
* @param callback A CallbackStatus containing the trigger status
* @param index trigger ID of the to be updated
2021-10-16 22:33:00 -07:00
*/
void SetTrigger(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid);
2021-10-16 22:33:00 -07:00
/**
* 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
2021-10-16 22:33:00 -07:00
*/
void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index);
2021-10-16 22:33:00 -07:00
/**
* Updates the battery status of the controller
* @param callback A CallbackStatus containing the battery status
* @param index Button ID of the to be updated
2021-10-16 22:33:00 -07:00
*/
void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index);
2021-09-20 17:43:16 -07:00
/**
2021-10-16 22:33:00 -07:00
* 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
2021-09-20 17:43:16 -07:00
*/
void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
2021-09-20 17:43:16 -07:00
const NpadIdType npad_id_type;
NpadStyleIndex npad_type{NpadStyleIndex::None};
NpadStyleTag supported_style_tag{NpadStyleSet::All};
2021-09-20 17:43:16 -07:00
bool is_connected{false};
bool is_configuring{false};
2021-11-15 15:57:41 -08:00
bool system_buttons_enabled{true};
2021-09-20 17:43:16 -07:00
f32 motion_sensitivity{0.01f};
bool force_update_motion{false};
2021-09-20 17:43:16 -07:00
// Temporary values to avoid doing changes while the controller is in configuring mode
NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
bool tmp_is_connected{false};
2021-09-20 17:43:16 -07:00
ButtonParams button_params;
StickParams stick_params;
ControllerMotionParams motion_params;
TriggerParams trigger_params;
BatteryParams battery_params;
2021-10-10 22:43:11 -07:00
OutputParams output_params;
2021-09-20 17:43:16 -07:00
ButtonDevices button_devices;
StickDevices stick_devices;
ControllerMotionDevices motion_devices;
TriggerDevices trigger_devices;
BatteryDevices battery_devices;
2021-10-10 22:43:11 -07:00
OutputDevices output_devices;
2021-09-20 17:43:16 -07:00
2021-10-26 22:20:28 -07:00
// TAS related variables
ButtonParams tas_button_params;
StickParams tas_stick_params;
ButtonDevices tas_button_devices;
StickDevices tas_stick_devices;
2021-09-20 17:43:16 -07:00
mutable std::mutex mutex;
mutable std::mutex callback_mutex;
2021-09-20 17:43:16 -07:00
std::unordered_map<int, ControllerUpdateCallback> callback_list;
int last_callback_key = 0;
2021-10-16 22:33:00 -07:00
// Stores the current status of all controller input
2021-09-20 17:43:16 -07:00
ControllerStatus controller;
};
} // namespace Core::HID