summaryrefslogtreecommitdiff
path: root/src/core/hid/emulated_controller.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hid/emulated_controller.h')
-rw-r--r--src/core/hid/emulated_controller.h392
1 files changed, 392 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..2c5d51bc8
--- /dev/null
+++ b/src/core/hid/emulated_controller.h
@@ -0,0 +1,392 @@
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
23namespace Core::HID {
24const std::size_t max_emulated_controllers = 2;
25struct ControllerMotionInfo {
26 Common::Input::MotionStatus raw_status{};
27 MotionInput emulated{};
28};
29
30using ButtonDevices =
31 std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeButton::NumButtons>;
32using StickDevices =
33 std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeAnalog::NumAnalogs>;
34using ControllerMotionDevices =
35 std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>;
36using TriggerDevices =
37 std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
38using BatteryDevices =
39 std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
40using OutputDevices =
41 std::array<std::unique_ptr<Common::Input::OutputDevice>, max_emulated_controllers>;
42
43using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
44using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
45using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
46using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
47using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>;
48using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>;
49
50using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>;
51using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
52using TriggerValues =
53 std::array<Common::Input::TriggerStatus, Settings::NativeTrigger::NumTriggers>;
54using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>;
55using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>;
56using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>;
57using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>;
58
59struct AnalogSticks {
60 AnalogStickState left{};
61 AnalogStickState right{};
62};
63
64struct ControllerColors {
65 NpadControllerColor fullkey{};
66 NpadControllerColor left{};
67 NpadControllerColor right{};
68};
69
70struct BatteryLevelState {
71 NpadPowerInfo dual{};
72 NpadPowerInfo left{};
73 NpadPowerInfo right{};
74};
75
76struct 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
84enum EmulatedDeviceIndex : u8 {
85 LeftIndex,
86 RightIndex,
87 DualIndex,
88 AllDevices,
89};
90
91using MotionState = std::array<ControllerMotion, 2>;
92
93struct 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
113enum 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
127struct ControllerUpdateCallback {
128 std::function<void(ControllerTriggerType)> on_change;
129 bool is_npad_service;
130};
131
132class EmulatedController {
133public:
134 /**
135 * Contains all input data related to this controller. Like buttons, joysticks, motion.
136 * @param 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 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 /// Sets the connected status to true
164 void Connect();
165
166 /// Sets the connected status to false
167 void Disconnect();
168
169 /**
170 * Is the emulated connected
171 * @param If true tmp_is_connected will be returned
172 * @return true if the controller has the connected status
173 */
174 bool IsConnected(bool get_temporary_value = false) const;
175
176 /// Returns true if vibration is enabled
177 bool IsVibrationEnabled() const;
178
179 /// Removes all callbacks created from input devices
180 void UnloadInput();
181
182 /// Sets the emulated console into configuring mode. Locking all HID service events from being
183 /// moddified
184 void EnableConfiguration();
185
186 /// Returns the emulated console to the normal behaivour
187 void DisableConfiguration();
188
189 /// Returns true if the emulated device is on configuring mode
190 bool IsConfiguring() const;
191
192 /// Reload all input devices
193 void ReloadInput();
194
195 /// Overrides current mapped devices with the stored configuration and reloads all input devices
196 void ReloadFromSettings();
197
198 /// Saves the current mapped configuration
199 void SaveCurrentConfig();
200
201 /// Reverts any mapped changes made that weren't saved
202 void RestoreConfig();
203
204 /// Returns a vector of mapped devices from the mapped button and stick parameters
205 std::vector<Common::ParamPackage> GetMappedDevices(EmulatedDeviceIndex device_index) const;
206
207 // Returns the current mapped button device
208 Common::ParamPackage GetButtonParam(std::size_t index) const;
209
210 // Returns the current mapped stick device
211 Common::ParamPackage GetStickParam(std::size_t index) const;
212
213 // Returns the current mapped motion device
214 Common::ParamPackage GetMotionParam(std::size_t index) const;
215
216 /**
217 * Updates the current mapped button device
218 * @param ParamPackage with controller data to be mapped
219 */
220 void SetButtonParam(std::size_t index, Common::ParamPackage param);
221
222 /**
223 * Updates the current mapped stick device
224 * @param ParamPackage with controller data to be mapped
225 */
226 void SetStickParam(std::size_t index, Common::ParamPackage param);
227
228 /**
229 * Updates the current mapped motion device
230 * @param ParamPackage with controller data to be mapped
231 */
232 void SetMotionParam(std::size_t index, Common::ParamPackage param);
233
234 /// Returns the latest button status from the controller with parameters
235 ButtonValues GetButtonsValues() const;
236
237 /// Returns the latest analog stick status from the controller with parameters
238 SticksValues GetSticksValues() const;
239
240 /// Returns the latest trigger status from the controller with parameters
241 TriggerValues GetTriggersValues() const;
242
243 /// Returns the latest motion status from the controller with parameters
244 ControllerMotionValues GetMotionValues() const;
245
246 /// Returns the latest color status from the controller with parameters
247 ColorValues GetColorsValues() const;
248
249 /// Returns the latest battery status from the controller with parameters
250 BatteryValues GetBatteryValues() const;
251
252 /// Returns the latest status of button input for the npad service
253 NpadButtonState GetNpadButtons() const;
254
255 /// Returns the latest status of button input for the debug pad service
256 DebugPadButton GetDebugPadButtons() const;
257
258 /// Returns the latest status of stick input from the mouse
259 AnalogSticks GetSticks() const;
260
261 /// Returns the latest status of trigger input from the mouse
262 NpadGcTriggerState GetTriggers() const;
263
264 /// Returns the latest status of motion input from the mouse
265 MotionState GetMotions() const;
266
267 /// Returns the latest color value from the controller
268 ControllerColors GetColors() const;
269
270 /// Returns the latest battery status from the controller
271 BatteryLevelState GetBattery() const;
272
273 /*
274 * Sends a specific vibration to the output device
275 * @return returns true if vibration had no errors
276 */
277 bool SetVibration(std::size_t device_index, VibrationValue vibration);
278
279 /*
280 * Sends a small vibration to the output device
281 * @return returns true if SetVibration was successfull
282 */
283 bool TestVibration(std::size_t device_index);
284
285 /// Returns the led pattern corresponding to this emulated controller
286 LedPattern GetLedPattern() const;
287
288 /// Asks the output device to change the player led pattern
289 void SetLedPattern();
290
291 /**
292 * Adds a callback to the list of events
293 * @param ConsoleUpdateCallback that will be triggered
294 * @return an unique key corresponding to the callback index in the list
295 */
296 int SetCallback(ControllerUpdateCallback update_callback);
297
298 /**
299 * Removes a callback from the list stopping any future events to this object
300 * @param Key corresponding to the callback index in the list
301 */
302 void DeleteCallback(int key);
303
304private:
305 /// creates input devices from params
306 void LoadDevices();
307
308 /// Set the params for TAS devices
309 void LoadTASParams();
310
311 /**
312 * Updates the button status of the controller
313 * @param callback: A CallbackStatus containing the button status
314 * @param index: Button ID of the to be updated
315 */
316 void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
317
318 /**
319 * Updates the analog stick status of the controller
320 * @param callback: A CallbackStatus containing the analog stick status
321 * @param index: stick ID of the to be updated
322 */
323 void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
324
325 /**
326 * Updates the trigger status of the controller
327 * @param callback: A CallbackStatus containing the trigger status
328 * @param index: trigger ID of the to be updated
329 */
330 void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
331
332 /**
333 * Updates the motion status of the controller
334 * @param callback: A CallbackStatus containing gyro and accelerometer data
335 * @param index: motion ID of the to be updated
336 */
337 void SetMotion(Common::Input::CallbackStatus callback, std::size_t index);
338
339 /**
340 * Updates the battery status of the controller
341 * @param callback: A CallbackStatus containing the battery status
342 * @param index: Button ID of the to be updated
343 */
344 void SetBattery(Common::Input::CallbackStatus callback, std::size_t index);
345
346 /**
347 * Triggers a callback that something has changed on the controller status
348 * @param type: Input type of the event to trigger
349 * @param is_service_update: indicates if this event should be sended to only services
350 */
351 void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
352
353 NpadIdType npad_id_type;
354 NpadStyleIndex npad_type{NpadStyleIndex::None};
355 bool is_connected{false};
356 bool is_configuring{false};
357 f32 motion_sensitivity{0.01f};
358 bool force_update_motion{false};
359
360 // Temporary values to avoid doing changes while the controller is on configuration mode
361 NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
362 bool tmp_is_connected{false};
363
364 ButtonParams button_params;
365 StickParams stick_params;
366 ControllerMotionParams motion_params;
367 TriggerParams trigger_params;
368 BatteryParams battery_params;
369 OutputParams output_params;
370
371 ButtonDevices button_devices;
372 StickDevices stick_devices;
373 ControllerMotionDevices motion_devices;
374 TriggerDevices trigger_devices;
375 BatteryDevices battery_devices;
376 OutputDevices output_devices;
377
378 // TAS related variables
379 ButtonParams tas_button_params;
380 StickParams tas_stick_params;
381 ButtonDevices tas_button_devices;
382 StickDevices tas_stick_devices;
383
384 mutable std::mutex mutex;
385 std::unordered_map<int, ControllerUpdateCallback> callback_list;
386 int last_callback_key = 0;
387
388 // Stores the current status of all controller input
389 ControllerStatus controller;
390};
391
392} // namespace Core::HID