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