// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" #include "common/point.h" #include "common/uuid.h" #include "common/vector_math.h" namespace Core::HID { enum class DeviceIndex : u8 { Left = 0, Right = 1, None = 2, MaxDeviceIndex = 3, }; // This is nn::hid::NpadButton enum class NpadButton : u64 { None = 0, A = 1U << 0, B = 1U << 1, X = 1U << 2, Y = 1U << 3, StickL = 1U << 4, StickR = 1U << 5, L = 1U << 6, R = 1U << 7, ZL = 1U << 8, ZR = 1U << 9, Plus = 1U << 10, Minus = 1U << 11, Left = 1U << 12, Up = 1U << 13, Right = 1U << 14, Down = 1U << 15, StickLLeft = 1U << 16, StickLUp = 1U << 17, StickLRight = 1U << 18, StickLDown = 1U << 19, StickRLeft = 1U << 20, StickRUp = 1U << 21, StickRRight = 1U << 22, StickRDown = 1U << 23, LeftSL = 1U << 24, LeftSR = 1U << 25, RightSL = 1U << 26, RightSR = 1U << 27, Palma = 1U << 28, Verification = 1U << 29, HandheldLeftB = 1U << 30, LagonCLeft = 1U << 31, LagonCUp = 1ULL << 32, LagonCRight = 1ULL << 33, LagonCDown = 1ULL << 34, All = 0xFFFFFFFFFFFFFFFFULL, }; DECLARE_ENUM_FLAG_OPERATORS(NpadButton); enum class KeyboardKeyIndex : u32 { A = 4, B = 5, C = 6, D = 7, E = 8, F = 9, G = 10, H = 11, I = 12, J = 13, K = 14, L = 15, M = 16, N = 17, O = 18, P = 19, Q = 20, R = 21, S = 22, T = 23, U = 24, V = 25, W = 26, X = 27, Y = 28, Z = 29, D1 = 30, D2 = 31, D3 = 32, D4 = 33, D5 = 34, D6 = 35, D7 = 36, D8 = 37, D9 = 38, D0 = 39, Return = 40, Escape = 41, Backspace = 42, Tab = 43, Space = 44, Minus = 45, Plus = 46, OpenBracket = 47, CloseBracket = 48, Pipe = 49, Tilde = 50, Semicolon = 51, Quote = 52, Backquote = 53, Comma = 54, Period = 55, Slash = 56, CapsLock = 57, F1 = 58, F2 = 59, F3 = 60, F4 = 61, F5 = 62, F6 = 63, F7 = 64, F8 = 65, F9 = 66, F10 = 67, F11 = 68, F12 = 69, PrintScreen = 70, ScrollLock = 71, Pause = 72, Insert = 73, Home = 74, PageUp = 75, Delete = 76, End = 77, PageDown = 78, RightArrow = 79, LeftArrow = 80, DownArrow = 81, UpArrow = 82, NumLock = 83, NumPadDivide = 84, NumPadMultiply = 85, NumPadSubtract = 86, NumPadAdd = 87, NumPadEnter = 88, NumPad1 = 89, NumPad2 = 90, NumPad3 = 91, NumPad4 = 92, NumPad5 = 93, NumPad6 = 94, NumPad7 = 95, NumPad8 = 96, NumPad9 = 97, NumPad0 = 98, NumPadDot = 99, Backslash = 100, Application = 101, Power = 102, NumPadEquals = 103, F13 = 104, F14 = 105, F15 = 106, F16 = 107, F17 = 108, F18 = 109, F19 = 110, F20 = 111, F21 = 112, F22 = 113, F23 = 114, F24 = 115, NumPadComma = 133, Ro = 135, KatakanaHiragana = 136, Yen = 137, Henkan = 138, Muhenkan = 139, NumPadCommaPc98 = 140, HangulEnglish = 144, Hanja = 145, Katakana = 146, Hiragana = 147, ZenkakuHankaku = 148, LeftControl = 224, LeftShift = 225, LeftAlt = 226, LeftGui = 227, RightControl = 228, RightShift = 229, RightAlt = 230, RightGui = 231, }; // This is nn::hid::NpadIdType enum class NpadIdType : u32 { Player1 = 0x0, Player2 = 0x1, Player3 = 0x2, Player4 = 0x3, Player5 = 0x4, Player6 = 0x5, Player7 = 0x6, Player8 = 0x7, Other = 0x10, Handheld = 0x20, Invalid = 0xFFFFFFFF, }; enum class NpadInterfaceType : u8 { None = 0, Bluetooth = 1, Rail = 2, Usb = 3, Embedded = 4, }; // This is nn::hid::NpadStyleIndex enum class NpadStyleIndex : u8 { None = 0, Fullkey = 3, Handheld = 4, HandheldNES = 4, JoyconDual = 5, JoyconLeft = 6, JoyconRight = 7, GameCube = 8, Pokeball = 9, NES = 10, SNES = 12, N64 = 13, SegaGenesis = 14, SystemExt = 32, System = 33, MaxNpadType = 34, }; // This is nn::hid::NpadStyleSet enum class NpadStyleSet : u32 { None = 0, Fullkey = 1U << 0, Handheld = 1U << 1, JoyDual = 1U << 2, JoyLeft = 1U << 3, JoyRight = 1U << 4, Gc = 1U << 5, Palma = 1U << 6, Lark = 1U << 7, HandheldLark = 1U << 8, Lucia = 1U << 9, Lagoon = 1U << 10, Lager = 1U << 11, SystemExt = 1U << 29, System = 1U << 30, All = 0xFFFFFFFFU, }; static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); DECLARE_ENUM_FLAG_OPERATORS(NpadStyleSet) // This is nn::hid::VibrationDevicePosition enum class VibrationDevicePosition : u32 { None = 0, Left = 1, Right = 2, }; // This is nn::hid::VibrationDeviceType enum class VibrationDeviceType : u32 { Unknown = 0, LinearResonantActuator = 1, GcErm = 2, N64 = 3, }; // This is nn::hid::VibrationGcErmCommand enum class VibrationGcErmCommand : u64 { Stop = 0, Start = 1, StopHard = 2, }; // This is nn::hid::GyroscopeZeroDriftMode enum class GyroscopeZeroDriftMode : u32 { Loose = 0, Standard = 1, Tight = 2, }; // This is nn::hid::TouchScreenModeForNx enum class TouchScreenModeForNx : u8 { UseSystemSetting, Finger, Heat2, }; // This is nn::hid::system::NpadBatteryLevel enum class NpadBatteryLevel : u32 { Empty, Critical, Low, High, Full, }; // This is nn::hid::NpadStyleTag struct NpadStyleTag { union { NpadStyleSet raw{}; BitField<0, 1, u32> fullkey; BitField<1, 1, u32> handheld; BitField<2, 1, u32> joycon_dual; BitField<3, 1, u32> joycon_left; BitField<4, 1, u32> joycon_right; BitField<5, 1, u32> gamecube; BitField<6, 1, u32> palma; BitField<7, 1, u32> lark; BitField<8, 1, u32> handheld_lark; BitField<9, 1, u32> lucia; BitField<10, 1, u32> lagoon; BitField<11, 1, u32> lager; BitField<29, 1, u32> system_ext; BitField<30, 1, u32> system; }; }; static_assert(sizeof(NpadStyleTag) == 4, "NpadStyleTag is an invalid size"); // This is nn::hid::TouchAttribute struct TouchAttribute { union { u32 raw{}; BitField<0, 1, u32> start_touch; BitField<1, 1, u32> end_touch; }; }; static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"); struct TouchFinger { u64 last_touch{}; Common::Point position{}; u32 id{}; TouchAttribute attribute{}; bool pressed{}; }; // This is nn::hid::TouchScreenConfigurationForNx struct TouchScreenConfigurationForNx { TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting}; INSERT_PADDING_BYTES(0xF); }; static_assert(sizeof(TouchScreenConfigurationForNx) == 0x10, "TouchScreenConfigurationForNx is an invalid size"); struct NpadColor { u8 r{}; u8 g{}; u8 b{}; u8 a{}; }; static_assert(sizeof(NpadColor) == 4, "NpadColor is an invalid size"); // This is nn::hid::NpadControllerColor struct NpadControllerColor { NpadColor body{}; NpadColor button{}; }; static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); // This is nn::hid::AnalogStickState struct AnalogStickState { s32 x{}; s32 y{}; }; static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size"); // This is nn::hid::server::NpadGcTriggerState struct NpadGcTriggerState { s64 sampling_number{}; s32 left{}; s32 right{}; }; static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); // This is nn::hid::system::NpadPowerInfo struct NpadPowerInfo { bool is_powered{}; bool is_charging{}; INSERT_PADDING_BYTES(0x6); NpadBatteryLevel battery_level{NpadBatteryLevel::Full}; }; static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); struct LedPattern { LedPattern() { raw = 0; } LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { position1.Assign(light1); position2.Assign(light2); position3.Assign(light3); position4.Assign(light4); } union { u64 raw{}; BitField<0, 1, u64> position1; BitField<1, 1, u64> position2; BitField<2, 1, u64> position3; BitField<3, 1, u64> position4; }; }; struct SleepButtonState { union { u64 raw{}; // Buttons BitField<0, 1, u64> sleep; }; }; static_assert(sizeof(SleepButtonState) == 0x8, "SleepButtonState has incorrect size."); struct HomeButtonState { union { u64 raw{}; // Buttons BitField<0, 1, u64> home; }; }; static_assert(sizeof(HomeButtonState) == 0x8, "HomeButtonState has incorrect size."); struct CaptureButtonState { union { u64 raw{}; // Buttons BitField<0, 1, u64> capture; }; }; static_assert(sizeof(CaptureButtonState) == 0x8, "CaptureButtonState has incorrect size."); struct NpadButtonState { union { NpadButton raw{}; // Buttons BitField<0, 1, u64> a; BitField<1, 1, u64> b; BitField<2, 1, u64> x; BitField<3, 1, u64> y; BitField<4, 1, u64> stick_l; BitField<5, 1, u64> stick_r; BitField<6, 1, u64> l; BitField<7, 1, u64> r; BitField<8, 1, u64> zl; BitField<9, 1, u64> zr; BitField<10, 1, u64> plus; BitField<11, 1, u64> minus; // D-Pad BitField<12, 1, u64> left; BitField<13, 1, u64> up; BitField<14, 1, u64> right; BitField<15, 1, u64> down; // Left JoyStick BitField<16, 1, u64> stick_l_left; BitField<17, 1, u64> stick_l_up; BitField<18, 1, u64> stick_l_right; BitField<19, 1, u64> stick_l_down; // Right JoyStick BitField<20, 1, u64> stick_r_left; BitField<21, 1, u64> stick_r_up; BitField<22, 1, u64> stick_r_right; BitField<23, 1, u64> stick_r_down; BitField<24, 1, u64> left_sl; BitField<25, 1, u64> left_sr; BitField<26, 1, u64> right_sl; BitField<27, 1, u64> right_sr; BitField<28, 1, u64> palma; BitField<29, 1, u64> verification; BitField<30, 1, u64> handheld_left_b; BitField<31, 1, u64> lagon_c_left; BitField<32, 1, u64> lagon_c_up; BitField<33, 1, u64> lagon_c_right; BitField<34, 1, u64> lagon_c_down; }; }; static_assert(sizeof(NpadButtonState) == 0x8, "NpadButtonState has incorrect size."); // This is nn::hid::DebugPadButton struct DebugPadButton { union { u32 raw{}; BitField<0, 1, u32> a; BitField<1, 1, u32> b; BitField<2, 1, u32> x; BitField<3, 1, u32> y; BitField<4, 1, u32> l; BitField<5, 1, u32> r; BitField<6, 1, u32> zl; BitField<7, 1, u32> zr; BitField<8, 1, u32> plus; BitField<9, 1, u32> minus; BitField<10, 1, u32> d_left; BitField<11, 1, u32> d_up; BitField<12, 1, u32> d_right; BitField<13, 1, u32> d_down; }; }; static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); // This is nn::hid::ConsoleSixAxisSensorHandle struct ConsoleSixAxisSensorHandle { u8 unknown_1{}; u8 unknown_2{}; INSERT_PADDING_BYTES_NOINIT(2); }; static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4, "ConsoleSixAxisSensorHandle is an invalid size"); // This is nn::hid::SixAxisSensorHandle struct SixAxisSensorHandle { NpadStyleIndex npad_type{NpadStyleIndex::None}; u8 npad_id{}; DeviceIndex device_index{DeviceIndex::None}; INSERT_PADDING_BYTES_NOINIT(1); }; static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size"); // These parameters seem related to how much gyro/accelerometer is used struct SixAxisSensorFusionParameters { f32 parameter1{0.03f}; // Range 0.0 to 1.0, default 0.03 f32 parameter2{0.4f}; // Default 0.4 }; static_assert(sizeof(SixAxisSensorFusionParameters) == 8, "SixAxisSensorFusionParameters is an invalid size"); // This is nn::hid::server::SixAxisSensorProperties struct SixAxisSensorProperties { union { u8 raw{}; BitField<0, 1, u8> is_newly_assigned; BitField<1, 1, u8> is_firmware_update_available; }; }; static_assert(sizeof(SixAxisSensorProperties) == 1, "SixAxisSensorProperties is an invalid size"); // This is nn::hid::SixAxisSensorCalibrationParameter struct SixAxisSensorCalibrationParameter { std::array unknown_data; }; static_assert(sizeof(SixAxisSensorCalibrationParameter) == 0x744, "SixAxisSensorCalibrationParameter is an invalid size"); static_assert(std::is_trivial_v, "SixAxisSensorCalibrationParameter must be trivial."); // This is nn::hid::SixAxisSensorIcInformation struct SixAxisSensorIcInformation { f32 angular_rate; // dps std::array unknown_gyro_data1; // dps std::array unknown_gyro_data2; std::array unknown_gyro_data3; f32 acceleration_range; // g force std::array unknown_accel_data1; // g force std::array unknown_accel_data2; std::array unknown_accel_data3; }; static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8, "SixAxisSensorIcInformation is an invalid size"); static_assert(std::is_trivial_v, "SixAxisSensorIcInformation must be trivial."); // This is nn::hid::SixAxisSensorAttribute struct SixAxisSensorAttribute { union { u32 raw{}; BitField<0, 1, u32> is_connected; BitField<1, 1, u32> is_interpolated; }; }; static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size"); // This is nn::hid::SixAxisSensorState struct SixAxisSensorState { s64 delta_time{}; s64 sampling_number{}; Common::Vec3f accel{}; Common::Vec3f gyro{}; Common::Vec3f rotation{}; std::array orientation{}; SixAxisSensorAttribute attribute{}; INSERT_PADDING_BYTES(4); // Reserved }; static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size"); // This is nn::hid::VibrationDeviceHandle struct VibrationDeviceHandle { NpadStyleIndex npad_type{NpadStyleIndex::None}; u8 npad_id{}; DeviceIndex device_index{DeviceIndex::None}; INSERT_PADDING_BYTES_NOINIT(1); }; static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size"); // This is nn::hid::VibrationValue struct VibrationValue { f32 low_amplitude{}; f32 low_frequency{}; f32 high_amplitude{}; f32 high_frequency{}; bool operator==(const VibrationValue& b) { if (low_amplitude != b.low_amplitude || high_amplitude != b.high_amplitude) { return false; } // Changes in frequency without amplitude don't have any effect if (low_amplitude == 0 && high_amplitude == 0) { return true; } if (low_frequency != b.low_frequency || high_frequency != b.high_frequency) { return false; } return true; } }; static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); constexpr VibrationValue DEFAULT_VIBRATION_VALUE{ .low_amplitude = 0.0f, .low_frequency = 160.0f, .high_amplitude = 0.0f, .high_frequency = 320.0f, }; // This is nn::hid::VibrationDeviceInfo struct VibrationDeviceInfo { VibrationDeviceType type{}; VibrationDevicePosition position{}; }; static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); // This is nn::hid::KeyboardModifier struct KeyboardModifier { union { u32 raw{}; BitField<0, 1, u32> control; BitField<1, 1, u32> shift; BitField<2, 1, u32> left_alt; BitField<3, 1, u32> right_alt; BitField<4, 1, u32> gui; BitField<8, 1, u32> caps_lock; BitField<9, 1, u32> scroll_lock; BitField<10, 1, u32> num_lock; BitField<11, 1, u32> katakana; BitField<12, 1, u32> hiragana; }; }; static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size"); // This is nn::hid::KeyboardAttribute struct KeyboardAttribute { union { u32 raw{}; BitField<0, 1, u32> is_connected; }; }; static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid size"); // This is nn::hid::KeyboardKey struct KeyboardKey { // This should be a 256 bit flag std::array key{}; }; static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size"); // This is nn::hid::MouseButton struct MouseButton { union { u32_le raw{}; BitField<0, 1, u32> left; BitField<1, 1, u32> right; BitField<2, 1, u32> middle; BitField<3, 1, u32> forward; BitField<4, 1, u32> back; }; }; static_assert(sizeof(MouseButton) == 0x4, "MouseButton is an invalid size"); // This is nn::hid::MouseAttribute struct MouseAttribute { union { u32 raw{}; BitField<0, 1, u32> transferable; BitField<1, 1, u32> is_connected; }; }; static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size"); // This is nn::hid::detail::MouseState struct MouseState { s64 sampling_number{}; s32 x{}; s32 y{}; s32 delta_x{}; s32 delta_y{}; // Axis Order in HW is switched for the wheel s32 delta_wheel_y{}; s32 delta_wheel_x{}; MouseButton button{}; MouseAttribute attribute{}; }; static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); struct UniquePadId { u64 id; }; static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size"); // This is nn::hid::system::FirmwareVersion struct FirmwareVersion { u8 major; u8 minor; u8 micro; u8 revision; std::array device_identifier; }; static_assert(sizeof(FirmwareVersion) == 0x10, "FirmwareVersion is an invalid size"); } // namespace Core::HID