Merge pull request #12359 from german77/real_shared
service: hid: Allow to create multiple instances of shared memory
This commit is contained in:
		@@ -549,6 +549,11 @@ add_library(core STATIC
 | 
			
		||||
    hle/service/hid/xcd.cpp
 | 
			
		||||
    hle/service/hid/xcd.h
 | 
			
		||||
    hle/service/hid/errors.h
 | 
			
		||||
    hle/service/hid/controllers/types/debug_pad_types.h
 | 
			
		||||
    hle/service/hid/controllers/types/keyboard_types.h
 | 
			
		||||
    hle/service/hid/controllers/types/mouse_types.h
 | 
			
		||||
    hle/service/hid/controllers/types/npad_types.h
 | 
			
		||||
    hle/service/hid/controllers/types/touch_types.h
 | 
			
		||||
    hle/service/hid/controllers/applet_resource.cpp
 | 
			
		||||
    hle/service/hid/controllers/applet_resource.h
 | 
			
		||||
    hle/service/hid/controllers/console_six_axis.cpp
 | 
			
		||||
@@ -569,14 +574,15 @@ add_library(core STATIC
 | 
			
		||||
    hle/service/hid/controllers/palma.h
 | 
			
		||||
    hle/service/hid/controllers/seven_six_axis.cpp
 | 
			
		||||
    hle/service/hid/controllers/seven_six_axis.h
 | 
			
		||||
    hle/service/hid/controllers/shared_memory_format.h
 | 
			
		||||
    hle/service/hid/controllers/shared_memory_holder.cpp
 | 
			
		||||
    hle/service/hid/controllers/shared_memory_holder.h
 | 
			
		||||
    hle/service/hid/controllers/six_axis.cpp
 | 
			
		||||
    hle/service/hid/controllers/six_axis.h
 | 
			
		||||
    hle/service/hid/controllers/stubbed.cpp
 | 
			
		||||
    hle/service/hid/controllers/stubbed.h
 | 
			
		||||
    hle/service/hid/controllers/touchscreen.cpp
 | 
			
		||||
    hle/service/hid/controllers/touchscreen.h
 | 
			
		||||
    hle/service/hid/controllers/xpad.cpp
 | 
			
		||||
    hle/service/hid/controllers/xpad.h
 | 
			
		||||
    hle/service/hid/hidbus/hidbus_base.cpp
 | 
			
		||||
    hle/service/hid/hidbus/hidbus_base.h
 | 
			
		||||
    hle/service/hid/hidbus/ringcon.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,9 @@ InputInterpreter::InputInterpreter(Core::System& system)
 | 
			
		||||
InputInterpreter::~InputInterpreter() = default;
 | 
			
		||||
 | 
			
		||||
void InputInterpreter::PollInput() {
 | 
			
		||||
    if (npad == nullptr) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    const auto button_state = npad->GetAndResetPressState();
 | 
			
		||||
 | 
			
		||||
    previous_index = current_index;
 | 
			
		||||
 
 | 
			
		||||
@@ -135,7 +135,6 @@ struct KernelCore::Impl {
 | 
			
		||||
                obj = nullptr;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        CleanupObject(hid_shared_mem);
 | 
			
		||||
        CleanupObject(font_shared_mem);
 | 
			
		||||
        CleanupObject(irs_shared_mem);
 | 
			
		||||
        CleanupObject(time_shared_mem);
 | 
			
		||||
@@ -744,22 +743,16 @@ struct KernelCore::Impl {
 | 
			
		||||
    void InitializeHackSharedMemory(KernelCore& kernel) {
 | 
			
		||||
        // Setup memory regions for emulated processes
 | 
			
		||||
        // TODO(bunnei): These should not be hardcoded regions initialized within the kernel
 | 
			
		||||
        constexpr std::size_t hid_size{0x40000};
 | 
			
		||||
        constexpr std::size_t font_size{0x1100000};
 | 
			
		||||
        constexpr std::size_t irs_size{0x8000};
 | 
			
		||||
        constexpr std::size_t time_size{0x1000};
 | 
			
		||||
        constexpr std::size_t hidbus_size{0x1000};
 | 
			
		||||
 | 
			
		||||
        hid_shared_mem = KSharedMemory::Create(system.Kernel());
 | 
			
		||||
        font_shared_mem = KSharedMemory::Create(system.Kernel());
 | 
			
		||||
        irs_shared_mem = KSharedMemory::Create(system.Kernel());
 | 
			
		||||
        time_shared_mem = KSharedMemory::Create(system.Kernel());
 | 
			
		||||
        hidbus_shared_mem = KSharedMemory::Create(system.Kernel());
 | 
			
		||||
 | 
			
		||||
        hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
 | 
			
		||||
                                   Svc::MemoryPermission::Read, hid_size);
 | 
			
		||||
        KSharedMemory::Register(kernel, hid_shared_mem);
 | 
			
		||||
 | 
			
		||||
        font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None,
 | 
			
		||||
                                    Svc::MemoryPermission::Read, font_size);
 | 
			
		||||
        KSharedMemory::Register(kernel, font_shared_mem);
 | 
			
		||||
@@ -1190,14 +1183,6 @@ const KSystemResource& KernelCore::GetSystemSystemResource() const {
 | 
			
		||||
    return *impl->sys_system_resource;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Kernel::KSharedMemory& KernelCore::GetHidSharedMem() {
 | 
			
		||||
    return *impl->hid_shared_mem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const {
 | 
			
		||||
    return *impl->hid_shared_mem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Kernel::KSharedMemory& KernelCore::GetFontSharedMem() {
 | 
			
		||||
    return *impl->font_shared_mem;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -239,12 +239,6 @@ public:
 | 
			
		||||
    /// Gets the system resource manager.
 | 
			
		||||
    const KSystemResource& GetSystemSystemResource() const;
 | 
			
		||||
 | 
			
		||||
    /// Gets the shared memory object for HID services.
 | 
			
		||||
    Kernel::KSharedMemory& GetHidSharedMem();
 | 
			
		||||
 | 
			
		||||
    /// Gets the shared memory object for HID services.
 | 
			
		||||
    const Kernel::KSharedMemory& GetHidSharedMem() const;
 | 
			
		||||
 | 
			
		||||
    /// Gets the shared memory object for font services.
 | 
			
		||||
    Kernel::KSharedMemory& GetFontSharedMem();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/hle/kernel/k_shared_memory.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/applet_resource.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
#include "core/hle/service/hid/errors.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
@@ -23,11 +24,24 @@ Result AppletResource::CreateAppletResource(u64 aruid) {
 | 
			
		||||
        return ResultAruidAlreadyRegistered;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: Here shared memory is created for the process we don't quite emulate this part so
 | 
			
		||||
    // obtain this pointer from system
 | 
			
		||||
    auto& shared_memory = system.Kernel().GetHidSharedMem();
 | 
			
		||||
    auto& shared_memory = shared_memory_holder[index];
 | 
			
		||||
    if (!shared_memory.IsMapped()) {
 | 
			
		||||
        const Result result = shared_memory.Initialize(system);
 | 
			
		||||
        if (result.IsError()) {
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        if (shared_memory.GetAddress() == nullptr) {
 | 
			
		||||
            shared_memory.Finalize();
 | 
			
		||||
            return ResultSharedMemoryNotInitialized;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data[index].shared_memory_handle = &shared_memory;
 | 
			
		||||
    auto* shared_memory_format = shared_memory.GetAddress();
 | 
			
		||||
    if (shared_memory_format != nullptr) {
 | 
			
		||||
        shared_memory_format->Initialize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data[index].shared_memory_format = shared_memory_format;
 | 
			
		||||
    data[index].flag.is_assigned.Assign(true);
 | 
			
		||||
    // TODO: InitializeSixAxisControllerConfig(false);
 | 
			
		||||
    active_aruid = aruid;
 | 
			
		||||
@@ -94,7 +108,7 @@ void AppletResource::UnregisterAppletResourceUserId(u64 aruid) {
 | 
			
		||||
 | 
			
		||||
    if (index < AruidIndexMax) {
 | 
			
		||||
        if (data[index].flag.is_assigned) {
 | 
			
		||||
            data[index].shared_memory_handle = nullptr;
 | 
			
		||||
            data[index].shared_memory_format = nullptr;
 | 
			
		||||
            data[index].flag.is_assigned.Assign(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -120,7 +134,7 @@ void AppletResource::FreeAppletResourceId(u64 aruid) {
 | 
			
		||||
 | 
			
		||||
    auto& aruid_data = data[index];
 | 
			
		||||
    if (aruid_data.flag.is_assigned) {
 | 
			
		||||
        aruid_data.shared_memory_handle = nullptr;
 | 
			
		||||
        aruid_data.shared_memory_format = nullptr;
 | 
			
		||||
        aruid_data.flag.is_assigned.Assign(false);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -135,7 +149,18 @@ Result AppletResource::GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle,
 | 
			
		||||
        return ResultAruidNotRegistered;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *out_handle = data[index].shared_memory_handle;
 | 
			
		||||
    *out_handle = shared_memory_holder[index].GetHandle();
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result AppletResource::GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format,
 | 
			
		||||
                                             u64 aruid) {
 | 
			
		||||
    u64 index = GetIndexFromAruid(aruid);
 | 
			
		||||
    if (index >= AruidIndexMax) {
 | 
			
		||||
        return ResultAruidNotRegistered;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *out_shared_memory_format = data[index].shared_memory_format;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hle/result.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_holder.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
@@ -18,6 +19,8 @@ class KSharedMemory;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct SharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class AppletResource {
 | 
			
		||||
public:
 | 
			
		||||
    explicit AppletResource(Core::System& system_);
 | 
			
		||||
@@ -32,6 +35,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    u64 GetActiveAruid();
 | 
			
		||||
    Result GetSharedMemoryHandle(Kernel::KSharedMemory** out_handle, u64 aruid);
 | 
			
		||||
    Result GetSharedMemoryFormat(SharedMemoryFormat** out_shared_memory_format, u64 aruid);
 | 
			
		||||
 | 
			
		||||
    u64 GetIndexFromAruid(u64 aruid);
 | 
			
		||||
 | 
			
		||||
@@ -80,12 +84,13 @@ private:
 | 
			
		||||
    struct AruidData {
 | 
			
		||||
        DataStatusFlag flag{};
 | 
			
		||||
        u64 aruid{};
 | 
			
		||||
        Kernel::KSharedMemory* shared_memory_handle{nullptr};
 | 
			
		||||
        SharedMemoryFormat* shared_memory_format{nullptr};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    u64 active_aruid{};
 | 
			
		||||
    AruidRegisterList registration_list{};
 | 
			
		||||
    std::array<AruidData, AruidIndexMax> data{};
 | 
			
		||||
    std::array<SharedMemoryHolder, AruidIndexMax> shared_memory_holder{};
 | 
			
		||||
    s32 ref_counter{};
 | 
			
		||||
 | 
			
		||||
    Core::System& system;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,18 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hid/emulated_console.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/console_six_axis.h"
 | 
			
		||||
#include "core/memory.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
 | 
			
		||||
 | 
			
		||||
ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
 | 
			
		||||
    : ControllerBase{hid_core_} {
 | 
			
		||||
ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                               ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory)
 | 
			
		||||
    : ControllerBase{hid_core_}, shared_memory{console_shared_memory} {
 | 
			
		||||
    console = hid_core.GetEmulatedConsole();
 | 
			
		||||
    static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
 | 
			
		||||
                  "ConsoleSharedMemory is bigger than the shared memory");
 | 
			
		||||
    shared_memory = std::construct_at(
 | 
			
		||||
        reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConsoleSixAxis::~ConsoleSixAxis() = default;
 | 
			
		||||
@@ -33,10 +28,10 @@ void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
 | 
			
		||||
    const auto motion_status = console->GetMotion();
 | 
			
		||||
 | 
			
		||||
    shared_memory->sampling_number++;
 | 
			
		||||
    shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
 | 
			
		||||
    shared_memory->verticalization_error = motion_status.verticalization_error;
 | 
			
		||||
    shared_memory->gyro_bias = motion_status.gyro_bias;
 | 
			
		||||
    shared_memory.sampling_number++;
 | 
			
		||||
    shared_memory.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
 | 
			
		||||
    shared_memory.verticalization_error = motion_status.verticalization_error;
 | 
			
		||||
    shared_memory.gyro_bias = motion_status.gyro_bias;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/vector_math.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
@@ -11,9 +10,12 @@ class EmulatedConsole;
 | 
			
		||||
} // namespace Core::HID
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct ConsoleSixAxisSensorSharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class ConsoleSixAxis final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                            ConsoleSixAxisSensorSharedMemoryFormat& console_shared_memory);
 | 
			
		||||
    ~ConsoleSixAxis() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
@@ -26,18 +28,7 @@ public:
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
 | 
			
		||||
    struct ConsoleSharedMemory {
 | 
			
		||||
        u64 sampling_number{};
 | 
			
		||||
        bool is_seven_six_axis_sensor_at_rest{};
 | 
			
		||||
        INSERT_PADDING_BYTES(3); // padding
 | 
			
		||||
        f32 verticalization_error{};
 | 
			
		||||
        Common::Vec3f gyro_bias{};
 | 
			
		||||
        INSERT_PADDING_BYTES(4); // padding
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
 | 
			
		||||
 | 
			
		||||
    ConsoleSharedMemory* shared_memory = nullptr;
 | 
			
		||||
    ConsoleSixAxisSensorSharedMemoryFormat& shared_memory;
 | 
			
		||||
    Core::HID::EmulatedConsole* console = nullptr;
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,6 @@ public:
 | 
			
		||||
 | 
			
		||||
    bool IsControllerActivated() const;
 | 
			
		||||
 | 
			
		||||
    static const std::size_t hid_entry_count = 17;
 | 
			
		||||
    static const std::size_t shared_memory_size = 0x40000;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    bool is_activated{false};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +1,19 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/settings.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hid/emulated_controller.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/debug_pad.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
 | 
			
		||||
 | 
			
		||||
DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
 | 
			
		||||
    : ControllerBase{hid_core_} {
 | 
			
		||||
    static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
 | 
			
		||||
                  "DebugPadSharedMemory is bigger than the shared memory");
 | 
			
		||||
    shared_memory = std::construct_at(
 | 
			
		||||
        reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 | 
			
		||||
DebugPad::DebugPad(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                   DebugPadSharedMemoryFormat& debug_pad_shared_memory)
 | 
			
		||||
    : ControllerBase{hid_core_}, shared_memory{debug_pad_shared_memory} {
 | 
			
		||||
    controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -30,12 +25,12 @@ void DebugPad::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
        shared_memory->debug_pad_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory->debug_pad_lifo.buffer_tail = 0;
 | 
			
		||||
        shared_memory.debug_pad_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory.debug_pad_lifo.buffer_tail = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    const auto& last_entry = shared_memory.debug_pad_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    next_state.sampling_number = last_entry.sampling_number + 1;
 | 
			
		||||
 | 
			
		||||
    if (Settings::values.debug_pad_enabled) {
 | 
			
		||||
@@ -49,7 +44,7 @@ void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        next_state.r_stick = stick_state.right;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_memory->debug_pad_lifo.WriteNextEntry(next_state);
 | 
			
		||||
    shared_memory.debug_pad_lifo.WriteNextEntry(next_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -3,21 +3,24 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/types/debug_pad_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
class EmulatedController;
 | 
			
		||||
struct DebugPadButton;
 | 
			
		||||
struct AnalogStickState;
 | 
			
		||||
} // namespace Core::HID
 | 
			
		||||
class HIDCore;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Core::Timing {
 | 
			
		||||
class CoreTiming;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct DebugPadSharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class DebugPad final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    explicit DebugPad(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                      DebugPadSharedMemoryFormat& debug_pad_shared_memory);
 | 
			
		||||
    ~DebugPad() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
@@ -30,35 +33,8 @@ public:
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // This is nn::hid::DebugPadAttribute
 | 
			
		||||
    struct DebugPadAttribute {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw{};
 | 
			
		||||
            BitField<0, 1, u32> connected;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::DebugPadState
 | 
			
		||||
    struct DebugPadState {
 | 
			
		||||
        s64 sampling_number{};
 | 
			
		||||
        DebugPadAttribute attribute{};
 | 
			
		||||
        Core::HID::DebugPadButton pad_state{};
 | 
			
		||||
        Core::HID::AnalogStickState r_stick{};
 | 
			
		||||
        Core::HID::AnalogStickState l_stick{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
 | 
			
		||||
 | 
			
		||||
    struct DebugPadSharedMemory {
 | 
			
		||||
        // This is nn::hid::detail::DebugPadLifo
 | 
			
		||||
        Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
 | 
			
		||||
        static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
 | 
			
		||||
        INSERT_PADDING_WORDS(0x4E);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size");
 | 
			
		||||
 | 
			
		||||
    DebugPadState next_state{};
 | 
			
		||||
    DebugPadSharedMemory* shared_memory = nullptr;
 | 
			
		||||
    DebugPadSharedMemoryFormat& shared_memory;
 | 
			
		||||
    Core::HID::EmulatedController* controller = nullptr;
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,15 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "common/math_util.h"
 | 
			
		||||
#include "common/settings.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/frontend/emu_window.h"
 | 
			
		||||
#include "core/hid/emulated_console.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/gesture.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
 | 
			
		||||
 | 
			
		||||
// HW is around 700, value is set to 400 to make it easier to trigger with mouse
 | 
			
		||||
constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s
 | 
			
		||||
constexpr f32 angle_threshold = 0.015f; // Threshold in radians
 | 
			
		||||
@@ -23,19 +21,15 @@ constexpr f32 Square(s32 num) {
 | 
			
		||||
    return static_cast<f32>(num * num);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
 | 
			
		||||
    : ControllerBase(hid_core_) {
 | 
			
		||||
    static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
 | 
			
		||||
                  "GestureSharedMemory is bigger than the shared memory");
 | 
			
		||||
    shared_memory = std::construct_at(
 | 
			
		||||
        reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 | 
			
		||||
Gesture::Gesture(Core::HID::HIDCore& hid_core_, GestureSharedMemoryFormat& gesture_shared_memory)
 | 
			
		||||
    : ControllerBase(hid_core_), shared_memory{gesture_shared_memory} {
 | 
			
		||||
    console = hid_core.GetEmulatedConsole();
 | 
			
		||||
}
 | 
			
		||||
Gesture::~Gesture() = default;
 | 
			
		||||
 | 
			
		||||
void Gesture::OnInit() {
 | 
			
		||||
    shared_memory->gesture_lifo.buffer_count = 0;
 | 
			
		||||
    shared_memory->gesture_lifo.buffer_tail = 0;
 | 
			
		||||
    shared_memory.gesture_lifo.buffer_count = 0;
 | 
			
		||||
    shared_memory.gesture_lifo.buffer_tail = 0;
 | 
			
		||||
    force_update = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -43,8 +37,8 @@ void Gesture::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
        shared_memory->gesture_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory->gesture_lifo.buffer_tail = 0;
 | 
			
		||||
        shared_memory.gesture_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory.gesture_lifo.buffer_tail = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -52,7 +46,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
 | 
			
		||||
    GestureProperties gesture = GetGestureProperties();
 | 
			
		||||
    f32 time_difference =
 | 
			
		||||
        static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) /
 | 
			
		||||
        static_cast<f32>(shared_memory.gesture_lifo.timestamp - last_update_timestamp) /
 | 
			
		||||
        (1000 * 1000 * 1000);
 | 
			
		||||
 | 
			
		||||
    // Only update if necessary
 | 
			
		||||
@@ -60,7 +54,7 @@ void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    last_update_timestamp = shared_memory->gesture_lifo.timestamp;
 | 
			
		||||
    last_update_timestamp = shared_memory.gesture_lifo.timestamp;
 | 
			
		||||
    UpdateGestureSharedMemory(gesture, time_difference);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -103,7 +97,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
 | 
			
		||||
    GestureType type = GestureType::Idle;
 | 
			
		||||
    GestureAttribute attributes{};
 | 
			
		||||
 | 
			
		||||
    const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    const auto& last_entry = shared_memory.gesture_lifo.ReadCurrentEntry().state;
 | 
			
		||||
 | 
			
		||||
    // Reset next state to default
 | 
			
		||||
    next_state.sampling_number = last_entry.sampling_number + 1;
 | 
			
		||||
@@ -133,7 +127,7 @@ void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_dif
 | 
			
		||||
    next_state.points = gesture.points;
 | 
			
		||||
    last_gesture = gesture;
 | 
			
		||||
 | 
			
		||||
    shared_memory->gesture_lifo.WriteNextEntry(next_state);
 | 
			
		||||
    shared_memory.gesture_lifo.WriteNextEntry(next_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
 | 
			
		||||
@@ -305,11 +299,11 @@ void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_
 | 
			
		||||
    next_state.direction = GestureDirection::Up;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Gesture::GestureState& Gesture::GetLastGestureEntry() const {
 | 
			
		||||
    return shared_memory->gesture_lifo.ReadCurrentEntry().state;
 | 
			
		||||
const GestureState& Gesture::GetLastGestureEntry() const {
 | 
			
		||||
    return shared_memory.gesture_lifo.ReadCurrentEntry().state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Gesture::GestureProperties Gesture::GetGestureProperties() {
 | 
			
		||||
GestureProperties Gesture::GetGestureProperties() {
 | 
			
		||||
    GestureProperties gesture;
 | 
			
		||||
    std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
 | 
			
		||||
    const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
 | 
			
		||||
 
 | 
			
		||||
@@ -4,17 +4,22 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/point.h"
 | 
			
		||||
#include "core/hid/emulated_console.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/types/touch_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
class EmulatedConsole;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct GestureSharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class Gesture final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    explicit Gesture(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                     GestureSharedMemoryFormat& gesture_shared_memory);
 | 
			
		||||
    ~Gesture() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
@@ -27,79 +32,6 @@ public:
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static constexpr size_t MAX_FINGERS = 16;
 | 
			
		||||
    static constexpr size_t MAX_POINTS = 4;
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::GestureType
 | 
			
		||||
    enum class GestureType : u32 {
 | 
			
		||||
        Idle,     // Nothing touching the screen
 | 
			
		||||
        Complete, // Set at the end of a touch event
 | 
			
		||||
        Cancel,   // Set when the number of fingers change
 | 
			
		||||
        Touch,    // A finger just touched the screen
 | 
			
		||||
        Press,    // Set if last type is touch and the finger hasn't moved
 | 
			
		||||
        Tap,      // Fast press then release
 | 
			
		||||
        Pan,      // All points moving together across the screen
 | 
			
		||||
        Swipe,    // Fast press movement and release of a single point
 | 
			
		||||
        Pinch,    // All points moving away/closer to the midpoint
 | 
			
		||||
        Rotate,   // All points rotating from the midpoint
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::GestureDirection
 | 
			
		||||
    enum class GestureDirection : u32 {
 | 
			
		||||
        None,
 | 
			
		||||
        Left,
 | 
			
		||||
        Up,
 | 
			
		||||
        Right,
 | 
			
		||||
        Down,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::GestureAttribute
 | 
			
		||||
    struct GestureAttribute {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw{};
 | 
			
		||||
 | 
			
		||||
            BitField<4, 1, u32> is_new_touch;
 | 
			
		||||
            BitField<8, 1, u32> is_double_tap;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::GestureState
 | 
			
		||||
    struct GestureState {
 | 
			
		||||
        s64 sampling_number{};
 | 
			
		||||
        s64 detection_count{};
 | 
			
		||||
        GestureType type{GestureType::Idle};
 | 
			
		||||
        GestureDirection direction{GestureDirection::None};
 | 
			
		||||
        Common::Point<s32> pos{};
 | 
			
		||||
        Common::Point<s32> delta{};
 | 
			
		||||
        f32 vel_x{};
 | 
			
		||||
        f32 vel_y{};
 | 
			
		||||
        GestureAttribute attributes{};
 | 
			
		||||
        f32 scale{};
 | 
			
		||||
        f32 rotation_angle{};
 | 
			
		||||
        s32 point_count{};
 | 
			
		||||
        std::array<Common::Point<s32>, 4> points{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    struct GestureProperties {
 | 
			
		||||
        std::array<Common::Point<s32>, MAX_POINTS> points{};
 | 
			
		||||
        std::size_t active_points{};
 | 
			
		||||
        Common::Point<s32> mid_point{};
 | 
			
		||||
        s64 detection_count{};
 | 
			
		||||
        u64 delta_time{};
 | 
			
		||||
        f32 average_distance{};
 | 
			
		||||
        f32 angle{};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct GestureSharedMemory {
 | 
			
		||||
        // This is nn::hid::detail::GestureLifo
 | 
			
		||||
        Lifo<GestureState, hid_entry_count> gesture_lifo{};
 | 
			
		||||
        static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
 | 
			
		||||
        INSERT_PADDING_WORDS(0x3E);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // Reads input from all available input engines
 | 
			
		||||
    void ReadTouchInput();
 | 
			
		||||
 | 
			
		||||
@@ -142,7 +74,7 @@ private:
 | 
			
		||||
    GestureProperties GetGestureProperties();
 | 
			
		||||
 | 
			
		||||
    GestureState next_state{};
 | 
			
		||||
    GestureSharedMemory* shared_memory = nullptr;
 | 
			
		||||
    GestureSharedMemoryFormat& shared_memory;
 | 
			
		||||
    Core::HID::EmulatedConsole* console = nullptr;
 | 
			
		||||
 | 
			
		||||
    std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,18 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/settings.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hid/emulated_devices.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/keyboard.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
 | 
			
		||||
 | 
			
		||||
Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
 | 
			
		||||
    : ControllerBase{hid_core_} {
 | 
			
		||||
    static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
 | 
			
		||||
                  "KeyboardSharedMemory is bigger than the shared memory");
 | 
			
		||||
    shared_memory = std::construct_at(
 | 
			
		||||
        reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 | 
			
		||||
Keyboard::Keyboard(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                   KeyboardSharedMemoryFormat& keyboard_shared_memory)
 | 
			
		||||
    : ControllerBase{hid_core_}, shared_memory{keyboard_shared_memory} {
 | 
			
		||||
    emulated_devices = hid_core.GetEmulatedDevices();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -29,12 +24,12 @@ void Keyboard::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
        shared_memory->keyboard_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory->keyboard_lifo.buffer_tail = 0;
 | 
			
		||||
        shared_memory.keyboard_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory.keyboard_lifo.buffer_tail = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    const auto& last_entry = shared_memory.keyboard_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    next_state.sampling_number = last_entry.sampling_number + 1;
 | 
			
		||||
 | 
			
		||||
    if (Settings::values.keyboard_enabled) {
 | 
			
		||||
@@ -46,7 +41,7 @@ void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        next_state.attribute.is_connected.Assign(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_memory->keyboard_lifo.WriteNextEntry(next_state);
 | 
			
		||||
    shared_memory.keyboard_lifo.WriteNextEntry(next_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -3,20 +3,16 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
class EmulatedDevices;
 | 
			
		||||
struct KeyboardModifier;
 | 
			
		||||
struct KeyboardKey;
 | 
			
		||||
} // namespace Core::HID
 | 
			
		||||
#include "core/hle/service/hid/controllers/types/keyboard_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct KeyboardSharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class Keyboard final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    explicit Keyboard(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                      KeyboardSharedMemoryFormat& keyboard_shared_memory);
 | 
			
		||||
    ~Keyboard() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
@@ -29,25 +25,8 @@ public:
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // This is nn::hid::detail::KeyboardState
 | 
			
		||||
    struct KeyboardState {
 | 
			
		||||
        s64 sampling_number{};
 | 
			
		||||
        Core::HID::KeyboardModifier modifier{};
 | 
			
		||||
        Core::HID::KeyboardAttribute attribute{};
 | 
			
		||||
        Core::HID::KeyboardKey key{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    struct KeyboardSharedMemory {
 | 
			
		||||
        // This is nn::hid::detail::KeyboardLifo
 | 
			
		||||
        Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
 | 
			
		||||
        static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
 | 
			
		||||
        INSERT_PADDING_WORDS(0xA);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size");
 | 
			
		||||
 | 
			
		||||
    KeyboardState next_state{};
 | 
			
		||||
    KeyboardSharedMemory* shared_memory = nullptr;
 | 
			
		||||
    KeyboardSharedMemoryFormat& shared_memory;
 | 
			
		||||
    Core::HID::EmulatedDevices* emulated_devices = nullptr;
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,17 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/frontend/emu_window.h"
 | 
			
		||||
#include "core/hid/emulated_devices.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/mouse.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
 | 
			
		||||
 | 
			
		||||
Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
 | 
			
		||||
    static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
 | 
			
		||||
                  "MouseSharedMemory is bigger than the shared memory");
 | 
			
		||||
    shared_memory = std::construct_at(
 | 
			
		||||
        reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 | 
			
		||||
Mouse::Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory)
 | 
			
		||||
    : ControllerBase{hid_core_}, shared_memory{mouse_shared_memory} {
 | 
			
		||||
    emulated_devices = hid_core.GetEmulatedDevices();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -27,14 +22,14 @@ void Mouse::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
        shared_memory->mouse_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory->mouse_lifo.buffer_tail = 0;
 | 
			
		||||
        shared_memory.mouse_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory.mouse_lifo.buffer_tail = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    next_state = {};
 | 
			
		||||
 | 
			
		||||
    const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    const auto& last_entry = shared_memory.mouse_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    next_state.sampling_number = last_entry.sampling_number + 1;
 | 
			
		||||
 | 
			
		||||
    if (Settings::values.mouse_enabled) {
 | 
			
		||||
@@ -53,7 +48,7 @@ void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        next_state.button = mouse_button_state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_memory->mouse_lifo.WriteNextEntry(next_state);
 | 
			
		||||
    shared_memory.mouse_lifo.WriteNextEntry(next_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
class EmulatedDevices;
 | 
			
		||||
@@ -14,9 +12,11 @@ struct AnalogStickState;
 | 
			
		||||
} // namespace Core::HID
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct MouseSharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class Mouse final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    explicit Mouse(Core::HID::HIDCore& hid_core_, MouseSharedMemoryFormat& mouse_shared_memory);
 | 
			
		||||
    ~Mouse() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
@@ -29,17 +29,9 @@ public:
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    struct MouseSharedMemory {
 | 
			
		||||
        // This is nn::hid::detail::MouseLifo
 | 
			
		||||
        Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
 | 
			
		||||
        static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
 | 
			
		||||
        INSERT_PADDING_WORDS(0x2C);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size");
 | 
			
		||||
 | 
			
		||||
    Core::HID::MouseState next_state{};
 | 
			
		||||
    Core::HID::AnalogStickState last_mouse_wheel_state{};
 | 
			
		||||
    MouseSharedMemory* shared_memory = nullptr;
 | 
			
		||||
    MouseSharedMemoryFormat& shared_memory;
 | 
			
		||||
    Core::HID::EmulatedDevices* emulated_devices = nullptr;
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -17,12 +17,12 @@
 | 
			
		||||
#include "core/hle/kernel/k_event.h"
 | 
			
		||||
#include "core/hle/kernel/k_readable_event.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/npad.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
#include "core/hle/service/hid/errors.h"
 | 
			
		||||
#include "core/hle/service/hid/hid_util.h"
 | 
			
		||||
#include "core/hle/service/kernel_helpers.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t NPAD_OFFSET = 0x9A00;
 | 
			
		||||
constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
 | 
			
		||||
    Core::HID::NpadIdType::Player1,  Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
 | 
			
		||||
    Core::HID::NpadIdType::Player4,  Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
 | 
			
		||||
@@ -30,14 +30,12 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
 | 
			
		||||
    Core::HID::NpadIdType::Handheld,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
 | 
			
		||||
NPad::NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
 | 
			
		||||
           KernelHelpers::ServiceContext& service_context_)
 | 
			
		||||
    : ControllerBase{hid_core_}, service_context{service_context_} {
 | 
			
		||||
    static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
 | 
			
		||||
    for (std::size_t i = 0; i < controller_data.size(); ++i) {
 | 
			
		||||
        auto& controller = controller_data[i];
 | 
			
		||||
        controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>(
 | 
			
		||||
            raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));
 | 
			
		||||
        controller.shared_memory = &npad_shared_memory_format.npad_entry[i].internal_state;
 | 
			
		||||
        controller.device = hid_core.GetEmulatedControllerByIndex(i);
 | 
			
		||||
        controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
 | 
			
		||||
            Core::HID::DEFAULT_VIBRATION_VALUE;
 | 
			
		||||
@@ -617,7 +615,7 @@ void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
 | 
			
		||||
    hold_type = joy_hold_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::NpadJoyHoldType NPad::GetHoldType() const {
 | 
			
		||||
NpadJoyHoldType NPad::GetHoldType() const {
 | 
			
		||||
    return hold_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -630,7 +628,7 @@ void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_m
 | 
			
		||||
    handheld_activation_mode = activation_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
 | 
			
		||||
NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
 | 
			
		||||
    return handheld_activation_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -638,7 +636,7 @@ void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
 | 
			
		||||
    communication_mode = communication_mode_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
 | 
			
		||||
NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
 | 
			
		||||
    return communication_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -978,27 +976,27 @@ Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
NpadSixAxisSensorLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
NpadSixAxisSensorLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
NpadSixAxisSensorLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
NpadSixAxisSensorLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
NpadSixAxisSensorLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
NpadSixAxisSensorLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1343,7 +1341,7 @@ const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,10 @@
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <span>
 | 
			
		||||
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/types/npad_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
class EmulatedController;
 | 
			
		||||
@@ -32,10 +30,13 @@ class ServiceContext;
 | 
			
		||||
union Result;
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct NpadInternalState;
 | 
			
		||||
struct NpadSixAxisSensorLifo;
 | 
			
		||||
struct NpadSharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class NPad final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
 | 
			
		||||
    explicit NPad(Core::HID::HIDCore& hid_core_, NpadSharedMemoryFormat& npad_shared_memory_format,
 | 
			
		||||
                  KernelHelpers::ServiceContext& service_context_);
 | 
			
		||||
    ~NPad() override;
 | 
			
		||||
 | 
			
		||||
@@ -48,89 +49,6 @@ public:
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadJoyHoldType
 | 
			
		||||
    enum class NpadJoyHoldType : u64 {
 | 
			
		||||
        Vertical = 0,
 | 
			
		||||
        Horizontal = 1,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadJoyAssignmentMode
 | 
			
		||||
    enum class NpadJoyAssignmentMode : u32 {
 | 
			
		||||
        Dual = 0,
 | 
			
		||||
        Single = 1,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadJoyDeviceType
 | 
			
		||||
    enum class NpadJoyDeviceType : s64 {
 | 
			
		||||
        Left = 0,
 | 
			
		||||
        Right = 1,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadHandheldActivationMode
 | 
			
		||||
    enum class NpadHandheldActivationMode : u64 {
 | 
			
		||||
        Dual = 0,
 | 
			
		||||
        Single = 1,
 | 
			
		||||
        None = 2,
 | 
			
		||||
        MaxActivationMode = 3,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::system::AppletFooterUiAttributesSet
 | 
			
		||||
    struct AppletFooterUiAttributes {
 | 
			
		||||
        INSERT_PADDING_BYTES(0x4);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::system::AppletFooterUiType
 | 
			
		||||
    enum class AppletFooterUiType : u8 {
 | 
			
		||||
        None = 0,
 | 
			
		||||
        HandheldNone = 1,
 | 
			
		||||
        HandheldJoyConLeftOnly = 2,
 | 
			
		||||
        HandheldJoyConRightOnly = 3,
 | 
			
		||||
        HandheldJoyConLeftJoyConRight = 4,
 | 
			
		||||
        JoyDual = 5,
 | 
			
		||||
        JoyDualLeftOnly = 6,
 | 
			
		||||
        JoyDualRightOnly = 7,
 | 
			
		||||
        JoyLeftHorizontal = 8,
 | 
			
		||||
        JoyLeftVertical = 9,
 | 
			
		||||
        JoyRightHorizontal = 10,
 | 
			
		||||
        JoyRightVertical = 11,
 | 
			
		||||
        SwitchProController = 12,
 | 
			
		||||
        CompatibleProController = 13,
 | 
			
		||||
        CompatibleJoyCon = 14,
 | 
			
		||||
        LarkHvc1 = 15,
 | 
			
		||||
        LarkHvc2 = 16,
 | 
			
		||||
        LarkNesLeft = 17,
 | 
			
		||||
        LarkNesRight = 18,
 | 
			
		||||
        Lucia = 19,
 | 
			
		||||
        Verification = 20,
 | 
			
		||||
        Lagon = 21,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    using AppletFooterUiVariant = u8;
 | 
			
		||||
 | 
			
		||||
    // This is "nn::hid::system::AppletDetailedUiType".
 | 
			
		||||
    struct AppletDetailedUiType {
 | 
			
		||||
        AppletFooterUiVariant ui_variant;
 | 
			
		||||
        INSERT_PADDING_BYTES(0x2);
 | 
			
		||||
        AppletFooterUiType footer;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
 | 
			
		||||
    // This is nn::hid::NpadCommunicationMode
 | 
			
		||||
    enum class NpadCommunicationMode : u64 {
 | 
			
		||||
        Mode_5ms = 0,
 | 
			
		||||
        Mode_10ms = 1,
 | 
			
		||||
        Mode_15ms = 2,
 | 
			
		||||
        Default = 3,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum class NpadRevision : u32 {
 | 
			
		||||
        Revision0 = 0,
 | 
			
		||||
        Revision1 = 1,
 | 
			
		||||
        Revision2 = 2,
 | 
			
		||||
        Revision3 = 3,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
 | 
			
		||||
 | 
			
		||||
    void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
 | 
			
		||||
    Core::HID::NpadStyleTag GetSupportedStyleSet() const;
 | 
			
		||||
 | 
			
		||||
@@ -188,12 +106,12 @@ public:
 | 
			
		||||
    Result ResetIsSixAxisSensorDeviceNewlyAssigned(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle);
 | 
			
		||||
 | 
			
		||||
    SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    NpadSixAxisSensorLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    NpadSixAxisSensorLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    NpadSixAxisSensorLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    NpadSixAxisSensorLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    NpadSixAxisSensorLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    NpadSixAxisSensorLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
 | 
			
		||||
 | 
			
		||||
    Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
 | 
			
		||||
    Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
 | 
			
		||||
@@ -221,214 +139,6 @@ public:
 | 
			
		||||
    AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static constexpr std::size_t NPAD_COUNT = 10;
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::detail::ColorAttribute
 | 
			
		||||
    enum class ColorAttribute : u32 {
 | 
			
		||||
        Ok = 0,
 | 
			
		||||
        ReadError = 1,
 | 
			
		||||
        NoController = 2,
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::detail::NpadFullKeyColorState
 | 
			
		||||
    struct NpadFullKeyColorState {
 | 
			
		||||
        ColorAttribute attribute{ColorAttribute::NoController};
 | 
			
		||||
        Core::HID::NpadControllerColor fullkey{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::detail::NpadJoyColorState
 | 
			
		||||
    struct NpadJoyColorState {
 | 
			
		||||
        ColorAttribute attribute{ColorAttribute::NoController};
 | 
			
		||||
        Core::HID::NpadControllerColor left{};
 | 
			
		||||
        Core::HID::NpadControllerColor right{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadAttribute
 | 
			
		||||
    struct NpadAttribute {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw{};
 | 
			
		||||
            BitField<0, 1, u32> is_connected;
 | 
			
		||||
            BitField<1, 1, u32> is_wired;
 | 
			
		||||
            BitField<2, 1, u32> is_left_connected;
 | 
			
		||||
            BitField<3, 1, u32> is_left_wired;
 | 
			
		||||
            BitField<4, 1, u32> is_right_connected;
 | 
			
		||||
            BitField<5, 1, u32> is_right_wired;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadFullKeyState
 | 
			
		||||
    // This is nn::hid::NpadHandheldState
 | 
			
		||||
    // This is nn::hid::NpadJoyDualState
 | 
			
		||||
    // This is nn::hid::NpadJoyLeftState
 | 
			
		||||
    // This is nn::hid::NpadJoyRightState
 | 
			
		||||
    // This is nn::hid::NpadPalmaState
 | 
			
		||||
    // This is nn::hid::NpadSystemExtState
 | 
			
		||||
    struct NPadGenericState {
 | 
			
		||||
        s64_le sampling_number{};
 | 
			
		||||
        Core::HID::NpadButtonState npad_buttons{};
 | 
			
		||||
        Core::HID::AnalogStickState l_stick{};
 | 
			
		||||
        Core::HID::AnalogStickState r_stick{};
 | 
			
		||||
        NpadAttribute connection_status{};
 | 
			
		||||
        INSERT_PADDING_BYTES(4); // Reserved
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::server::NpadGcTriggerState
 | 
			
		||||
    struct NpadGcTriggerState {
 | 
			
		||||
        s64 sampling_number{};
 | 
			
		||||
        s32 l_analog{};
 | 
			
		||||
        s32 r_analog{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadSystemProperties
 | 
			
		||||
    struct NPadSystemProperties {
 | 
			
		||||
        union {
 | 
			
		||||
            s64 raw{};
 | 
			
		||||
            BitField<0, 1, s64> is_charging_joy_dual;
 | 
			
		||||
            BitField<1, 1, s64> is_charging_joy_left;
 | 
			
		||||
            BitField<2, 1, s64> is_charging_joy_right;
 | 
			
		||||
            BitField<3, 1, s64> is_powered_joy_dual;
 | 
			
		||||
            BitField<4, 1, s64> is_powered_joy_left;
 | 
			
		||||
            BitField<5, 1, s64> is_powered_joy_right;
 | 
			
		||||
            BitField<9, 1, s64> is_system_unsupported_button;
 | 
			
		||||
            BitField<10, 1, s64> is_system_ext_unsupported_button;
 | 
			
		||||
            BitField<11, 1, s64> is_vertical;
 | 
			
		||||
            BitField<12, 1, s64> is_horizontal;
 | 
			
		||||
            BitField<13, 1, s64> use_plus;
 | 
			
		||||
            BitField<14, 1, s64> use_minus;
 | 
			
		||||
            BitField<15, 1, s64> use_directional_buttons;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadSystemButtonProperties
 | 
			
		||||
    struct NpadSystemButtonProperties {
 | 
			
		||||
        union {
 | 
			
		||||
            s32 raw{};
 | 
			
		||||
            BitField<0, 1, s32> is_home_button_protection_enabled;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NpadSystemButtonProperties) == 0x4,
 | 
			
		||||
                  "NPadButtonProperties is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::system::DeviceType
 | 
			
		||||
    struct DeviceType {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw{};
 | 
			
		||||
            BitField<0, 1, s32> fullkey;
 | 
			
		||||
            BitField<1, 1, s32> debug_pad;
 | 
			
		||||
            BitField<2, 1, s32> handheld_left;
 | 
			
		||||
            BitField<3, 1, s32> handheld_right;
 | 
			
		||||
            BitField<4, 1, s32> joycon_left;
 | 
			
		||||
            BitField<5, 1, s32> joycon_right;
 | 
			
		||||
            BitField<6, 1, s32> palma;
 | 
			
		||||
            BitField<7, 1, s32> lark_hvc_left;
 | 
			
		||||
            BitField<8, 1, s32> lark_hvc_right;
 | 
			
		||||
            BitField<9, 1, s32> lark_nes_left;
 | 
			
		||||
            BitField<10, 1, s32> lark_nes_right;
 | 
			
		||||
            BitField<11, 1, s32> handheld_lark_hvc_left;
 | 
			
		||||
            BitField<12, 1, s32> handheld_lark_hvc_right;
 | 
			
		||||
            BitField<13, 1, s32> handheld_lark_nes_left;
 | 
			
		||||
            BitField<14, 1, s32> handheld_lark_nes_right;
 | 
			
		||||
            BitField<15, 1, s32> lucia;
 | 
			
		||||
            BitField<16, 1, s32> lagon;
 | 
			
		||||
            BitField<17, 1, s32> lager;
 | 
			
		||||
            BitField<31, 1, s32> system;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
 | 
			
		||||
    struct NfcXcdDeviceHandleStateImpl {
 | 
			
		||||
        u64 handle{};
 | 
			
		||||
        bool is_available{};
 | 
			
		||||
        bool is_activated{};
 | 
			
		||||
        INSERT_PADDING_BYTES(0x6); // Reserved
 | 
			
		||||
        u64 sampling_number{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
 | 
			
		||||
                  "NfcXcdDeviceHandleStateImpl is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadLarkType
 | 
			
		||||
    enum class NpadLarkType : u32 {
 | 
			
		||||
        Invalid,
 | 
			
		||||
        H1,
 | 
			
		||||
        H2,
 | 
			
		||||
        NL,
 | 
			
		||||
        NR,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadLuciaType
 | 
			
		||||
    enum class NpadLuciaType : u32 {
 | 
			
		||||
        Invalid,
 | 
			
		||||
        J,
 | 
			
		||||
        E,
 | 
			
		||||
        U,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadLagonType
 | 
			
		||||
    enum class NpadLagonType : u32 {
 | 
			
		||||
        Invalid,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::NpadLagerType
 | 
			
		||||
    enum class NpadLagerType : u32 {
 | 
			
		||||
        Invalid,
 | 
			
		||||
        J,
 | 
			
		||||
        E,
 | 
			
		||||
        U,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::detail::NpadInternalState
 | 
			
		||||
    struct NpadInternalState {
 | 
			
		||||
        Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
 | 
			
		||||
        NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
 | 
			
		||||
        NpadFullKeyColorState fullkey_color{};
 | 
			
		||||
        NpadJoyColorState joycon_color{};
 | 
			
		||||
        Lifo<NPadGenericState, hid_entry_count> fullkey_lifo{};
 | 
			
		||||
        Lifo<NPadGenericState, hid_entry_count> handheld_lifo{};
 | 
			
		||||
        Lifo<NPadGenericState, hid_entry_count> joy_dual_lifo{};
 | 
			
		||||
        Lifo<NPadGenericState, hid_entry_count> joy_left_lifo{};
 | 
			
		||||
        Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
 | 
			
		||||
        Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
 | 
			
		||||
        Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
 | 
			
		||||
        Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
 | 
			
		||||
        Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
 | 
			
		||||
        Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
 | 
			
		||||
        Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
 | 
			
		||||
        Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
 | 
			
		||||
        Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
 | 
			
		||||
        DeviceType device_type{};
 | 
			
		||||
        INSERT_PADDING_BYTES(0x4); // Reserved
 | 
			
		||||
        NPadSystemProperties system_properties{};
 | 
			
		||||
        NpadSystemButtonProperties button_properties{};
 | 
			
		||||
        Core::HID::NpadBatteryLevel battery_level_dual{};
 | 
			
		||||
        Core::HID::NpadBatteryLevel battery_level_left{};
 | 
			
		||||
        Core::HID::NpadBatteryLevel battery_level_right{};
 | 
			
		||||
        AppletFooterUiAttributes applet_footer_attributes{};
 | 
			
		||||
        AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
 | 
			
		||||
        INSERT_PADDING_BYTES(0x5B); // Reserved
 | 
			
		||||
        INSERT_PADDING_BYTES(0x20); // Unknown
 | 
			
		||||
        Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};
 | 
			
		||||
        NpadLarkType lark_type_l_and_main{};
 | 
			
		||||
        NpadLarkType lark_type_r{};
 | 
			
		||||
        NpadLuciaType lucia_type{};
 | 
			
		||||
        NpadLagonType lagon_type{};
 | 
			
		||||
        NpadLagerType lager_type{};
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_left_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_right_properties;
 | 
			
		||||
        INSERT_PADDING_BYTES(0xc06); // Unknown
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    struct VibrationData {
 | 
			
		||||
        bool device_mounted{};
 | 
			
		||||
        Core::HID::VibrationValue latest_vibration_value{};
 | 
			
		||||
@@ -479,7 +189,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    std::atomic<u64> press_state{};
 | 
			
		||||
 | 
			
		||||
    std::array<NpadControllerData, NPAD_COUNT> controller_data{};
 | 
			
		||||
    std::array<NpadControllerData, NpadCount> controller_data{};
 | 
			
		||||
    KernelHelpers::ServiceContext& service_context;
 | 
			
		||||
    std::mutex mutex;
 | 
			
		||||
    std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
 | 
			
		||||
 
 | 
			
		||||
@@ -12,8 +12,7 @@
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
 | 
			
		||||
Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
 | 
			
		||||
             KernelHelpers::ServiceContext& service_context_)
 | 
			
		||||
Palma::Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_)
 | 
			
		||||
    : ControllerBase{hid_core_}, service_context{service_context_} {
 | 
			
		||||
    controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
 | 
			
		||||
    operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
 | 
			
		||||
 
 | 
			
		||||
@@ -97,8 +97,7 @@ public:
 | 
			
		||||
    static_assert(sizeof(PalmaConnectionHandle) == 0x8,
 | 
			
		||||
                  "PalmaConnectionHandle has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
 | 
			
		||||
                   KernelHelpers::ServiceContext& service_context_);
 | 
			
		||||
    explicit Palma(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_);
 | 
			
		||||
    ~Palma() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										240
									
								
								src/core/hle/service/hid/controllers/shared_memory_format.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								src/core/hle/service/hid/controllers/shared_memory_format.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,240 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/vector_math.h"
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
#include "core/hle/service/hid//controllers/types/debug_pad_types.h"
 | 
			
		||||
#include "core/hle/service/hid//controllers/types/keyboard_types.h"
 | 
			
		||||
#include "core/hle/service/hid//controllers/types/mouse_types.h"
 | 
			
		||||
#include "core/hle/service/hid//controllers/types/npad_types.h"
 | 
			
		||||
#include "core/hle/service/hid//controllers/types/touch_types.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
static const std::size_t HidEntryCount = 17;
 | 
			
		||||
 | 
			
		||||
struct CommonHeader {
 | 
			
		||||
    s64 timestamp{};
 | 
			
		||||
    s64 total_entry_count{};
 | 
			
		||||
    s64 last_entry_index{};
 | 
			
		||||
    s64 entry_count{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::DebugPadSharedMemoryFormat
 | 
			
		||||
struct DebugPadSharedMemoryFormat {
 | 
			
		||||
    // This is nn::hid::detail::DebugPadLifo
 | 
			
		||||
    Lifo<DebugPadState, HidEntryCount> debug_pad_lifo{};
 | 
			
		||||
    static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
 | 
			
		||||
    INSERT_PADDING_WORDS(0x4E);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(DebugPadSharedMemoryFormat) == 0x400,
 | 
			
		||||
              "DebugPadSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::TouchScreenSharedMemoryFormat
 | 
			
		||||
struct TouchScreenSharedMemoryFormat {
 | 
			
		||||
    // This is nn::hid::detail::TouchScreenLifo
 | 
			
		||||
    Lifo<TouchScreenState, HidEntryCount> touch_screen_lifo{};
 | 
			
		||||
    static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
 | 
			
		||||
    INSERT_PADDING_WORDS(0xF2);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(TouchScreenSharedMemoryFormat) == 0x3000,
 | 
			
		||||
              "TouchScreenSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::MouseSharedMemoryFormat
 | 
			
		||||
struct MouseSharedMemoryFormat {
 | 
			
		||||
    // This is nn::hid::detail::MouseLifo
 | 
			
		||||
    Lifo<Core::HID::MouseState, HidEntryCount> mouse_lifo{};
 | 
			
		||||
    static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
 | 
			
		||||
    INSERT_PADDING_WORDS(0x2C);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(MouseSharedMemoryFormat) == 0x400,
 | 
			
		||||
              "MouseSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::KeyboardSharedMemoryFormat
 | 
			
		||||
struct KeyboardSharedMemoryFormat {
 | 
			
		||||
    // This is nn::hid::detail::KeyboardLifo
 | 
			
		||||
    Lifo<KeyboardState, HidEntryCount> keyboard_lifo{};
 | 
			
		||||
    static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
 | 
			
		||||
    INSERT_PADDING_WORDS(0xA);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(KeyboardSharedMemoryFormat) == 0x400,
 | 
			
		||||
              "KeyboardSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::DigitizerSharedMemoryFormat
 | 
			
		||||
struct DigitizerSharedMemoryFormat {
 | 
			
		||||
    CommonHeader header;
 | 
			
		||||
    INSERT_PADDING_BYTES(0xFE0);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(DigitizerSharedMemoryFormat) == 0x1000,
 | 
			
		||||
              "DigitizerSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::HomeButtonSharedMemoryFormat
 | 
			
		||||
struct HomeButtonSharedMemoryFormat {
 | 
			
		||||
    CommonHeader header;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x1E0);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(HomeButtonSharedMemoryFormat) == 0x200,
 | 
			
		||||
              "HomeButtonSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::SleepButtonSharedMemoryFormat
 | 
			
		||||
struct SleepButtonSharedMemoryFormat {
 | 
			
		||||
    CommonHeader header;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x1E0);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(SleepButtonSharedMemoryFormat) == 0x200,
 | 
			
		||||
              "SleepButtonSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::CaptureButtonSharedMemoryFormat
 | 
			
		||||
struct CaptureButtonSharedMemoryFormat {
 | 
			
		||||
    CommonHeader header;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x1E0);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(CaptureButtonSharedMemoryFormat) == 0x200,
 | 
			
		||||
              "CaptureButtonSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::InputDetectorSharedMemoryFormat
 | 
			
		||||
struct InputDetectorSharedMemoryFormat {
 | 
			
		||||
    CommonHeader header;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x7E0);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(InputDetectorSharedMemoryFormat) == 0x800,
 | 
			
		||||
              "InputDetectorSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::UniquePadSharedMemoryFormat
 | 
			
		||||
struct UniquePadSharedMemoryFormat {
 | 
			
		||||
    CommonHeader header;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x3FE0);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(UniquePadSharedMemoryFormat) == 0x4000,
 | 
			
		||||
              "UniquePadSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::NpadSixAxisSensorLifo
 | 
			
		||||
struct NpadSixAxisSensorLifo {
 | 
			
		||||
    Lifo<Core::HID::SixAxisSensorState, HidEntryCount> lifo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::NpadInternalState
 | 
			
		||||
struct NpadInternalState {
 | 
			
		||||
    Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
 | 
			
		||||
    NpadJoyAssignmentMode assignment_mode{NpadJoyAssignmentMode::Dual};
 | 
			
		||||
    NpadFullKeyColorState fullkey_color{};
 | 
			
		||||
    NpadJoyColorState joycon_color{};
 | 
			
		||||
    Lifo<NPadGenericState, HidEntryCount> fullkey_lifo{};
 | 
			
		||||
    Lifo<NPadGenericState, HidEntryCount> handheld_lifo{};
 | 
			
		||||
    Lifo<NPadGenericState, HidEntryCount> joy_dual_lifo{};
 | 
			
		||||
    Lifo<NPadGenericState, HidEntryCount> joy_left_lifo{};
 | 
			
		||||
    Lifo<NPadGenericState, HidEntryCount> joy_right_lifo{};
 | 
			
		||||
    Lifo<NPadGenericState, HidEntryCount> palma_lifo{};
 | 
			
		||||
    Lifo<NPadGenericState, HidEntryCount> system_ext_lifo{};
 | 
			
		||||
    NpadSixAxisSensorLifo sixaxis_fullkey_lifo{};
 | 
			
		||||
    NpadSixAxisSensorLifo sixaxis_handheld_lifo{};
 | 
			
		||||
    NpadSixAxisSensorLifo sixaxis_dual_left_lifo{};
 | 
			
		||||
    NpadSixAxisSensorLifo sixaxis_dual_right_lifo{};
 | 
			
		||||
    NpadSixAxisSensorLifo sixaxis_left_lifo{};
 | 
			
		||||
    NpadSixAxisSensorLifo sixaxis_right_lifo{};
 | 
			
		||||
    DeviceType device_type{};
 | 
			
		||||
    INSERT_PADDING_BYTES(0x4); // Reserved
 | 
			
		||||
    NPadSystemProperties system_properties{};
 | 
			
		||||
    NpadSystemButtonProperties button_properties{};
 | 
			
		||||
    Core::HID::NpadBatteryLevel battery_level_dual{};
 | 
			
		||||
    Core::HID::NpadBatteryLevel battery_level_left{};
 | 
			
		||||
    Core::HID::NpadBatteryLevel battery_level_right{};
 | 
			
		||||
    AppletFooterUiAttributes applet_footer_attributes{};
 | 
			
		||||
    AppletFooterUiType applet_footer_type{AppletFooterUiType::None};
 | 
			
		||||
    INSERT_PADDING_BYTES(0x5B); // Reserved
 | 
			
		||||
    INSERT_PADDING_BYTES(0x20); // Unknown
 | 
			
		||||
    Lifo<NpadGcTriggerState, HidEntryCount> gc_trigger_lifo{};
 | 
			
		||||
    NpadLarkType lark_type_l_and_main{};
 | 
			
		||||
    NpadLarkType lark_type_r{};
 | 
			
		||||
    NpadLuciaType lucia_type{};
 | 
			
		||||
    NpadLagerType lager_type{};
 | 
			
		||||
    Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
 | 
			
		||||
    Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
 | 
			
		||||
    Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
 | 
			
		||||
    Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
 | 
			
		||||
    Core::HID::SixAxisSensorProperties sixaxis_left_properties;
 | 
			
		||||
    Core::HID::SixAxisSensorProperties sixaxis_right_properties;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadInternalState) == 0x43F8, "NpadInternalState is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::NpadSharedMemoryEntry
 | 
			
		||||
struct NpadSharedMemoryEntry {
 | 
			
		||||
    NpadInternalState internal_state;
 | 
			
		||||
    INSERT_PADDING_BYTES(0xC08);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadSharedMemoryEntry) == 0x5000, "NpadSharedMemoryEntry is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::NpadSharedMemoryFormat
 | 
			
		||||
struct NpadSharedMemoryFormat {
 | 
			
		||||
    std::array<NpadSharedMemoryEntry, NpadCount> npad_entry;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadSharedMemoryFormat) == 0x32000,
 | 
			
		||||
              "NpadSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::GestureSharedMemoryFormat
 | 
			
		||||
struct GestureSharedMemoryFormat {
 | 
			
		||||
    // This is nn::hid::detail::GestureLifo
 | 
			
		||||
    Lifo<GestureState, HidEntryCount> gesture_lifo{};
 | 
			
		||||
    static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
 | 
			
		||||
    INSERT_PADDING_WORDS(0x3E);
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(GestureSharedMemoryFormat) == 0x800,
 | 
			
		||||
              "GestureSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
 | 
			
		||||
struct ConsoleSixAxisSensorSharedMemoryFormat {
 | 
			
		||||
    u64 sampling_number{};
 | 
			
		||||
    bool is_seven_six_axis_sensor_at_rest{};
 | 
			
		||||
    INSERT_PADDING_BYTES(3); // padding
 | 
			
		||||
    f32 verticalization_error{};
 | 
			
		||||
    Common::Vec3f gyro_bias{};
 | 
			
		||||
    INSERT_PADDING_BYTES(4); // padding
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20,
 | 
			
		||||
              "ConsoleSixAxisSensorSharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::SharedMemoryFormat
 | 
			
		||||
struct SharedMemoryFormat {
 | 
			
		||||
    void Initialize() {}
 | 
			
		||||
 | 
			
		||||
    DebugPadSharedMemoryFormat debug_pad;
 | 
			
		||||
    TouchScreenSharedMemoryFormat touch_screen;
 | 
			
		||||
    MouseSharedMemoryFormat mouse;
 | 
			
		||||
    KeyboardSharedMemoryFormat keyboard;
 | 
			
		||||
    DigitizerSharedMemoryFormat digitizer;
 | 
			
		||||
    HomeButtonSharedMemoryFormat home_button;
 | 
			
		||||
    SleepButtonSharedMemoryFormat sleep_button;
 | 
			
		||||
    CaptureButtonSharedMemoryFormat capture_button;
 | 
			
		||||
    InputDetectorSharedMemoryFormat input_detector;
 | 
			
		||||
    UniquePadSharedMemoryFormat unique_pad;
 | 
			
		||||
    NpadSharedMemoryFormat npad;
 | 
			
		||||
    GestureSharedMemoryFormat gesture;
 | 
			
		||||
    ConsoleSixAxisSensorSharedMemoryFormat console;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x19E0);
 | 
			
		||||
    MouseSharedMemoryFormat debug_mouse;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x2000);
 | 
			
		||||
};
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, debug_pad) == 0x0, "debug_pad has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, touch_screen) == 0x400, "touch_screen has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, mouse) == 0x3400, "mouse has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, keyboard) == 0x3800, "keyboard has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, digitizer) == 0x3C00, "digitizer has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, home_button) == 0x4C00, "home_button has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, sleep_button) == 0x4E00,
 | 
			
		||||
              "sleep_button has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, capture_button) == 0x5000,
 | 
			
		||||
              "capture_button has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, input_detector) == 0x5200,
 | 
			
		||||
              "input_detector has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, npad) == 0x9A00, "npad has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, gesture) == 0x3BA00, "gesture has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, console) == 0x3C200, "console has wrong offset");
 | 
			
		||||
static_assert(offsetof(SharedMemoryFormat, debug_mouse) == 0x3DC00, "debug_mouse has wrong offset");
 | 
			
		||||
static_assert(sizeof(SharedMemoryFormat) == 0x40000, "SharedMemoryFormat is an invalid size");
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/hle/kernel/k_shared_memory.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_holder.h"
 | 
			
		||||
#include "core/hle/service/hid/errors.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
SharedMemoryHolder::SharedMemoryHolder() {}
 | 
			
		||||
 | 
			
		||||
SharedMemoryHolder::~SharedMemoryHolder() {
 | 
			
		||||
    Finalize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result SharedMemoryHolder::Initialize(Core::System& system) {
 | 
			
		||||
    shared_memory = Kernel::KSharedMemory::Create(system.Kernel());
 | 
			
		||||
    const Result result = shared_memory->Initialize(
 | 
			
		||||
        system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None,
 | 
			
		||||
        Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat));
 | 
			
		||||
    if (result.IsError()) {
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    Kernel::KSharedMemory::Register(system.Kernel(), shared_memory);
 | 
			
		||||
 | 
			
		||||
    is_created = true;
 | 
			
		||||
    is_mapped = true;
 | 
			
		||||
    address = std::construct_at(reinterpret_cast<SharedMemoryFormat*>(shared_memory->GetPointer()));
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SharedMemoryHolder::Finalize() {
 | 
			
		||||
    if (address != nullptr) {
 | 
			
		||||
        shared_memory->Close();
 | 
			
		||||
    }
 | 
			
		||||
    is_created = false;
 | 
			
		||||
    is_mapped = false;
 | 
			
		||||
    address = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SharedMemoryHolder::IsMapped() {
 | 
			
		||||
    return is_mapped;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SharedMemoryFormat* SharedMemoryHolder::GetAddress() {
 | 
			
		||||
    return address;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Kernel::KSharedMemory* SharedMemoryHolder::GetHandle() {
 | 
			
		||||
    return shared_memory;
 | 
			
		||||
}
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
							
								
								
									
										44
									
								
								src/core/hle/service/hid/controllers/shared_memory_holder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/core/hle/service/hid/controllers/shared_memory_holder.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/hle/result.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
class KSharedMemory;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct SharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::SharedMemoryHolder
 | 
			
		||||
class SharedMemoryHolder {
 | 
			
		||||
public:
 | 
			
		||||
    SharedMemoryHolder();
 | 
			
		||||
    ~SharedMemoryHolder();
 | 
			
		||||
 | 
			
		||||
    Result Initialize(Core::System& system);
 | 
			
		||||
    void Finalize();
 | 
			
		||||
 | 
			
		||||
    bool IsMapped();
 | 
			
		||||
    SharedMemoryFormat* GetAddress();
 | 
			
		||||
    Kernel::KSharedMemory* GetHandle();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    bool is_owner{};
 | 
			
		||||
    bool is_created{};
 | 
			
		||||
    bool is_mapped{};
 | 
			
		||||
    INSERT_PADDING_BYTES(0x5);
 | 
			
		||||
    Kernel::KSharedMemory* shared_memory;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x38);
 | 
			
		||||
    SharedMemoryFormat* address = nullptr;
 | 
			
		||||
};
 | 
			
		||||
// Correct size is 0x50 bytes
 | 
			
		||||
static_assert(sizeof(SharedMemoryHolder) == 0x50, "SharedMemoryHolder is an invalid size");
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
#include "core/hid/emulated_controller.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/npad.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/six_axis.h"
 | 
			
		||||
#include "core/hle/service/hid/errors.h"
 | 
			
		||||
#include "core/hle/service/hid/hid_util.h"
 | 
			
		||||
@@ -132,30 +133,30 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sixaxis_fullkey_state.sampling_number =
 | 
			
		||||
            sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
            sixaxis_fullkey_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
        sixaxis_handheld_state.sampling_number =
 | 
			
		||||
            sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
            sixaxis_handheld_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
        sixaxis_dual_left_state.sampling_number =
 | 
			
		||||
            sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
            sixaxis_dual_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
        sixaxis_dual_right_state.sampling_number =
 | 
			
		||||
            sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
            sixaxis_dual_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
        sixaxis_left_lifo_state.sampling_number =
 | 
			
		||||
            sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
            sixaxis_left_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
        sixaxis_right_lifo_state.sampling_number =
 | 
			
		||||
            sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
            sixaxis_right_lifo.lifo.ReadCurrentEntry().state.sampling_number + 1;
 | 
			
		||||
 | 
			
		||||
        if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
 | 
			
		||||
            // This buffer only is updated on handheld on HW
 | 
			
		||||
            sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
 | 
			
		||||
            sixaxis_handheld_lifo.lifo.WriteNextEntry(sixaxis_handheld_state);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Handheld doesn't update this buffer on HW
 | 
			
		||||
            sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
 | 
			
		||||
            sixaxis_fullkey_lifo.lifo.WriteNextEntry(sixaxis_fullkey_state);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
 | 
			
		||||
        sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
 | 
			
		||||
        sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
 | 
			
		||||
        sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
 | 
			
		||||
        sixaxis_dual_left_lifo.lifo.WriteNextEntry(sixaxis_dual_left_state);
 | 
			
		||||
        sixaxis_dual_right_lifo.lifo.WriteNextEntry(sixaxis_dual_right_state);
 | 
			
		||||
        sixaxis_left_lifo.lifo.WriteNextEntry(sixaxis_left_lifo_state);
 | 
			
		||||
        sixaxis_right_lifo.lifo.WriteNextEntry(sixaxis_right_lifo_state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,15 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/stubbed.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
 | 
			
		||||
Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
 | 
			
		||||
    : ControllerBase{hid_core_} {
 | 
			
		||||
    raw_shared_memory = raw_shared_memory_;
 | 
			
		||||
}
 | 
			
		||||
Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                                       CommonHeader& ring_lifo_header)
 | 
			
		||||
    : ControllerBase{hid_core_}, header{ring_lifo_header} {}
 | 
			
		||||
 | 
			
		||||
Controller_Stubbed::~Controller_Stubbed() = default;
 | 
			
		||||
 | 
			
		||||
@@ -25,18 +22,10 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CommonHeader header{};
 | 
			
		||||
    header.timestamp = core_timing.GetGlobalTimeNs().count();
 | 
			
		||||
    header.total_entry_count = 17;
 | 
			
		||||
    header.entry_count = 0;
 | 
			
		||||
    header.last_entry_index = 0;
 | 
			
		||||
 | 
			
		||||
    std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
 | 
			
		||||
    common_offset = off;
 | 
			
		||||
    smart_update = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,14 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct CommonHeader;
 | 
			
		||||
 | 
			
		||||
class Controller_Stubbed final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, CommonHeader& ring_lifo_header);
 | 
			
		||||
    ~Controller_Stubbed() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
@@ -21,19 +22,8 @@ public:
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
    void SetCommonHeaderOffset(std::size_t off);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    struct CommonHeader {
 | 
			
		||||
        s64 timestamp{};
 | 
			
		||||
        s64 total_entry_count{};
 | 
			
		||||
        s64 last_entry_index{};
 | 
			
		||||
        s64 entry_count{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
 | 
			
		||||
 | 
			
		||||
    u8* raw_shared_memory = nullptr;
 | 
			
		||||
    CommonHeader& header;
 | 
			
		||||
    bool smart_update{};
 | 
			
		||||
    std::size_t common_offset{};
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -2,26 +2,22 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/settings.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/frontend/emu_window.h"
 | 
			
		||||
#include "core/hid/emulated_console.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/touchscreen.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
 | 
			
		||||
 | 
			
		||||
TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
 | 
			
		||||
    : ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width),
 | 
			
		||||
TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                         TouchScreenSharedMemoryFormat& touch_shared_memory)
 | 
			
		||||
    : ControllerBase{hid_core_}, shared_memory{touch_shared_memory},
 | 
			
		||||
      touchscreen_width(Layout::ScreenUndocked::Width),
 | 
			
		||||
      touchscreen_height(Layout::ScreenUndocked::Height) {
 | 
			
		||||
    static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
 | 
			
		||||
                  "TouchSharedMemory is bigger than the shared memory");
 | 
			
		||||
    shared_memory = std::construct_at(
 | 
			
		||||
        reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 | 
			
		||||
    console = hid_core.GetEmulatedConsole();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -32,11 +28,11 @@ void TouchScreen::OnInit() {}
 | 
			
		||||
void TouchScreen::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
    shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
 | 
			
		||||
    shared_memory.touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
 | 
			
		||||
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
        shared_memory->touch_screen_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory->touch_screen_lifo.buffer_tail = 0;
 | 
			
		||||
        shared_memory.touch_screen_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory.touch_screen_lifo.buffer_tail = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -86,7 +82,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
 | 
			
		||||
 | 
			
		||||
    const u64 timestamp = static_cast<u64>(core_timing.GetGlobalTimeNs().count());
 | 
			
		||||
    const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    const auto& last_entry = shared_memory.touch_screen_lifo.ReadCurrentEntry().state;
 | 
			
		||||
 | 
			
		||||
    next_state.sampling_number = last_entry.sampling_number + 1;
 | 
			
		||||
    next_state.entry_count = static_cast<s32>(active_fingers_count);
 | 
			
		||||
@@ -118,7 +114,7 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shared_memory->touch_screen_lifo.WriteNextEntry(next_state);
 | 
			
		||||
    shared_memory.touch_screen_lifo.WriteNextEntry(next_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,20 +3,23 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/types/touch_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
class EmulatedConsole;
 | 
			
		||||
} // namespace Core::HID
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
struct TouchScreenSharedMemoryFormat;
 | 
			
		||||
 | 
			
		||||
class TouchScreen final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    explicit TouchScreen(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                         TouchScreenSharedMemoryFormat& touch_shared_memory);
 | 
			
		||||
    ~TouchScreen() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
@@ -31,27 +34,8 @@ public:
 | 
			
		||||
    void SetTouchscreenDimensions(u32 width, u32 height);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static constexpr std::size_t MAX_FINGERS = 16;
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::TouchScreenState
 | 
			
		||||
    struct TouchScreenState {
 | 
			
		||||
        s64 sampling_number{};
 | 
			
		||||
        s32 entry_count{};
 | 
			
		||||
        INSERT_PADDING_BYTES(4); // Reserved
 | 
			
		||||
        std::array<Core::HID::TouchState, MAX_FINGERS> states{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    struct TouchSharedMemory {
 | 
			
		||||
        // This is nn::hid::detail::TouchScreenLifo
 | 
			
		||||
        Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
 | 
			
		||||
        static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
 | 
			
		||||
        INSERT_PADDING_WORDS(0xF2);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size");
 | 
			
		||||
 | 
			
		||||
    TouchScreenState next_state{};
 | 
			
		||||
    TouchSharedMemory* shared_memory = nullptr;
 | 
			
		||||
    TouchScreenSharedMemoryFormat& shared_memory;
 | 
			
		||||
    Core::HID::EmulatedConsole* console = nullptr;
 | 
			
		||||
 | 
			
		||||
    std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								src/core/hle/service/hid/controllers/types/debug_pad_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/core/hle/service/hid/controllers/types/debug_pad_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::DebugPadAttribute
 | 
			
		||||
struct DebugPadAttribute {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw{};
 | 
			
		||||
        BitField<0, 1, u32> connected;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(DebugPadAttribute) == 0x4, "DebugPadAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::DebugPadState
 | 
			
		||||
struct DebugPadState {
 | 
			
		||||
    s64 sampling_number{};
 | 
			
		||||
    DebugPadAttribute attribute{};
 | 
			
		||||
    Core::HID::DebugPadButton pad_state{};
 | 
			
		||||
    Core::HID::AnalogStickState r_stick{};
 | 
			
		||||
    Core::HID::AnalogStickState l_stick{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
							
								
								
									
										77
									
								
								src/core/hle/service/hid/controllers/types/gesture_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/core/hle/service/hid/controllers/types/gesture_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/point.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
static constexpr size_t MAX_FINGERS = 16;
 | 
			
		||||
static constexpr size_t MAX_POINTS = 4;
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureType
 | 
			
		||||
enum class GestureType : u32 {
 | 
			
		||||
    Idle,     // Nothing touching the screen
 | 
			
		||||
    Complete, // Set at the end of a touch event
 | 
			
		||||
    Cancel,   // Set when the number of fingers change
 | 
			
		||||
    Touch,    // A finger just touched the screen
 | 
			
		||||
    Press,    // Set if last type is touch and the finger hasn't moved
 | 
			
		||||
    Tap,      // Fast press then release
 | 
			
		||||
    Pan,      // All points moving together across the screen
 | 
			
		||||
    Swipe,    // Fast press movement and release of a single point
 | 
			
		||||
    Pinch,    // All points moving away/closer to the midpoint
 | 
			
		||||
    Rotate,   // All points rotating from the midpoint
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureDirection
 | 
			
		||||
enum class GestureDirection : u32 {
 | 
			
		||||
    None,
 | 
			
		||||
    Left,
 | 
			
		||||
    Up,
 | 
			
		||||
    Right,
 | 
			
		||||
    Down,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureAttribute
 | 
			
		||||
struct GestureAttribute {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw{};
 | 
			
		||||
 | 
			
		||||
        BitField<4, 1, u32> is_new_touch;
 | 
			
		||||
        BitField<8, 1, u32> is_double_tap;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureState
 | 
			
		||||
struct GestureState {
 | 
			
		||||
    s64 sampling_number{};
 | 
			
		||||
    s64 detection_count{};
 | 
			
		||||
    GestureType type{GestureType::Idle};
 | 
			
		||||
    GestureDirection direction{GestureDirection::None};
 | 
			
		||||
    Common::Point<s32> pos{};
 | 
			
		||||
    Common::Point<s32> delta{};
 | 
			
		||||
    f32 vel_x{};
 | 
			
		||||
    f32 vel_y{};
 | 
			
		||||
    GestureAttribute attributes{};
 | 
			
		||||
    f32 scale{};
 | 
			
		||||
    f32 rotation_angle{};
 | 
			
		||||
    s32 point_count{};
 | 
			
		||||
    std::array<Common::Point<s32>, 4> points{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct GestureProperties {
 | 
			
		||||
    std::array<Common::Point<s32>, MAX_POINTS> points{};
 | 
			
		||||
    std::size_t active_points{};
 | 
			
		||||
    Common::Point<s32> mid_point{};
 | 
			
		||||
    s64 detection_count{};
 | 
			
		||||
    u64 delta_time{};
 | 
			
		||||
    f32 average_distance{};
 | 
			
		||||
    f32 angle{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
							
								
								
									
										20
									
								
								src/core/hle/service/hid/controllers/types/keyboard_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/core/hle/service/hid/controllers/types/keyboard_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::KeyboardState
 | 
			
		||||
struct KeyboardState {
 | 
			
		||||
    s64 sampling_number{};
 | 
			
		||||
    Core::HID::KeyboardModifier modifier{};
 | 
			
		||||
    Core::HID::KeyboardAttribute attribute{};
 | 
			
		||||
    Core::HID::KeyboardKey key{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
							
								
								
									
										8
									
								
								src/core/hle/service/hid/controllers/types/mouse_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/core/hle/service/hid/controllers/types/mouse_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {} // namespace Service::HID
 | 
			
		||||
							
								
								
									
										254
									
								
								src/core/hle/service/hid/controllers/types/npad_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								src/core/hle/service/hid/controllers/types/npad_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
static constexpr std::size_t NpadCount = 10;
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadJoyHoldType
 | 
			
		||||
enum class NpadJoyHoldType : u64 {
 | 
			
		||||
    Vertical = 0,
 | 
			
		||||
    Horizontal = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadJoyAssignmentMode
 | 
			
		||||
enum class NpadJoyAssignmentMode : u32 {
 | 
			
		||||
    Dual = 0,
 | 
			
		||||
    Single = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadJoyDeviceType
 | 
			
		||||
enum class NpadJoyDeviceType : s64 {
 | 
			
		||||
    Left = 0,
 | 
			
		||||
    Right = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadHandheldActivationMode
 | 
			
		||||
enum class NpadHandheldActivationMode : u64 {
 | 
			
		||||
    Dual = 0,
 | 
			
		||||
    Single = 1,
 | 
			
		||||
    None = 2,
 | 
			
		||||
    MaxActivationMode = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::system::AppletFooterUiAttributesSet
 | 
			
		||||
struct AppletFooterUiAttributes {
 | 
			
		||||
    INSERT_PADDING_BYTES(0x4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::system::AppletFooterUiType
 | 
			
		||||
enum class AppletFooterUiType : u8 {
 | 
			
		||||
    None = 0,
 | 
			
		||||
    HandheldNone = 1,
 | 
			
		||||
    HandheldJoyConLeftOnly = 2,
 | 
			
		||||
    HandheldJoyConRightOnly = 3,
 | 
			
		||||
    HandheldJoyConLeftJoyConRight = 4,
 | 
			
		||||
    JoyDual = 5,
 | 
			
		||||
    JoyDualLeftOnly = 6,
 | 
			
		||||
    JoyDualRightOnly = 7,
 | 
			
		||||
    JoyLeftHorizontal = 8,
 | 
			
		||||
    JoyLeftVertical = 9,
 | 
			
		||||
    JoyRightHorizontal = 10,
 | 
			
		||||
    JoyRightVertical = 11,
 | 
			
		||||
    SwitchProController = 12,
 | 
			
		||||
    CompatibleProController = 13,
 | 
			
		||||
    CompatibleJoyCon = 14,
 | 
			
		||||
    LarkHvc1 = 15,
 | 
			
		||||
    LarkHvc2 = 16,
 | 
			
		||||
    LarkNesLeft = 17,
 | 
			
		||||
    LarkNesRight = 18,
 | 
			
		||||
    Lucia = 19,
 | 
			
		||||
    Verification = 20,
 | 
			
		||||
    Lagon = 21,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using AppletFooterUiVariant = u8;
 | 
			
		||||
 | 
			
		||||
// This is "nn::hid::system::AppletDetailedUiType".
 | 
			
		||||
struct AppletDetailedUiType {
 | 
			
		||||
    AppletFooterUiVariant ui_variant;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x2);
 | 
			
		||||
    AppletFooterUiType footer;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
 | 
			
		||||
// This is nn::hid::NpadCommunicationMode
 | 
			
		||||
enum class NpadCommunicationMode : u64 {
 | 
			
		||||
    Mode_5ms = 0,
 | 
			
		||||
    Mode_10ms = 1,
 | 
			
		||||
    Mode_15ms = 2,
 | 
			
		||||
    Default = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class NpadRevision : u32 {
 | 
			
		||||
    Revision0 = 0,
 | 
			
		||||
    Revision1 = 1,
 | 
			
		||||
    Revision2 = 2,
 | 
			
		||||
    Revision3 = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::ColorAttribute
 | 
			
		||||
enum class ColorAttribute : u32 {
 | 
			
		||||
    Ok = 0,
 | 
			
		||||
    ReadError = 1,
 | 
			
		||||
    NoController = 2,
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(ColorAttribute) == 4, "ColorAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::NpadFullKeyColorState
 | 
			
		||||
struct NpadFullKeyColorState {
 | 
			
		||||
    ColorAttribute attribute{ColorAttribute::NoController};
 | 
			
		||||
    Core::HID::NpadControllerColor fullkey{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadFullKeyColorState) == 0xC, "NpadFullKeyColorState is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::NpadJoyColorState
 | 
			
		||||
struct NpadJoyColorState {
 | 
			
		||||
    ColorAttribute attribute{ColorAttribute::NoController};
 | 
			
		||||
    Core::HID::NpadControllerColor left{};
 | 
			
		||||
    Core::HID::NpadControllerColor right{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadJoyColorState) == 0x14, "NpadJoyColorState is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadAttribute
 | 
			
		||||
struct NpadAttribute {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw{};
 | 
			
		||||
        BitField<0, 1, u32> is_connected;
 | 
			
		||||
        BitField<1, 1, u32> is_wired;
 | 
			
		||||
        BitField<2, 1, u32> is_left_connected;
 | 
			
		||||
        BitField<3, 1, u32> is_left_wired;
 | 
			
		||||
        BitField<4, 1, u32> is_right_connected;
 | 
			
		||||
        BitField<5, 1, u32> is_right_wired;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadAttribute) == 4, "NpadAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadFullKeyState
 | 
			
		||||
// This is nn::hid::NpadHandheldState
 | 
			
		||||
// This is nn::hid::NpadJoyDualState
 | 
			
		||||
// This is nn::hid::NpadJoyLeftState
 | 
			
		||||
// This is nn::hid::NpadJoyRightState
 | 
			
		||||
// This is nn::hid::NpadPalmaState
 | 
			
		||||
// This is nn::hid::NpadSystemExtState
 | 
			
		||||
struct NPadGenericState {
 | 
			
		||||
    s64_le sampling_number{};
 | 
			
		||||
    Core::HID::NpadButtonState npad_buttons{};
 | 
			
		||||
    Core::HID::AnalogStickState l_stick{};
 | 
			
		||||
    Core::HID::AnalogStickState r_stick{};
 | 
			
		||||
    NpadAttribute connection_status{};
 | 
			
		||||
    INSERT_PADDING_BYTES(4); // Reserved
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::server::NpadGcTriggerState
 | 
			
		||||
struct NpadGcTriggerState {
 | 
			
		||||
    s64 sampling_number{};
 | 
			
		||||
    s32 l_analog{};
 | 
			
		||||
    s32 r_analog{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadSystemProperties
 | 
			
		||||
struct NPadSystemProperties {
 | 
			
		||||
    union {
 | 
			
		||||
        s64 raw{};
 | 
			
		||||
        BitField<0, 1, s64> is_charging_joy_dual;
 | 
			
		||||
        BitField<1, 1, s64> is_charging_joy_left;
 | 
			
		||||
        BitField<2, 1, s64> is_charging_joy_right;
 | 
			
		||||
        BitField<3, 1, s64> is_powered_joy_dual;
 | 
			
		||||
        BitField<4, 1, s64> is_powered_joy_left;
 | 
			
		||||
        BitField<5, 1, s64> is_powered_joy_right;
 | 
			
		||||
        BitField<9, 1, s64> is_system_unsupported_button;
 | 
			
		||||
        BitField<10, 1, s64> is_system_ext_unsupported_button;
 | 
			
		||||
        BitField<11, 1, s64> is_vertical;
 | 
			
		||||
        BitField<12, 1, s64> is_horizontal;
 | 
			
		||||
        BitField<13, 1, s64> use_plus;
 | 
			
		||||
        BitField<14, 1, s64> use_minus;
 | 
			
		||||
        BitField<15, 1, s64> use_directional_buttons;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadSystemButtonProperties
 | 
			
		||||
struct NpadSystemButtonProperties {
 | 
			
		||||
    union {
 | 
			
		||||
        s32 raw{};
 | 
			
		||||
        BitField<0, 1, s32> is_home_button_protection_enabled;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NpadSystemButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::system::DeviceType
 | 
			
		||||
struct DeviceType {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw{};
 | 
			
		||||
        BitField<0, 1, s32> fullkey;
 | 
			
		||||
        BitField<1, 1, s32> debug_pad;
 | 
			
		||||
        BitField<2, 1, s32> handheld_left;
 | 
			
		||||
        BitField<3, 1, s32> handheld_right;
 | 
			
		||||
        BitField<4, 1, s32> joycon_left;
 | 
			
		||||
        BitField<5, 1, s32> joycon_right;
 | 
			
		||||
        BitField<6, 1, s32> palma;
 | 
			
		||||
        BitField<7, 1, s32> lark_hvc_left;
 | 
			
		||||
        BitField<8, 1, s32> lark_hvc_right;
 | 
			
		||||
        BitField<9, 1, s32> lark_nes_left;
 | 
			
		||||
        BitField<10, 1, s32> lark_nes_right;
 | 
			
		||||
        BitField<11, 1, s32> handheld_lark_hvc_left;
 | 
			
		||||
        BitField<12, 1, s32> handheld_lark_hvc_right;
 | 
			
		||||
        BitField<13, 1, s32> handheld_lark_nes_left;
 | 
			
		||||
        BitField<14, 1, s32> handheld_lark_nes_right;
 | 
			
		||||
        BitField<15, 1, s32> lucia;
 | 
			
		||||
        BitField<16, 1, s32> lagon;
 | 
			
		||||
        BitField<17, 1, s32> lager;
 | 
			
		||||
        BitField<31, 1, s32> system;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::detail::NfcXcdDeviceHandleStateImpl
 | 
			
		||||
struct NfcXcdDeviceHandleStateImpl {
 | 
			
		||||
    u64 handle{};
 | 
			
		||||
    bool is_available{};
 | 
			
		||||
    bool is_activated{};
 | 
			
		||||
    INSERT_PADDING_BYTES(0x6); // Reserved
 | 
			
		||||
    u64 sampling_number{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
 | 
			
		||||
              "NfcXcdDeviceHandleStateImpl is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadLarkType
 | 
			
		||||
enum class NpadLarkType : u32 {
 | 
			
		||||
    Invalid,
 | 
			
		||||
    H1,
 | 
			
		||||
    H2,
 | 
			
		||||
    NL,
 | 
			
		||||
    NR,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadLuciaType
 | 
			
		||||
enum class NpadLuciaType : u32 {
 | 
			
		||||
    Invalid,
 | 
			
		||||
    J,
 | 
			
		||||
    E,
 | 
			
		||||
    U,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadLagonType
 | 
			
		||||
enum class NpadLagonType : u32 {
 | 
			
		||||
    Invalid,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::NpadLagerType
 | 
			
		||||
enum class NpadLagerType : u32 {
 | 
			
		||||
    Invalid,
 | 
			
		||||
    J,
 | 
			
		||||
    E,
 | 
			
		||||
    U,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
							
								
								
									
										90
									
								
								src/core/hle/service/hid/controllers/types/touch_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/core/hle/service/hid/controllers/types/touch_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/point.h"
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
static constexpr std::size_t MAX_FINGERS = 16;
 | 
			
		||||
static constexpr size_t MAX_POINTS = 4;
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureType
 | 
			
		||||
enum class GestureType : u32 {
 | 
			
		||||
    Idle,     // Nothing touching the screen
 | 
			
		||||
    Complete, // Set at the end of a touch event
 | 
			
		||||
    Cancel,   // Set when the number of fingers change
 | 
			
		||||
    Touch,    // A finger just touched the screen
 | 
			
		||||
    Press,    // Set if last type is touch and the finger hasn't moved
 | 
			
		||||
    Tap,      // Fast press then release
 | 
			
		||||
    Pan,      // All points moving together across the screen
 | 
			
		||||
    Swipe,    // Fast press movement and release of a single point
 | 
			
		||||
    Pinch,    // All points moving away/closer to the midpoint
 | 
			
		||||
    Rotate,   // All points rotating from the midpoint
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureDirection
 | 
			
		||||
enum class GestureDirection : u32 {
 | 
			
		||||
    None,
 | 
			
		||||
    Left,
 | 
			
		||||
    Up,
 | 
			
		||||
    Right,
 | 
			
		||||
    Down,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureAttribute
 | 
			
		||||
struct GestureAttribute {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 raw{};
 | 
			
		||||
 | 
			
		||||
        BitField<4, 1, u32> is_new_touch;
 | 
			
		||||
        BitField<8, 1, u32> is_double_tap;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(GestureAttribute) == 4, "GestureAttribute is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::GestureState
 | 
			
		||||
struct GestureState {
 | 
			
		||||
    s64 sampling_number{};
 | 
			
		||||
    s64 detection_count{};
 | 
			
		||||
    GestureType type{GestureType::Idle};
 | 
			
		||||
    GestureDirection direction{GestureDirection::None};
 | 
			
		||||
    Common::Point<s32> pos{};
 | 
			
		||||
    Common::Point<s32> delta{};
 | 
			
		||||
    f32 vel_x{};
 | 
			
		||||
    f32 vel_y{};
 | 
			
		||||
    GestureAttribute attributes{};
 | 
			
		||||
    f32 scale{};
 | 
			
		||||
    f32 rotation_angle{};
 | 
			
		||||
    s32 point_count{};
 | 
			
		||||
    std::array<Common::Point<s32>, 4> points{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
 | 
			
		||||
 | 
			
		||||
struct GestureProperties {
 | 
			
		||||
    std::array<Common::Point<s32>, MAX_POINTS> points{};
 | 
			
		||||
    std::size_t active_points{};
 | 
			
		||||
    Common::Point<s32> mid_point{};
 | 
			
		||||
    s64 detection_count{};
 | 
			
		||||
    u64 delta_time{};
 | 
			
		||||
    f32 average_distance{};
 | 
			
		||||
    f32 angle{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::TouchScreenState
 | 
			
		||||
struct TouchScreenState {
 | 
			
		||||
    s64 sampling_number{};
 | 
			
		||||
    s32 entry_count{};
 | 
			
		||||
    INSERT_PADDING_BYTES(4); // Reserved
 | 
			
		||||
    std::array<Core::HID::TouchState, MAX_FINGERS> states{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/xpad.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
 | 
			
		||||
 | 
			
		||||
XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
 | 
			
		||||
    static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
 | 
			
		||||
                  "XpadSharedMemory is bigger than the shared memory");
 | 
			
		||||
    shared_memory = std::construct_at(
 | 
			
		||||
        reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
 | 
			
		||||
}
 | 
			
		||||
XPad::~XPad() = default;
 | 
			
		||||
 | 
			
		||||
void XPad::OnInit() {}
 | 
			
		||||
 | 
			
		||||
void XPad::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
        shared_memory->basic_xpad_lifo.buffer_count = 0;
 | 
			
		||||
        shared_memory->basic_xpad_lifo.buffer_tail = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& last_entry = shared_memory->basic_xpad_lifo.ReadCurrentEntry().state;
 | 
			
		||||
    next_state.sampling_number = last_entry.sampling_number + 1;
 | 
			
		||||
    // TODO(ogniK): Update xpad states
 | 
			
		||||
 | 
			
		||||
    shared_memory->basic_xpad_lifo.WriteNextEntry(next_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
@@ -1,112 +0,0 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hid/hid_types.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/controller_base.h"
 | 
			
		||||
#include "core/hle/service/hid/ring_lifo.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
class XPad final : public ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
 | 
			
		||||
    ~XPad() override;
 | 
			
		||||
 | 
			
		||||
    // Called when the controller is initialized
 | 
			
		||||
    void OnInit() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is released
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // This is nn::hid::BasicXpadAttributeSet
 | 
			
		||||
    struct BasicXpadAttributeSet {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw{};
 | 
			
		||||
            BitField<0, 1, u32> is_connected;
 | 
			
		||||
            BitField<1, 1, u32> is_wired;
 | 
			
		||||
            BitField<2, 1, u32> is_left_connected;
 | 
			
		||||
            BitField<3, 1, u32> is_left_wired;
 | 
			
		||||
            BitField<4, 1, u32> is_right_connected;
 | 
			
		||||
            BitField<5, 1, u32> is_right_wired;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(BasicXpadAttributeSet) == 4, "BasicXpadAttributeSet is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::BasicXpadButtonSet
 | 
			
		||||
    struct BasicXpadButtonSet {
 | 
			
		||||
        union {
 | 
			
		||||
            u32 raw{};
 | 
			
		||||
            // Button states
 | 
			
		||||
            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_stick;
 | 
			
		||||
            BitField<5, 1, u32> r_stick;
 | 
			
		||||
            BitField<6, 1, u32> l;
 | 
			
		||||
            BitField<7, 1, u32> r;
 | 
			
		||||
            BitField<8, 1, u32> zl;
 | 
			
		||||
            BitField<9, 1, u32> zr;
 | 
			
		||||
            BitField<10, 1, u32> plus;
 | 
			
		||||
            BitField<11, 1, u32> minus;
 | 
			
		||||
 | 
			
		||||
            // D-Pad
 | 
			
		||||
            BitField<12, 1, u32> d_left;
 | 
			
		||||
            BitField<13, 1, u32> d_up;
 | 
			
		||||
            BitField<14, 1, u32> d_right;
 | 
			
		||||
            BitField<15, 1, u32> d_down;
 | 
			
		||||
 | 
			
		||||
            // Left JoyStick
 | 
			
		||||
            BitField<16, 1, u32> l_stick_left;
 | 
			
		||||
            BitField<17, 1, u32> l_stick_up;
 | 
			
		||||
            BitField<18, 1, u32> l_stick_right;
 | 
			
		||||
            BitField<19, 1, u32> l_stick_down;
 | 
			
		||||
 | 
			
		||||
            // Right JoyStick
 | 
			
		||||
            BitField<20, 1, u32> r_stick_left;
 | 
			
		||||
            BitField<21, 1, u32> r_stick_up;
 | 
			
		||||
            BitField<22, 1, u32> r_stick_right;
 | 
			
		||||
            BitField<23, 1, u32> r_stick_down;
 | 
			
		||||
 | 
			
		||||
            // Not always active?
 | 
			
		||||
            BitField<24, 1, u32> left_sl;
 | 
			
		||||
            BitField<25, 1, u32> left_sr;
 | 
			
		||||
 | 
			
		||||
            BitField<26, 1, u32> right_sl;
 | 
			
		||||
            BitField<27, 1, u32> right_sr;
 | 
			
		||||
 | 
			
		||||
            BitField<28, 1, u32> palma;
 | 
			
		||||
            BitField<30, 1, u32> handheld_left_b;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(BasicXpadButtonSet) == 4, "BasicXpadButtonSet is an invalid size");
 | 
			
		||||
 | 
			
		||||
    // This is nn::hid::detail::BasicXpadState
 | 
			
		||||
    struct BasicXpadState {
 | 
			
		||||
        s64 sampling_number{};
 | 
			
		||||
        BasicXpadAttributeSet attributes{};
 | 
			
		||||
        BasicXpadButtonSet pad_states{};
 | 
			
		||||
        Core::HID::AnalogStickState l_stick{};
 | 
			
		||||
        Core::HID::AnalogStickState r_stick{};
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
 | 
			
		||||
 | 
			
		||||
    struct XpadSharedMemory {
 | 
			
		||||
        // This is nn::hid::detail::BasicXpadLifo
 | 
			
		||||
        Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
 | 
			
		||||
        static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
 | 
			
		||||
        INSERT_PADDING_WORDS(0x4E);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(XpadSharedMemory) == 0x400, "XpadSharedMemory is an invalid size");
 | 
			
		||||
 | 
			
		||||
    BasicXpadState next_state{};
 | 
			
		||||
    XpadSharedMemory* shared_memory = nullptr;
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
#include "core/hle/service/hid/controllers/seven_six_axis.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/six_axis.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/touchscreen.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/types/npad_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
 | 
			
		||||
@@ -1099,7 +1100,7 @@ void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
 | 
			
		||||
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    struct Parameters {
 | 
			
		||||
        NPad::NpadRevision revision;
 | 
			
		||||
        NpadRevision revision;
 | 
			
		||||
        INSERT_PADDING_WORDS_NOINIT(1);
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
    };
 | 
			
		||||
@@ -1122,7 +1123,7 @@ void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
 | 
			
		||||
void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto applet_resource_user_id{rp.Pop<u64>()};
 | 
			
		||||
    const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()};
 | 
			
		||||
    const auto hold_type{rp.PopEnum<NpadJoyHoldType>()};
 | 
			
		||||
 | 
			
		||||
    GetResourceManager()->GetNpad()->SetHoldType(hold_type);
 | 
			
		||||
 | 
			
		||||
@@ -1157,8 +1158,8 @@ void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx)
 | 
			
		||||
 | 
			
		||||
    Core::HID::NpadIdType new_npad_id{};
 | 
			
		||||
    auto controller = GetResourceManager()->GetNpad();
 | 
			
		||||
    controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left,
 | 
			
		||||
                            NPad::NpadJoyAssignmentMode::Single);
 | 
			
		||||
    controller->SetNpadMode(new_npad_id, parameters.npad_id, NpadJoyDeviceType::Left,
 | 
			
		||||
                            NpadJoyAssignmentMode::Single);
 | 
			
		||||
 | 
			
		||||
    LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
 | 
			
		||||
             parameters.applet_resource_user_id);
 | 
			
		||||
@@ -1173,7 +1174,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
 | 
			
		||||
        Core::HID::NpadIdType npad_id;
 | 
			
		||||
        INSERT_PADDING_WORDS_NOINIT(1);
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
        NPad::NpadJoyDeviceType npad_joy_device_type;
 | 
			
		||||
        NpadJoyDeviceType npad_joy_device_type;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
 | 
			
		||||
 | 
			
		||||
@@ -1182,7 +1183,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
 | 
			
		||||
    Core::HID::NpadIdType new_npad_id{};
 | 
			
		||||
    auto controller = GetResourceManager()->GetNpad();
 | 
			
		||||
    controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
 | 
			
		||||
                            NPad::NpadJoyAssignmentMode::Single);
 | 
			
		||||
                            NpadJoyAssignmentMode::Single);
 | 
			
		||||
 | 
			
		||||
    LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
 | 
			
		||||
             parameters.npad_id, parameters.applet_resource_user_id,
 | 
			
		||||
@@ -1205,7 +1206,7 @@ void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
 | 
			
		||||
 | 
			
		||||
    Core::HID::NpadIdType new_npad_id{};
 | 
			
		||||
    auto controller = GetResourceManager()->GetNpad();
 | 
			
		||||
    controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual);
 | 
			
		||||
    controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NpadJoyAssignmentMode::Dual);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
 | 
			
		||||
              parameters.applet_resource_user_id); // Spams a lot when controller applet is open
 | 
			
		||||
@@ -1257,7 +1258,7 @@ void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
 | 
			
		||||
void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto applet_resource_user_id{rp.Pop<u64>()};
 | 
			
		||||
    const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()};
 | 
			
		||||
    const auto activation_mode{rp.PopEnum<NpadHandheldActivationMode>()};
 | 
			
		||||
 | 
			
		||||
    GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
 | 
			
		||||
 | 
			
		||||
@@ -1349,7 +1350,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
 | 
			
		||||
        Core::HID::NpadIdType npad_id;
 | 
			
		||||
        INSERT_PADDING_WORDS_NOINIT(1);
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
        NPad::NpadJoyDeviceType npad_joy_device_type;
 | 
			
		||||
        NpadJoyDeviceType npad_joy_device_type;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
 | 
			
		||||
 | 
			
		||||
@@ -1359,7 +1360,7 @@ void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext
 | 
			
		||||
    auto controller = GetResourceManager()->GetNpad();
 | 
			
		||||
    const auto is_reassigned =
 | 
			
		||||
        controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
 | 
			
		||||
                                NPad::NpadJoyAssignmentMode::Single);
 | 
			
		||||
                                NpadJoyAssignmentMode::Single);
 | 
			
		||||
 | 
			
		||||
    LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
 | 
			
		||||
             parameters.npad_id, parameters.applet_resource_user_id,
 | 
			
		||||
@@ -2315,7 +2316,7 @@ void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
 | 
			
		||||
void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto applet_resource_user_id{rp.Pop<u64>()};
 | 
			
		||||
    const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()};
 | 
			
		||||
    const auto communication_mode{rp.PopEnum<NpadCommunicationMode>()};
 | 
			
		||||
 | 
			
		||||
    GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
#include "core/hle/service/hid/controllers/npad.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/palma.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/touchscreen.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/types/npad_types.h"
 | 
			
		||||
#include "core/hle/service/hid/errors.h"
 | 
			
		||||
#include "core/hle/service/hid/hid_system_server.h"
 | 
			
		||||
#include "core/hle/service/hid/resource_manager.h"
 | 
			
		||||
@@ -328,7 +329,7 @@ void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_HID, "called, npad_id_type={}",
 | 
			
		||||
              npad_id_type); // Spams a lot when controller applet is running
 | 
			
		||||
 | 
			
		||||
    const NPad::AppletDetailedUiType detailed_ui_type =
 | 
			
		||||
    const AppletDetailedUiType detailed_ui_type =
 | 
			
		||||
        GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
 
 | 
			
		||||
@@ -18,10 +18,10 @@
 | 
			
		||||
#include "core/hle/service/hid/controllers/npad.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/palma.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/seven_six_axis.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/shared_memory_format.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/six_axis.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/stubbed.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/touchscreen.h"
 | 
			
		||||
#include "core/hle/service/hid/controllers/xpad.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
 | 
			
		||||
@@ -45,40 +45,43 @@ void ResourceManager::Initialize() {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
 | 
			
		||||
    debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory);
 | 
			
		||||
    mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory);
 | 
			
		||||
    debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory);
 | 
			
		||||
    keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory);
 | 
			
		||||
    unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory);
 | 
			
		||||
    npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context);
 | 
			
		||||
    gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory);
 | 
			
		||||
    touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory);
 | 
			
		||||
    xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory);
 | 
			
		||||
    system.HIDCore().ReloadInputDevices();
 | 
			
		||||
    is_initialized = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context);
 | 
			
		||||
void ResourceManager::InitializeController(u64 aruid) {
 | 
			
		||||
    SharedMemoryFormat* shared_memory = nullptr;
 | 
			
		||||
    const auto result = applet_resource->GetSharedMemoryFormat(&shared_memory, aruid);
 | 
			
		||||
    if (result.IsError()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory);
 | 
			
		||||
    sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory);
 | 
			
		||||
    capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory);
 | 
			
		||||
    debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory->debug_pad);
 | 
			
		||||
    mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory->mouse);
 | 
			
		||||
    debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory->debug_mouse);
 | 
			
		||||
    keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory->keyboard);
 | 
			
		||||
    unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory->unique_pad.header);
 | 
			
		||||
    npad = std::make_shared<NPad>(system.HIDCore(), shared_memory->npad, service_context);
 | 
			
		||||
    gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory->gesture);
 | 
			
		||||
    touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory->touch_screen);
 | 
			
		||||
 | 
			
		||||
    palma = std::make_shared<Palma>(system.HIDCore(), service_context);
 | 
			
		||||
 | 
			
		||||
    home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory->home_button.header);
 | 
			
		||||
    sleep_button =
 | 
			
		||||
        std::make_shared<SleepButton>(system.HIDCore(), shared_memory->sleep_button.header);
 | 
			
		||||
    capture_button =
 | 
			
		||||
        std::make_shared<CaptureButton>(system.HIDCore(), shared_memory->capture_button.header);
 | 
			
		||||
    digitizer = std::make_shared<Digitizer>(system.HIDCore(), shared_memory->digitizer.header);
 | 
			
		||||
 | 
			
		||||
    six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
 | 
			
		||||
    console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory);
 | 
			
		||||
    console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory->console);
 | 
			
		||||
    seven_six_axis = std::make_shared<SevenSixAxis>(system);
 | 
			
		||||
 | 
			
		||||
    home_button->SetCommonHeaderOffset(0x4C00);
 | 
			
		||||
    sleep_button->SetCommonHeaderOffset(0x4E00);
 | 
			
		||||
    capture_button->SetCommonHeaderOffset(0x5000);
 | 
			
		||||
    unique_pad->SetCommonHeaderOffset(0x5A00);
 | 
			
		||||
    debug_mouse->SetCommonHeaderOffset(0x3DC00);
 | 
			
		||||
 | 
			
		||||
    // Homebrew doesn't try to activate some controllers, so we activate them by default
 | 
			
		||||
    npad->Activate();
 | 
			
		||||
    six_axis->Activate();
 | 
			
		||||
    touch_screen->Activate();
 | 
			
		||||
 | 
			
		||||
    system.HIDCore().ReloadInputDevices();
 | 
			
		||||
    is_initialized = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<AppletResource> ResourceManager::GetAppletResource() const {
 | 
			
		||||
@@ -101,6 +104,10 @@ std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
 | 
			
		||||
    return debug_pad;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<Digitizer> ResourceManager::GetDigitizer() const {
 | 
			
		||||
    return digitizer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
 | 
			
		||||
    return gesture;
 | 
			
		||||
}
 | 
			
		||||
@@ -163,7 +170,11 @@ Result ResourceManager::CreateAppletResource(u64 aruid) {
 | 
			
		||||
 | 
			
		||||
Result ResourceManager::CreateAppletResourceImpl(u64 aruid) {
 | 
			
		||||
    std::scoped_lock lock{shared_mutex};
 | 
			
		||||
    return applet_resource->CreateAppletResource(aruid);
 | 
			
		||||
    const auto result = applet_resource->CreateAppletResource(aruid);
 | 
			
		||||
    if (result.IsSuccess()) {
 | 
			
		||||
        InitializeController(aruid);
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result ResourceManager::RegisterCoreAppletResource() {
 | 
			
		||||
@@ -220,6 +231,7 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
 | 
			
		||||
                                        std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    auto& core_timing = system.CoreTiming();
 | 
			
		||||
    debug_pad->OnUpdate(core_timing);
 | 
			
		||||
    digitizer->OnUpdate(core_timing);
 | 
			
		||||
    unique_pad->OnUpdate(core_timing);
 | 
			
		||||
    gesture->OnUpdate(core_timing);
 | 
			
		||||
    touch_screen->OnUpdate(core_timing);
 | 
			
		||||
@@ -227,7 +239,6 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
 | 
			
		||||
    home_button->OnUpdate(core_timing);
 | 
			
		||||
    sleep_button->OnUpdate(core_timing);
 | 
			
		||||
    capture_button->OnUpdate(core_timing);
 | 
			
		||||
    xpad->OnUpdate(core_timing);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
 | 
			
		||||
 
 | 
			
		||||
@@ -31,10 +31,10 @@ class Palma;
 | 
			
		||||
class SevenSixAxis;
 | 
			
		||||
class SixAxis;
 | 
			
		||||
class TouchScreen;
 | 
			
		||||
class XPad;
 | 
			
		||||
 | 
			
		||||
using CaptureButton = Controller_Stubbed;
 | 
			
		||||
using DebugMouse = Controller_Stubbed;
 | 
			
		||||
using DebugMouse = Mouse;
 | 
			
		||||
using Digitizer = Controller_Stubbed;
 | 
			
		||||
using HomeButton = Controller_Stubbed;
 | 
			
		||||
using SleepButton = Controller_Stubbed;
 | 
			
		||||
using UniquePad = Controller_Stubbed;
 | 
			
		||||
@@ -46,12 +46,14 @@ public:
 | 
			
		||||
    ~ResourceManager();
 | 
			
		||||
 | 
			
		||||
    void Initialize();
 | 
			
		||||
    void InitializeController(u64 aruid);
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<AppletResource> GetAppletResource() const;
 | 
			
		||||
    std::shared_ptr<CaptureButton> GetCaptureButton() const;
 | 
			
		||||
    std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
 | 
			
		||||
    std::shared_ptr<DebugMouse> GetDebugMouse() const;
 | 
			
		||||
    std::shared_ptr<DebugPad> GetDebugPad() const;
 | 
			
		||||
    std::shared_ptr<Digitizer> GetDigitizer() const;
 | 
			
		||||
    std::shared_ptr<Gesture> GetGesture() const;
 | 
			
		||||
    std::shared_ptr<HomeButton> GetHomeButton() const;
 | 
			
		||||
    std::shared_ptr<Keyboard> GetKeyboard() const;
 | 
			
		||||
@@ -96,6 +98,7 @@ private:
 | 
			
		||||
    std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
 | 
			
		||||
    std::shared_ptr<DebugMouse> debug_mouse = nullptr;
 | 
			
		||||
    std::shared_ptr<DebugPad> debug_pad = nullptr;
 | 
			
		||||
    std::shared_ptr<Digitizer> digitizer = nullptr;
 | 
			
		||||
    std::shared_ptr<Gesture> gesture = nullptr;
 | 
			
		||||
    std::shared_ptr<HomeButton> home_button = nullptr;
 | 
			
		||||
    std::shared_ptr<Keyboard> keyboard = nullptr;
 | 
			
		||||
@@ -107,7 +110,6 @@ private:
 | 
			
		||||
    std::shared_ptr<SleepButton> sleep_button = nullptr;
 | 
			
		||||
    std::shared_ptr<TouchScreen> touch_screen = nullptr;
 | 
			
		||||
    std::shared_ptr<UniquePad> unique_pad = nullptr;
 | 
			
		||||
    std::shared_ptr<XPad> xpad = nullptr;
 | 
			
		||||
 | 
			
		||||
    // TODO: Create these resources
 | 
			
		||||
    // std::shared_ptr<AudioControl> audio_control = nullptr;
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ u64 StandardVmCallbacks::HidKeysDown() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto applet_resource = hid->GetResourceManager();
 | 
			
		||||
    if (applet_resource == nullptr) {
 | 
			
		||||
    if (applet_resource == nullptr || applet_resource->GetNpad() == nullptr) {
 | 
			
		||||
        LOG_WARNING(CheatEngine,
 | 
			
		||||
                    "Attempted to read input state, but applet resource is not initialized!");
 | 
			
		||||
        return 0;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user