1 // Copyright 2018 yuzu emulator team
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 "common/bit_field.h"
9 #include "common/common_types.h"
10 #include "core/frontend/input.h"
11 #include "core/hle/kernel/object.h"
12 #include "core/hle/kernel/writable_event.h"
13 #include "core/hle/service/hid/controllers/controller_base.h"
14 #include "core/settings.h"
15 
16 namespace Service::HID {
17 
18 constexpr u32 NPAD_HANDHELD = 32;
19 constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this?
20 
21 class Controller_NPad final : public ControllerBase {
22 public:
23     explicit Controller_NPad(Core::System& system);
24     ~Controller_NPad() override;
25 
26     // Called when the controller is initialized
27     void OnInit() override;
28 
29     // When the controller is released
30     void OnRelease() override;
31 
32     // When the controller is requesting an update for the shared memory
33     void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
34 
35     // When the controller is requesting a motion update for the shared memory
36     void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
37                         std::size_t size) override;
38 
39     // Called when input devices should be loaded
40     void OnLoadInputDevices() override;
41 
42     enum class NPadControllerType {
43         None,
44         ProController,
45         Handheld,
46         JoyDual,
47         JoyLeft,
48         JoyRight,
49         Pokeball,
50     };
51 
52     enum class NpadType : u8 {
53         ProController = 3,
54         Handheld = 4,
55         JoyconDual = 5,
56         JoyconLeft = 6,
57         JoyconRight = 7,
58         Pokeball = 9,
59         MaxNpadType = 10,
60     };
61 
62     enum class DeviceIndex : u8 {
63         Left = 0,
64         Right = 1,
65         None = 2,
66         MaxDeviceIndex = 3,
67     };
68 
69     enum class GyroscopeZeroDriftMode : u32 {
70         Loose = 0,
71         Standard = 1,
72         Tight = 2,
73     };
74 
75     enum class NpadHoldType : u64 {
76         Vertical = 0,
77         Horizontal = 1,
78     };
79 
80     enum class NpadAssignments : u32 {
81         Dual = 0,
82         Single = 1,
83     };
84 
85     enum class NpadHandheldActivationMode : u64 {
86         Dual = 0,
87         Single = 1,
88         None = 2,
89     };
90 
91     enum class NpadCommunicationMode : u64 {
92         Unknown0 = 0,
93         Unknown1 = 1,
94         Unknown2 = 2,
95         Unknown3 = 3,
96     };
97 
98     struct DeviceHandle {
99         NpadType npad_type{};
100         u8 npad_id{};
101         DeviceIndex device_index{};
102         INSERT_PADDING_BYTES(1);
103     };
104     static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size");
105 
106     struct NpadStyleSet {
107         union {
108             u32_le raw{};
109 
110             BitField<0, 1, u32> pro_controller;
111             BitField<1, 1, u32> handheld;
112             BitField<2, 1, u32> joycon_dual;
113             BitField<3, 1, u32> joycon_left;
114             BitField<4, 1, u32> joycon_right;
115 
116             BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible
117         };
118     };
119     static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
120 
121     struct VibrationValue {
122         f32 amp_low{0.0f};
123         f32 freq_low{160.0f};
124         f32 amp_high{0.0f};
125         f32 freq_high{320.0f};
126     };
127     static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size");
128 
129     struct LedPattern {
LedPatternLedPattern130         explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
131             position1.Assign(light1);
132             position2.Assign(light2);
133             position3.Assign(light3);
134             position4.Assign(light4);
135         }
136         union {
137             u64 raw{};
138             BitField<0, 1, u64> position1;
139             BitField<1, 1, u64> position2;
140             BitField<2, 1, u64> position3;
141             BitField<3, 1, u64> position4;
142         };
143     };
144 
145     void SetSupportedStyleSet(NpadStyleSet style_set);
146     NpadStyleSet GetSupportedStyleSet() const;
147 
148     void SetSupportedNpadIdTypes(u8* data, std::size_t length);
149     void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
150     std::size_t GetSupportedNpadIdTypesSize() const;
151 
152     void SetHoldType(NpadHoldType joy_hold_type);
153     NpadHoldType GetHoldType() const;
154 
155     void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode);
156     NpadHandheldActivationMode GetNpadHandheldActivationMode() const;
157 
158     void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
159     NpadCommunicationMode GetNpadCommunicationMode() const;
160 
161     void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode);
162 
163     bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
164                                   const VibrationValue& vibration_value);
165 
166     void VibrateController(const DeviceHandle& vibration_device_handle,
167                            const VibrationValue& vibration_value);
168 
169     void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
170                             const std::vector<VibrationValue>& vibration_values);
171 
172     VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const;
173 
174     void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle);
175 
176     void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index);
177 
178     void SetPermitVibrationSession(bool permit_vibration_session);
179 
180     bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
181 
182     std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
183     void SignalStyleSetChangedEvent(u32 npad_id) const;
184 
185     // Adds a new controller at an index.
186     void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index);
187     // Adds a new controller at an index with connection status.
188     void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected);
189 
190     void DisconnectNpad(u32 npad_id);
191     void DisconnectNpadAtIndex(std::size_t index);
192 
193     void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
194     GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
195     bool IsSixAxisSensorAtRest() const;
196     void SetSixAxisEnabled(bool six_axis_status);
197     LedPattern GetLedPattern(u32 npad_id);
198     bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
199     void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
200     void ClearAllConnectedControllers();
201     void DisconnectAllConnectedControllers();
202     void ConnectAllDisconnectedControllers();
203     void ClearAllControllers();
204 
205     void MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2);
206     void StartLRAssignmentMode();
207     void StopLRAssignmentMode();
208     bool SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2);
209 
210     // Logical OR for all buttons presses on all controllers
211     // Specifically for cheat engine and other features.
212     u32 GetAndResetPressState();
213 
214     static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type);
215     static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type);
216     static std::size_t NPadIdToIndex(u32 npad_id);
217     static u32 IndexToNPad(std::size_t index);
218     static bool IsNpadIdValid(u32 npad_id);
219     static bool IsDeviceHandleValid(const DeviceHandle& device_handle);
220 
221 private:
222     struct CommonHeader {
223         s64_le timestamp;
224         s64_le total_entry_count;
225         s64_le last_entry_index;
226         s64_le entry_count;
227     };
228     static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
229 
230     struct ControllerColor {
231         u32_le body_color;
232         u32_le button_color;
233     };
234     static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size");
235 
236     struct ControllerPadState {
237         union {
238             u64_le raw{};
239             // Button states
240             BitField<0, 1, u64> a;
241             BitField<1, 1, u64> b;
242             BitField<2, 1, u64> x;
243             BitField<3, 1, u64> y;
244             BitField<4, 1, u64> l_stick;
245             BitField<5, 1, u64> r_stick;
246             BitField<6, 1, u64> l;
247             BitField<7, 1, u64> r;
248             BitField<8, 1, u64> zl;
249             BitField<9, 1, u64> zr;
250             BitField<10, 1, u64> plus;
251             BitField<11, 1, u64> minus;
252 
253             // D-Pad
254             BitField<12, 1, u64> d_left;
255             BitField<13, 1, u64> d_up;
256             BitField<14, 1, u64> d_right;
257             BitField<15, 1, u64> d_down;
258 
259             // Left JoyStick
260             BitField<16, 1, u64> l_stick_left;
261             BitField<17, 1, u64> l_stick_up;
262             BitField<18, 1, u64> l_stick_right;
263             BitField<19, 1, u64> l_stick_down;
264 
265             // Right JoyStick
266             BitField<20, 1, u64> r_stick_left;
267             BitField<21, 1, u64> r_stick_up;
268             BitField<22, 1, u64> r_stick_right;
269             BitField<23, 1, u64> r_stick_down;
270 
271             // Not always active?
272             BitField<24, 1, u64> left_sl;
273             BitField<25, 1, u64> left_sr;
274 
275             BitField<26, 1, u64> right_sl;
276             BitField<27, 1, u64> right_sr;
277         };
278     };
279     static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
280 
281     struct AnalogPosition {
282         s32_le x;
283         s32_le y;
284     };
285     static_assert(sizeof(AnalogPosition) == 8, "AnalogPosition is an invalid size");
286 
287     struct ConnectionState {
288         union {
289             u32_le raw{};
290             BitField<0, 1, u32> IsConnected;
291             BitField<1, 1, u32> IsWired;
292             BitField<2, 1, u32> IsLeftJoyConnected;
293             BitField<3, 1, u32> IsLeftJoyWired;
294             BitField<4, 1, u32> IsRightJoyConnected;
295             BitField<5, 1, u32> IsRightJoyWired;
296         };
297     };
298     static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size");
299 
300     struct ControllerPad {
301         ControllerPadState pad_states;
302         AnalogPosition l_stick;
303         AnalogPosition r_stick;
304     };
305     static_assert(sizeof(ControllerPad) == 0x18, "ControllerPad is an invalid size");
306 
307     struct GenericStates {
308         s64_le timestamp;
309         s64_le timestamp2;
310         ControllerPad pad;
311         ConnectionState connection_status;
312     };
313     static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size");
314 
315     struct NPadGeneric {
316         CommonHeader common;
317         std::array<GenericStates, 17> npad;
318     };
319     static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
320 
321     struct SixAxisStates {
322         s64_le timestamp{};
323         INSERT_PADDING_WORDS(2);
324         s64_le timestamp2{};
325         Common::Vec3f accel{};
326         Common::Vec3f gyro{};
327         Common::Vec3f rotation{};
328         std::array<Common::Vec3f, 3> orientation{};
329         s64_le always_one{1};
330     };
331     static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
332 
333     struct SixAxisGeneric {
334         CommonHeader common{};
335         std::array<SixAxisStates, 17> sixaxis{};
336     };
337     static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
338 
339     enum class ColorReadError : u32_le {
340         ReadOk = 0,
341         ColorDoesntExist = 1,
342         NoController = 2,
343     };
344 
345     struct NPadProperties {
346         union {
347             s64_le raw{};
348             BitField<11, 1, s64> is_vertical;
349             BitField<12, 1, s64> is_horizontal;
350             BitField<13, 1, s64> use_plus;
351             BitField<14, 1, s64> use_minus;
352         };
353     };
354 
355     struct NPadDevice {
356         union {
357             u32_le raw{};
358             BitField<0, 1, s32> pro_controller;
359             BitField<1, 1, s32> handheld;
360             BitField<2, 1, s32> handheld_left;
361             BitField<3, 1, s32> handheld_right;
362             BitField<4, 1, s32> joycon_left;
363             BitField<5, 1, s32> joycon_right;
364             BitField<6, 1, s32> pokeball;
365         };
366     };
367 
368     struct MotionDevice {
369         Common::Vec3f accel;
370         Common::Vec3f gyro;
371         Common::Vec3f rotation;
372         std::array<Common::Vec3f, 3> orientation;
373     };
374 
375     struct NPadEntry {
376         NpadStyleSet joy_styles;
377         NpadAssignments pad_assignment;
378 
379         ColorReadError single_color_error;
380         ControllerColor single_color;
381 
382         ColorReadError dual_color_error;
383         ControllerColor left_color;
384         ControllerColor right_color;
385 
386         NPadGeneric main_controller_states;
387         NPadGeneric handheld_states;
388         NPadGeneric dual_states;
389         NPadGeneric left_joy_states;
390         NPadGeneric right_joy_states;
391         NPadGeneric pokeball_states;
392         NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be
393                            // relying on this for the time being
394         SixAxisGeneric sixaxis_full;
395         SixAxisGeneric sixaxis_handheld;
396         SixAxisGeneric sixaxis_dual_left;
397         SixAxisGeneric sixaxis_dual_right;
398         SixAxisGeneric sixaxis_left;
399         SixAxisGeneric sixaxis_right;
400         NPadDevice device_type;
401         NPadProperties properties;
402         INSERT_PADDING_WORDS(1);
403         std::array<u32, 3> battery_level;
404         INSERT_PADDING_BYTES(0x5c);
405         INSERT_PADDING_BYTES(0xdf8);
406     };
407     static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
408 
409     struct ControllerHolder {
410         NPadControllerType type;
411         bool is_connected;
412     };
413 
414     void InitNewlyAddedController(std::size_t controller_idx);
415     bool IsControllerSupported(NPadControllerType controller) const;
416     void RequestPadStateUpdate(u32 npad_id);
417 
418     u32 press_state{};
419 
420     NpadStyleSet style{};
421     std::array<NPadEntry, 10> shared_memory_entries{};
422     using ButtonArray = std::array<
423         std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
424         10>;
425     using StickArray = std::array<
426         std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
427         10>;
428     using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>,
429                                                  Settings::NativeVibration::NUM_VIBRATIONS_HID>,
430                                       10>;
431     using MotionArray = std::array<
432         std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>,
433         10>;
434     ButtonArray buttons;
435     StickArray sticks;
436     VibrationArray vibrations;
437     MotionArray motions;
438     std::vector<u32> supported_npad_id_types{};
439     NpadHoldType hold_type{NpadHoldType::Vertical};
440     NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
441     // NpadCommunicationMode is unknown, default value is 1
442     NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1};
443     // Each controller should have their own styleset changed event
444     std::array<Kernel::EventPair, 10> styleset_changed_events;
445     std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
446     std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
447     bool permit_vibration_session_enabled{false};
448     std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
449     std::array<ControllerHolder, 10> connected_controllers{};
450     std::array<bool, 10> unintended_home_button_input_protection{};
451     GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
452     bool sixaxis_sensors_enabled{true};
453     bool sixaxis_at_rest{true};
454     std::array<ControllerPad, 10> npad_pad_states{};
455     bool is_in_lr_assignment_mode{false};
456     Core::System& system;
457 };
458 } // namespace Service::HID
459