diff options
Diffstat (limited to 'src/core/hid/emulated_controller.h')
| -rw-r--r-- | src/core/hid/emulated_controller.h | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h new file mode 100644 index 000000000..e42aafebc --- /dev/null +++ b/src/core/hid/emulated_controller.h | |||
| @@ -0,0 +1,411 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <functional> | ||
| 9 | #include <memory> | ||
| 10 | #include <mutex> | ||
| 11 | #include <unordered_map> | ||
| 12 | |||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "common/input.h" | ||
| 15 | #include "common/param_package.h" | ||
| 16 | #include "common/point.h" | ||
| 17 | #include "common/quaternion.h" | ||
| 18 | #include "common/settings.h" | ||
| 19 | #include "common/vector_math.h" | ||
| 20 | #include "core/hid/hid_types.h" | ||
| 21 | #include "core/hid/motion_input.h" | ||
| 22 | |||
| 23 | namespace Core::HID { | ||
| 24 | const std::size_t max_emulated_controllers = 2; | ||
| 25 | struct ControllerMotionInfo { | ||
| 26 | Common::Input::MotionStatus raw_status{}; | ||
| 27 | MotionInput emulated{}; | ||
| 28 | }; | ||
| 29 | |||
| 30 | using ButtonDevices = | ||
| 31 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeButton::NumButtons>; | ||
| 32 | using StickDevices = | ||
| 33 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>; | ||
| 34 | using ControllerMotionDevices = | ||
| 35 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>; | ||
| 36 | using TriggerDevices = | ||
| 37 | std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>; | ||
| 38 | using BatteryDevices = | ||
| 39 | std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; | ||
| 40 | using OutputDevices = | ||
| 41 | std::array<std::unique_ptr<Common::Input::OutputDevice>, max_emulated_controllers>; | ||
| 42 | |||
| 43 | using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>; | ||
| 44 | using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>; | ||
| 45 | using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>; | ||
| 46 | using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>; | ||
| 47 | using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>; | ||
| 48 | using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>; | ||
| 49 | |||
| 50 | using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>; | ||
| 51 | using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>; | ||
| 52 | using TriggerValues = | ||
| 53 | std::array<Common::Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>; | ||
| 54 | using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>; | ||
| 55 | using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>; | ||
| 56 | using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>; | ||
| 57 | using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>; | ||
| 58 | |||
| 59 | struct AnalogSticks { | ||
| 60 | AnalogStickState left{}; | ||
| 61 | AnalogStickState right{}; | ||
| 62 | }; | ||
| 63 | |||
| 64 | struct ControllerColors { | ||
| 65 | NpadControllerColor fullkey{}; | ||
| 66 | NpadControllerColor left{}; | ||
| 67 | NpadControllerColor right{}; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct BatteryLevelState { | ||
| 71 | NpadPowerInfo dual{}; | ||
| 72 | NpadPowerInfo left{}; | ||
| 73 | NpadPowerInfo right{}; | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct ControllerMotion { | ||
| 77 | Common::Vec3f accel{}; | ||
| 78 | Common::Vec3f gyro{}; | ||
| 79 | Common::Vec3f rotation{}; | ||
| 80 | std::array<Common::Vec3f, 3> orientation{}; | ||
| 81 | bool is_at_rest{}; | ||
| 82 | }; | ||
| 83 | |||
| 84 | enum EmulatedDeviceIndex : u8 { | ||
| 85 | LeftIndex, | ||
| 86 | RightIndex, | ||
| 87 | DualIndex, | ||
| 88 | AllDevices, | ||
| 89 | }; | ||
| 90 | |||
| 91 | using MotionState = std::array<ControllerMotion, 2>; | ||
| 92 | |||
| 93 | struct ControllerStatus { | ||
| 94 | // Data from input_common | ||
| 95 | ButtonValues button_values{}; | ||
| 96 | SticksValues stick_values{}; | ||
| 97 | ControllerMotionValues motion_values{}; | ||
| 98 | TriggerValues trigger_values{}; | ||
| 99 | ColorValues color_values{}; | ||
| 100 | BatteryValues battery_values{}; | ||
| 101 | VibrationValues vibration_values{}; | ||
| 102 | |||
| 103 | // Data for HID serices | ||
| 104 | NpadButtonState npad_button_state{}; | ||
| 105 | DebugPadButton debug_pad_button_state{}; | ||
| 106 | AnalogSticks analog_stick_state{}; | ||
| 107 | MotionState motion_state{}; | ||
| 108 | NpadGcTriggerState gc_trigger_state{}; | ||
| 109 | ControllerColors colors_state{}; | ||
| 110 | BatteryLevelState battery_state{}; | ||
| 111 | }; | ||
| 112 | |||
| 113 | enum class ControllerTriggerType { | ||
| 114 | Button, | ||
| 115 | Stick, | ||
| 116 | Trigger, | ||
| 117 | Motion, | ||
| 118 | Color, | ||
| 119 | Battery, | ||
| 120 | Vibration, | ||
| 121 | Connected, | ||
| 122 | Disconnected, | ||
| 123 | Type, | ||
| 124 | All, | ||
| 125 | }; | ||
| 126 | |||
| 127 | struct ControllerUpdateCallback { | ||
| 128 | std::function<void(ControllerTriggerType)> on_change; | ||
| 129 | bool is_npad_service; | ||
| 130 | }; | ||
| 131 | |||
| 132 | class EmulatedController { | ||
| 133 | public: | ||
| 134 | /** | ||
| 135 | * Contains all input data (buttons, joysticks, vibration, and motion) within this controller. | ||
| 136 | * @param npad_id_type npad id type for this specific controller | ||
| 137 | */ | ||
| 138 | explicit EmulatedController(NpadIdType npad_id_type_); | ||
| 139 | ~EmulatedController(); | ||
| 140 | |||
| 141 | YUZU_NON_COPYABLE(EmulatedController); | ||
| 142 | YUZU_NON_MOVEABLE(EmulatedController); | ||
| 143 | |||
| 144 | /// Converts the controller type from settings to npad type | ||
| 145 | static NpadStyleIndex MapSettingsTypeToNPad(Settings::ControllerType type); | ||
| 146 | |||
| 147 | /// Converts npad type to the equivalent of controller type from settings | ||
| 148 | static Settings::ControllerType MapNPadToSettingsType(NpadStyleIndex type); | ||
| 149 | |||
| 150 | /// Gets the NpadIdType for this controller | ||
| 151 | NpadIdType GetNpadIdType() const; | ||
| 152 | |||
| 153 | /// Sets the NpadStyleIndex for this controller | ||
| 154 | void SetNpadStyleIndex(NpadStyleIndex npad_type_); | ||
| 155 | |||
| 156 | /** | ||
| 157 | * Gets the NpadStyleIndex for this controller | ||
| 158 | * @param get_temporary_value If true tmp_npad_type will be returned | ||
| 159 | * @return NpadStyleIndex set on the controller | ||
| 160 | */ | ||
| 161 | NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Sets the supported controller types. Disconnects the controller if current type is not | ||
| 165 | * supported | ||
| 166 | * @param supported_styles bitflag with supported types | ||
| 167 | */ | ||
| 168 | void SetSupportedNpadStyleTag(NpadStyleTag supported_styles); | ||
| 169 | |||
| 170 | /// Sets the connected status to true | ||
| 171 | void Connect(); | ||
| 172 | |||
| 173 | /// Sets the connected status to false | ||
| 174 | void Disconnect(); | ||
| 175 | |||
| 176 | /** | ||
| 177 | * Is the emulated connected | ||
| 178 | * @param get_temporary_value If true tmp_is_connected will be returned | ||
| 179 | * @return true if the controller has the connected status | ||
| 180 | */ | ||
| 181 | bool IsConnected(bool get_temporary_value = false) const; | ||
| 182 | |||
| 183 | /// Returns true if vibration is enabled | ||
| 184 | bool IsVibrationEnabled() const; | ||
| 185 | |||
| 186 | /// Removes all callbacks created from input devices | ||
| 187 | void UnloadInput(); | ||
| 188 | |||
| 189 | /** | ||
| 190 | * Sets the emulated controller into configuring mode | ||
| 191 | * This prevents the modification of the HID state of the emulated controller by input commands | ||
| 192 | */ | ||
| 193 | void EnableConfiguration(); | ||
| 194 | |||
| 195 | /// Returns the emulated controller into normal mode, allowing the modification of the HID state | ||
| 196 | void DisableConfiguration(); | ||
| 197 | |||
| 198 | /// Returns true if the emulated controller is in configuring mode | ||
| 199 | bool IsConfiguring() const; | ||
| 200 | |||
| 201 | /// Reload all input devices | ||
| 202 | void ReloadInput(); | ||
| 203 | |||
| 204 | /// Overrides current mapped devices with the stored configuration and reloads all input devices | ||
| 205 | void ReloadFromSettings(); | ||
| 206 | |||
| 207 | /// Saves the current mapped configuration | ||
| 208 | void SaveCurrentConfig(); | ||
| 209 | |||
| 210 | /// Reverts any mapped changes made that weren't saved | ||
| 211 | void RestoreConfig(); | ||
| 212 | |||
| 213 | /// Returns a vector of mapped devices from the mapped button and stick parameters | ||
| 214 | std::vector<Common::ParamPackage> GetMappedDevices(EmulatedDeviceIndex device_index) const; | ||
| 215 | |||
| 216 | // Returns the current mapped button device | ||
| 217 | Common::ParamPackage GetButtonParam(std::size_t index) const; | ||
| 218 | |||
| 219 | // Returns the current mapped stick device | ||
| 220 | Common::ParamPackage GetStickParam(std::size_t index) const; | ||
| 221 | |||
| 222 | // Returns the current mapped motion device | ||
| 223 | Common::ParamPackage GetMotionParam(std::size_t index) const; | ||
| 224 | |||
| 225 | /** | ||
| 226 | * Updates the current mapped button device | ||
| 227 | * @param param ParamPackage with controller data to be mapped | ||
| 228 | */ | ||
| 229 | void SetButtonParam(std::size_t index, Common::ParamPackage param); | ||
| 230 | |||
| 231 | /** | ||
| 232 | * Updates the current mapped stick device | ||
| 233 | * @param param ParamPackage with controller data to be mapped | ||
| 234 | */ | ||
| 235 | void SetStickParam(std::size_t index, Common::ParamPackage param); | ||
| 236 | |||
| 237 | /** | ||
| 238 | * Updates the current mapped motion device | ||
| 239 | * @param param ParamPackage with controller data to be mapped | ||
| 240 | */ | ||
| 241 | void SetMotionParam(std::size_t index, Common::ParamPackage param); | ||
| 242 | |||
| 243 | /// Returns the latest button status from the controller with parameters | ||
| 244 | ButtonValues GetButtonsValues() const; | ||
| 245 | |||
| 246 | /// Returns the latest analog stick status from the controller with parameters | ||
| 247 | SticksValues GetSticksValues() const; | ||
| 248 | |||
| 249 | /// Returns the latest trigger status from the controller with parameters | ||
| 250 | TriggerValues GetTriggersValues() const; | ||
| 251 | |||
| 252 | /// Returns the latest motion status from the controller with parameters | ||
| 253 | ControllerMotionValues GetMotionValues() const; | ||
| 254 | |||
| 255 | /// Returns the latest color status from the controller with parameters | ||
| 256 | ColorValues GetColorsValues() const; | ||
| 257 | |||
| 258 | /// Returns the latest battery status from the controller with parameters | ||
| 259 | BatteryValues GetBatteryValues() const; | ||
| 260 | |||
| 261 | /// Returns the latest status of button input for the npad service | ||
| 262 | NpadButtonState GetNpadButtons() const; | ||
| 263 | |||
| 264 | /// Returns the latest status of button input for the debug pad service | ||
| 265 | DebugPadButton GetDebugPadButtons() const; | ||
| 266 | |||
| 267 | /// Returns the latest status of stick input from the mouse | ||
| 268 | AnalogSticks GetSticks() const; | ||
| 269 | |||
| 270 | /// Returns the latest status of trigger input from the mouse | ||
| 271 | NpadGcTriggerState GetTriggers() const; | ||
| 272 | |||
| 273 | /// Returns the latest status of motion input from the mouse | ||
| 274 | MotionState GetMotions() const; | ||
| 275 | |||
| 276 | /// Returns the latest color value from the controller | ||
| 277 | ControllerColors GetColors() const; | ||
| 278 | |||
| 279 | /// Returns the latest battery status from the controller | ||
| 280 | BatteryLevelState GetBattery() const; | ||
| 281 | |||
| 282 | /** | ||
| 283 | * Sends a specific vibration to the output device | ||
| 284 | * @return returns true if vibration had no errors | ||
| 285 | */ | ||
| 286 | bool SetVibration(std::size_t device_index, VibrationValue vibration); | ||
| 287 | |||
| 288 | /** | ||
| 289 | * Sends a small vibration to the output device | ||
| 290 | * @return returns true if SetVibration was successfull | ||
| 291 | */ | ||
| 292 | bool TestVibration(std::size_t device_index); | ||
| 293 | |||
| 294 | /// Returns the led pattern corresponding to this emulated controller | ||
| 295 | LedPattern GetLedPattern() const; | ||
| 296 | |||
| 297 | /// Asks the output device to change the player led pattern | ||
| 298 | void SetLedPattern(); | ||
| 299 | |||
| 300 | /** | ||
| 301 | * Adds a callback to the list of events | ||
| 302 | * @param update_callback A ConsoleUpdateCallback that will be triggered | ||
| 303 | * @return an unique key corresponding to the callback index in the list | ||
| 304 | */ | ||
| 305 | int SetCallback(ControllerUpdateCallback update_callback); | ||
| 306 | |||
| 307 | /** | ||
| 308 | * Removes a callback from the list stopping any future events to this object | ||
| 309 | * @param key Key corresponding to the callback index in the list | ||
| 310 | */ | ||
| 311 | void DeleteCallback(int key); | ||
| 312 | |||
| 313 | private: | ||
| 314 | /// creates input devices from params | ||
| 315 | void LoadDevices(); | ||
| 316 | |||
| 317 | /// Set the params for TAS devices | ||
| 318 | void LoadTASParams(); | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Checks the current controller type against the supported_style_tag | ||
| 322 | * @return true if the controller is supported | ||
| 323 | */ | ||
| 324 | bool IsControllerSupported() const; | ||
| 325 | |||
| 326 | /** | ||
| 327 | * Updates the button status of the controller | ||
| 328 | * @param callback A CallbackStatus containing the button status | ||
| 329 | * @param index Button ID of the to be updated | ||
| 330 | */ | ||
| 331 | void SetButton(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 332 | Common::UUID uuid); | ||
| 333 | |||
| 334 | /** | ||
| 335 | * Updates the analog stick status of the controller | ||
| 336 | * @param callback A CallbackStatus containing the analog stick status | ||
| 337 | * @param index stick ID of the to be updated | ||
| 338 | */ | ||
| 339 | void SetStick(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 340 | Common::UUID uuid); | ||
| 341 | |||
| 342 | /** | ||
| 343 | * Updates the trigger status of the controller | ||
| 344 | * @param callback A CallbackStatus containing the trigger status | ||
| 345 | * @param index trigger ID of the to be updated | ||
| 346 | */ | ||
| 347 | void SetTrigger(const Common::Input::CallbackStatus& callback, std::size_t index, | ||
| 348 | Common::UUID uuid); | ||
| 349 | |||
| 350 | /** | ||
| 351 | * Updates the motion status of the controller | ||
| 352 | * @param callback A CallbackStatus containing gyro and accelerometer data | ||
| 353 | * @param index motion ID of the to be updated | ||
| 354 | */ | ||
| 355 | void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 356 | |||
| 357 | /** | ||
| 358 | * Updates the battery status of the controller | ||
| 359 | * @param callback A CallbackStatus containing the battery status | ||
| 360 | * @param index Button ID of the to be updated | ||
| 361 | */ | ||
| 362 | void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index); | ||
| 363 | |||
| 364 | /** | ||
| 365 | * Triggers a callback that something has changed on the controller status | ||
| 366 | * @param type Input type of the event to trigger | ||
| 367 | * @param is_service_update indicates if this event should only be sent to HID services | ||
| 368 | */ | ||
| 369 | void TriggerOnChange(ControllerTriggerType type, bool is_service_update); | ||
| 370 | |||
| 371 | NpadIdType npad_id_type; | ||
| 372 | NpadStyleIndex npad_type{NpadStyleIndex::None}; | ||
| 373 | NpadStyleTag supported_style_tag{NpadStyleSet::All}; | ||
| 374 | bool is_connected{false}; | ||
| 375 | bool is_configuring{false}; | ||
| 376 | f32 motion_sensitivity{0.01f}; | ||
| 377 | bool force_update_motion{false}; | ||
| 378 | |||
| 379 | // Temporary values to avoid doing changes while the controller is in configuring mode | ||
| 380 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; | ||
| 381 | bool tmp_is_connected{false}; | ||
| 382 | |||
| 383 | ButtonParams button_params; | ||
| 384 | StickParams stick_params; | ||
| 385 | ControllerMotionParams motion_params; | ||
| 386 | TriggerParams trigger_params; | ||
| 387 | BatteryParams battery_params; | ||
| 388 | OutputParams output_params; | ||
| 389 | |||
| 390 | ButtonDevices button_devices; | ||
| 391 | StickDevices stick_devices; | ||
| 392 | ControllerMotionDevices motion_devices; | ||
| 393 | TriggerDevices trigger_devices; | ||
| 394 | BatteryDevices battery_devices; | ||
| 395 | OutputDevices output_devices; | ||
| 396 | |||
| 397 | // TAS related variables | ||
| 398 | ButtonParams tas_button_params; | ||
| 399 | StickParams tas_stick_params; | ||
| 400 | ButtonDevices tas_button_devices; | ||
| 401 | StickDevices tas_stick_devices; | ||
| 402 | |||
| 403 | mutable std::mutex mutex; | ||
| 404 | std::unordered_map<int, ControllerUpdateCallback> callback_list; | ||
| 405 | int last_callback_key = 0; | ||
| 406 | |||
| 407 | // Stores the current status of all controller input | ||
| 408 | ControllerStatus controller; | ||
| 409 | }; | ||
| 410 | |||
| 411 | } // namespace Core::HID | ||