summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/acc/acc.cpp56
-rw-r--r--src/core/hle/service/am/am.cpp100
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp4
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp3
-rw-r--r--src/core/hle/service/am/applets/applets.h24
-rw-r--r--src/core/hle/service/caps/caps_manager.cpp16
-rw-r--r--src/core/hle/service/caps/caps_manager.h9
-rw-r--r--src/core/hle/service/caps/caps_ss.cpp10
-rw-r--r--src/core/hle/service/caps/caps_su.cpp42
-rw-r--r--src/core/hle/service/caps/caps_su.h9
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.cpp9
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.h4
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp12
-rw-r--r--src/core/hle/service/hid/controllers/npad.h7
-rw-r--r--src/core/hle/service/hid/controllers/palma.cpp6
-rw-r--r--src/core/hle/service/hid/hid.cpp2857
-rw-r--r--src/core/hle/service/hid/hid.h212
-rw-r--r--src/core/hle/service/hid/hid_debug_server.cpp159
-rw-r--r--src/core/hle/service/hid/hid_debug_server.h26
-rw-r--r--src/core/hle/service/hid/hid_firmware_settings.cpp99
-rw-r--r--src/core/hle/service/hid/hid_firmware_settings.h54
-rw-r--r--src/core/hle/service/hid/hid_server.cpp2440
-rw-r--r--src/core/hle/service/hid/hid_server.h149
-rw-r--r--src/core/hle/service/hid/hid_system_server.cpp304
-rw-r--r--src/core/hle/service/hid/hid_system_server.h40
-rw-r--r--src/core/hle/service/hid/hidbus/hidbus_base.cpp5
-rw-r--r--src/core/hle/service/hid/irs.cpp2
-rw-r--r--src/core/hle/service/hid/irs.h5
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.cpp16
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.h9
-rw-r--r--src/core/hle/service/hid/irsensor/image_transfer_processor.cpp2
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.cpp123
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.h34
-rw-r--r--src/core/hle/service/hid/resource_manager.cpp184
-rw-r--r--src/core/hle/service/hid/resource_manager.h104
-rw-r--r--src/core/hle/service/hid/ring_lifo.h6
-rw-r--r--src/core/hle/service/ldr/ldr.cpp45
-rw-r--r--src/core/hle/service/nvdrv/devices/ioctl_serialization.h159
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp82
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h20
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp42
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h12
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp115
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h29
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp117
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h35
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp15
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp87
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h14
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp7
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp13
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp47
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h12
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp19
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.h1
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_core.cpp12
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_core.h3
-rw-r--r--src/core/hle/service/nvnflinger/buffer_transform_flags.h2
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.cpp20
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.h2
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp27
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp22
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h2
-rw-r--r--src/core/hle/service/pctl/pctl_module.cpp6
-rw-r--r--src/core/hle/service/sockets/bsd.cpp77
-rw-r--r--src/core/hle/service/sockets/bsd.h2
68 files changed, 4562 insertions, 3630 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 1b1c8190e..f21553644 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -3,11 +3,13 @@
#include <algorithm>
#include <array>
+
#include "common/common_types.h"
#include "common/fs/file.h"
#include "common/fs/path_util.h"
#include "common/logging/log.h"
#include "common/polyfill_ranges.h"
+#include "common/stb.h"
#include "common/string_util.h"
#include "common/swap.h"
#include "core/constants.h"
@@ -38,9 +40,36 @@ static std::filesystem::path GetImagePath(const Common::UUID& uuid) {
fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString());
}
-static constexpr u32 SanitizeJPEGSize(std::size_t size) {
+static void JPGToMemory(void* context, void* data, int len) {
+ std::vector<u8>* jpg_image = static_cast<std::vector<u8>*>(context);
+ unsigned char* jpg = static_cast<unsigned char*>(data);
+ jpg_image->insert(jpg_image->end(), jpg, jpg + len);
+}
+
+static void SanitizeJPEGImageSize(std::vector<u8>& image) {
constexpr std::size_t max_jpeg_image_size = 0x20000;
- return static_cast<u32>(std::min(size, max_jpeg_image_size));
+ constexpr int profile_dimensions = 256;
+ int original_width, original_height, color_channels;
+
+ const auto plain_image =
+ stbi_load_from_memory(image.data(), static_cast<int>(image.size()), &original_width,
+ &original_height, &color_channels, STBI_rgb);
+
+ // Resize image to match 256*256
+ if (original_width != profile_dimensions || original_height != profile_dimensions) {
+ // Use vector instead of array to avoid overflowing the stack
+ std::vector<u8> out_image(profile_dimensions * profile_dimensions * STBI_rgb);
+ stbir_resize_uint8_srgb(plain_image, original_width, original_height, 0, out_image.data(),
+ profile_dimensions, profile_dimensions, 0, STBI_rgb, 0,
+ STBIR_FILTER_BOX);
+ image.clear();
+ if (!stbi_write_jpg_to_func(JPGToMemory, &image, profile_dimensions, profile_dimensions,
+ STBI_rgb, out_image.data(), 0)) {
+ LOG_ERROR(Service_ACC, "Failed to resize the user provided image.");
+ }
+ }
+
+ image.resize(std::min(image.size(), max_jpeg_image_size));
}
class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> {
@@ -339,19 +368,20 @@ protected:
LOG_WARNING(Service_ACC,
"Failed to load user provided image! Falling back to built-in backup...");
ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG);
- rb.Push(SanitizeJPEGSize(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
+ rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
return;
}
- const u32 size = SanitizeJPEGSize(image.GetSize());
- std::vector<u8> buffer(size);
+ std::vector<u8> buffer(image.GetSize());
if (image.Read(buffer) != buffer.size()) {
LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
}
+ SanitizeJPEGImageSize(buffer);
+
ctx.WriteBuffer(buffer);
- rb.Push<u32>(size);
+ rb.Push(static_cast<u32>(buffer.size()));
}
void GetImageSize(HLERequestContext& ctx) {
@@ -365,10 +395,18 @@ protected:
if (!image.IsOpen()) {
LOG_WARNING(Service_ACC,
"Failed to load user provided image! Falling back to built-in backup...");
- rb.Push(SanitizeJPEGSize(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
- } else {
- rb.Push(SanitizeJPEGSize(image.GetSize()));
+ rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
+ return;
}
+
+ std::vector<u8> buffer(image.GetSize());
+
+ if (image.Read(buffer) != buffer.size()) {
+ LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
+ }
+
+ SanitizeJPEGImageSize(buffer);
+ rb.Push(static_cast<u32>(buffer.size()));
}
void Store(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 98765b81a..cc643ea09 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -23,6 +23,7 @@
#include "core/hle/service/am/applets/applet_cabinet.h"
#include "core/hle/service/am/applets/applet_mii_edit_types.h"
#include "core/hle/service/am/applets/applet_profile_select.h"
+#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
#include "core/hle/service/am/applets/applet_web_browser.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/idle.h"
@@ -31,6 +32,7 @@
#include "core/hle/service/apm/apm_controller.h"
#include "core/hle/service/apm/apm_interface.h"
#include "core/hle/service/bcat/backend/backend.h"
+#include "core/hle/service/caps/caps_su.h"
#include "core/hle/service/caps/caps_types.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/ipc_helpers.h"
@@ -702,9 +704,17 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& c
void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const auto album_report_option = rp.PopEnum<Capture::AlbumReportOption>();
+ const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
- LOG_WARNING(Service_AM, "(STUBBED) called. album_report_option={}", album_report_option);
+ LOG_INFO(Service_AM, "called, report_option={}", report_option);
+
+ const auto screenshot_service =
+ system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
+ "caps:su");
+
+ if (screenshot_service) {
+ screenshot_service->CaptureAndSaveScreenshot(report_option);
+ }
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -796,7 +806,9 @@ ILockAccessor::ILockAccessor(Core::System& system_)
lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
}
-ILockAccessor::~ILockAccessor() = default;
+ILockAccessor::~ILockAccessor() {
+ service_context.CloseEvent(lock_event);
+};
void ILockAccessor::TryLock(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -909,7 +921,9 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
}
-ICommonStateGetter::~ICommonStateGetter() = default;
+ICommonStateGetter::~ICommonStateGetter() {
+ service_context.CloseEvent(sleep_lock_event);
+};
void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
@@ -1558,7 +1572,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
{16, nullptr, "GetMainAppletStorageId"},
{17, nullptr, "GetCallerAppletIdentityInfoStack"},
{18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
- {19, nullptr, "GetDesirableKeyboardLayout"},
+ {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
{20, nullptr, "PopExtraStorage"},
{25, nullptr, "GetPopExtraStorageEvent"},
{30, nullptr, "UnpopInData"},
@@ -1577,7 +1591,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
{120, nullptr, "GetLaunchStorageInfoForDebug"},
{130, nullptr, "GetGpuErrorDetectedSystemEvent"},
{140, nullptr, "SetApplicationMemoryReservation"},
- {150, nullptr, "ShouldSetGpuTimeSliceManually"},
+ {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
};
// clang-format on
RegisterHandlers(functions);
@@ -1592,6 +1606,9 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
case Applets::AppletId::PhotoViewer:
PushInShowAlbum();
break;
+ case Applets::AppletId::SoftwareKeyboard:
+ PushInShowSoftwareKeyboard();
+ break;
default:
break;
}
@@ -1668,6 +1685,14 @@ void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext&
rb.PushRaw(applet_info);
}
+void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push<u32>(0);
+}
+
void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
const Service::Account::ProfileManager manager{};
bool is_empty{true};
@@ -1687,6 +1712,14 @@ void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext&
rb.Push(user_count);
}
+void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+ rb.Push<u8>(0);
+}
+
void ILibraryAppletSelfAccessor::PushInShowAlbum() {
const Applets::CommonArguments arguments{
.arguments_version = Applets::CommonArgumentVersion::Version3,
@@ -1755,6 +1788,61 @@ void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
queue_data.emplace_back(std::move(argument_data));
}
+void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
+ const Applets::CommonArguments arguments{
+ .arguments_version = Applets::CommonArgumentVersion::Version3,
+ .size = Applets::CommonArgumentSize::Version3,
+ .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301),
+ .theme_color = Applets::ThemeColor::BasicBlack,
+ .play_startup_sound = true,
+ .system_tick = system.CoreTiming().GetClockTicks(),
+ };
+
+ std::vector<char16_t> initial_string(0);
+
+ const Applets::SwkbdConfigCommon swkbd_config{
+ .type = Applets::SwkbdType::Qwerty,
+ .ok_text{},
+ .left_optional_symbol_key{},
+ .right_optional_symbol_key{},
+ .use_prediction = false,
+ .key_disable_flags{},
+ .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start,
+ .header_text{},
+ .sub_text{},
+ .guide_text{},
+ .max_text_length = 500,
+ .min_text_length = 0,
+ .password_mode = Applets::SwkbdPasswordMode::Disabled,
+ .text_draw_type = Applets::SwkbdTextDrawType::Box,
+ .enable_return_button = true,
+ .use_utf8 = false,
+ .use_blur_background = true,
+ .initial_string_offset{},
+ .initial_string_length = static_cast<u32>(initial_string.size()),
+ .user_dictionary_offset{},
+ .user_dictionary_entries{},
+ .use_text_check = false,
+ };
+
+ Applets::SwkbdConfigNew swkbd_config_new{};
+
+ std::vector<u8> argument_data(sizeof(arguments));
+ std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
+ std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
+
+ std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
+ std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
+ std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
+ sizeof(Applets::SwkbdConfigNew));
+ std::memcpy(work_buffer.data(), initial_string.data(),
+ swkbd_config.initial_string_length * sizeof(char16_t));
+
+ queue_data.emplace_back(std::move(argument_data));
+ queue_data.emplace_back(std::move(swkbd_data));
+ queue_data.emplace_back(std::move(work_buffer));
+}
+
IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
: ServiceFramework{system_, "IAppletCommonFunctions"} {
// clang-format off
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 64b3f3fe2..8f8cb8a9e 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -347,11 +347,14 @@ private:
void GetLibraryAppletInfo(HLERequestContext& ctx);
void ExitProcessAndReturn(HLERequestContext& ctx);
void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
+ void GetDesirableKeyboardLayout(HLERequestContext& ctx);
void GetMainAppletAvailableUsers(HLERequestContext& ctx);
+ void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
void PushInShowAlbum();
void PushInShowCabinetData();
void PushInShowMiiEditData();
+ void PushInShowSoftwareKeyboard();
std::deque<std::vector<u8>> queue_data;
};
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index 19ed184e8..b379dadeb 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -25,7 +25,9 @@ Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_,
service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent");
}
-Cabinet::~Cabinet() = default;
+Cabinet::~Cabinet() {
+ service_context.CloseEvent(availability_change_event);
+};
void Cabinet::Initialize() {
Applet::Initialize();
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 1c9a1dc29..b0ea2b381 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -330,8 +330,7 @@ void WebBrowser::ExtractOfflineRomFS() {
LOG_DEBUG(Service_AM, "Extracting RomFS to {}",
Common::FS::PathToUTF8String(offline_cache_dir));
- const auto extracted_romfs_dir =
- FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard);
+ const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs);
const auto temp_dir = system.GetFilesystem()->CreateDirectory(
Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite);
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index f02bbc450..0bf2598b7 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -69,6 +69,30 @@ enum class AppletId : u32 {
MyPage = 0x1A,
};
+enum class AppletProgramId : u64 {
+ QLaunch = 0x0100000000001000ull,
+ Auth = 0x0100000000001001ull,
+ Cabinet = 0x0100000000001002ull,
+ Controller = 0x0100000000001003ull,
+ DataErase = 0x0100000000001004ull,
+ Error = 0x0100000000001005ull,
+ NetConnect = 0x0100000000001006ull,
+ ProfileSelect = 0x0100000000001007ull,
+ SoftwareKeyboard = 0x0100000000001008ull,
+ MiiEdit = 0x0100000000001009ull,
+ Web = 0x010000000000100Aull,
+ Shop = 0x010000000000100Bull,
+ OverlayDisplay = 0x010000000000100Cull,
+ PhotoViewer = 0x010000000000100Dull,
+ Settings = 0x010000000000100Eull,
+ OfflineWeb = 0x010000000000100Full,
+ LoginShare = 0x0100000000001010ull,
+ WebAuth = 0x0100000000001011ull,
+ Starter = 0x0100000000001012ull,
+ MyPage = 0x0100000000001013ull,
+ MaxProgramId = 0x0100000000001FFFull,
+};
+
enum class LibraryAppletMode : u32 {
AllForeground = 0,
Background = 1,
diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp
index 7d733eb54..96b225d5f 100644
--- a/src/core/hle/service/caps/caps_manager.cpp
+++ b/src/core/hle/service/caps/caps_manager.cpp
@@ -228,12 +228,14 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail(
Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
const ScreenShotAttribute& attribute,
- std::span<const u8> image_data, u64 aruid) {
- return SaveScreenShot(out_entry, attribute, {}, image_data, aruid);
+ AlbumReportOption report_option, std::span<const u8> image_data,
+ u64 aruid) {
+ return SaveScreenShot(out_entry, attribute, report_option, {}, image_data, aruid);
}
Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
const ScreenShotAttribute& attribute,
+ AlbumReportOption report_option,
const ApplicationData& app_data, std::span<const u8> image_data,
u64 aruid) {
const u64 title_id = system.GetApplicationProcessProgramID();
@@ -407,10 +409,14 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p
return ResultSuccess;
}
-static void PNGToMemory(void* context, void* png, int len) {
+void AlbumManager::FlipVerticallyOnWrite(bool flip) {
+ stbi_flip_vertically_on_write(flip);
+}
+
+static void PNGToMemory(void* context, void* data, int len) {
std::vector<u8>* png_image = static_cast<std::vector<u8>*>(context);
- png_image->reserve(len);
- std::memcpy(png_image->data(), png, len);
+ unsigned char* png = static_cast<unsigned char*>(data);
+ png_image->insert(png_image->end(), png, png + len);
}
Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image,
diff --git a/src/core/hle/service/caps/caps_manager.h b/src/core/hle/service/caps/caps_manager.h
index 44d85117f..e20c70c7b 100644
--- a/src/core/hle/service/caps/caps_manager.h
+++ b/src/core/hle/service/caps/caps_manager.h
@@ -59,14 +59,17 @@ public:
const ScreenShotDecodeOption& decoder_options) const;
Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
- std::span<const u8> image_data, u64 aruid);
- Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
- const ApplicationData& app_data, std::span<const u8> image_data,
+ AlbumReportOption report_option, std::span<const u8> image_data,
u64 aruid);
+ Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
+ AlbumReportOption report_option, const ApplicationData& app_data,
+ std::span<const u8> image_data, u64 aruid);
Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
const ScreenShotAttribute& attribute, const AlbumFileId& file_id,
std::span<const u8> image_data);
+ void FlipVerticallyOnWrite(bool flip);
+
private:
static constexpr std::size_t NandAlbumFileLimit = 1000;
static constexpr std::size_t SdAlbumFileLimit = 10000;
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp
index 1ba2b7972..eab023568 100644
--- a/src/core/hle/service/caps/caps_ss.cpp
+++ b/src/core/hle/service/caps/caps_ss.cpp
@@ -34,7 +34,7 @@ void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
ScreenShotAttribute attribute{};
- u32 report_option{};
+ AlbumReportOption report_option{};
INSERT_PADDING_BYTES(0x4);
u64 applet_resource_user_id{};
};
@@ -49,13 +49,16 @@ void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) {
parameters.applet_resource_user_id);
ApplicationAlbumEntry entry{};
- const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer,
- parameters.applet_resource_user_id);
+ manager->FlipVerticallyOnWrite(false);
+ const auto result =
+ manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option,
+ image_data_buffer, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(result);
rb.PushRaw(entry);
}
+
void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
@@ -83,6 +86,7 @@ void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) {
image_data_buffer.size(), thumbnail_image_data_buffer.size());
ApplicationAlbumEntry entry{};
+ manager->FlipVerticallyOnWrite(false);
const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute,
parameters.file_id, image_data_buffer);
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp
index e85625ee4..296b07b00 100644
--- a/src/core/hle/service/caps/caps_su.cpp
+++ b/src/core/hle/service/caps/caps_su.cpp
@@ -2,10 +2,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/hle/service/caps/caps_manager.h"
#include "core/hle/service/caps/caps_su.h"
#include "core/hle/service/caps/caps_types.h"
#include "core/hle/service/ipc_helpers.h"
+#include "video_core/renderer_base.h"
namespace Service::Capture {
@@ -58,8 +60,10 @@ void IScreenShotApplicationService::SaveScreenShotEx0(HLERequestContext& ctx) {
parameters.applet_resource_user_id);
ApplicationAlbumEntry entry{};
- const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer,
- parameters.applet_resource_user_id);
+ manager->FlipVerticallyOnWrite(false);
+ const auto result =
+ manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option,
+ image_data_buffer, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(result);
@@ -88,13 +92,43 @@ void IScreenShotApplicationService::SaveScreenShotEx1(HLERequestContext& ctx) {
ApplicationAlbumEntry entry{};
ApplicationData app_data{};
std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData));
+ manager->FlipVerticallyOnWrite(false);
const auto result =
- manager->SaveScreenShot(entry, parameters.attribute, app_data, image_data_buffer,
- parameters.applet_resource_user_id);
+ manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option, app_data,
+ image_data_buffer, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(result);
rb.PushRaw(entry);
}
+void IScreenShotApplicationService::CaptureAndSaveScreenshot(AlbumReportOption report_option) {
+ auto& renderer = system.Renderer();
+ Layout::FramebufferLayout layout =
+ Layout::DefaultFrameLayout(screenshot_width, screenshot_height);
+
+ const Capture::ScreenShotAttribute attribute{
+ .unknown_0{},
+ .orientation = Capture::AlbumImageOrientation::None,
+ .unknown_1{},
+ .unknown_2{},
+ };
+
+ renderer.RequestScreenshot(
+ image_data.data(),
+ [attribute, report_option, this](bool invert_y) {
+ // Convert from BGRA to RGBA
+ for (std::size_t i = 0; i < image_data.size(); i += bytes_per_pixel) {
+ const u8 temp = image_data[i];
+ image_data[i] = image_data[i + 2];
+ image_data[i + 2] = temp;
+ }
+
+ Capture::ApplicationAlbumEntry entry{};
+ manager->FlipVerticallyOnWrite(invert_y);
+ manager->SaveScreenShot(entry, attribute, report_option, image_data, {});
+ },
+ layout);
+}
+
} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h
index 89e71f506..21912e95f 100644
--- a/src/core/hle/service/caps/caps_su.h
+++ b/src/core/hle/service/caps/caps_su.h
@@ -10,6 +10,7 @@ class System;
}
namespace Service::Capture {
+enum class AlbumReportOption : s32;
class AlbumManager;
class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> {
@@ -18,11 +19,19 @@ public:
std::shared_ptr<AlbumManager> album_manager);
~IScreenShotApplicationService() override;
+ void CaptureAndSaveScreenshot(AlbumReportOption report_option);
+
private:
+ static constexpr std::size_t screenshot_width = 1280;
+ static constexpr std::size_t screenshot_height = 720;
+ static constexpr std::size_t bytes_per_pixel = 4;
+
void SetShimLibraryVersion(HLERequestContext& ctx);
void SaveScreenShotEx0(HLERequestContext& ctx);
void SaveScreenShotEx1(HLERequestContext& ctx);
+ std::array<u8, screenshot_width * screenshot_height * bytes_per_pixel> image_data;
+
std::shared_ptr<AlbumManager> manager;
};
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp
index c58d67d7d..0bcd87062 100644
--- a/src/core/hle/service/hid/controllers/controller_base.cpp
+++ b/src/core/hle/service/hid/controllers/controller_base.cpp
@@ -8,12 +8,17 @@ namespace Service::HID {
ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {}
ControllerBase::~ControllerBase() = default;
-void ControllerBase::ActivateController() {
+Result ControllerBase::Activate() {
if (is_activated) {
- return;
+ return ResultSuccess;
}
is_activated = true;
OnInit();
+ return ResultSuccess;
+}
+
+Result ControllerBase::Activate(u64 aruid) {
+ return Activate();
}
void ControllerBase::DeactivateController() {
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index d6f7a5073..9a44ee41e 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -4,6 +4,7 @@
#pragma once
#include "common/common_types.h"
+#include "core/hle/result.h"
namespace Core::Timing {
class CoreTiming;
@@ -31,7 +32,8 @@ public:
// When the controller is requesting a motion update for the shared memory
virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {}
- void ActivateController();
+ Result Activate();
+ Result Activate(u64 aruid);
void DeactivateController();
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index bc822f19e..d46bf917e 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -457,12 +457,14 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
pad_entry.l_stick = stick_state.left;
}
- if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
+ if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft ||
+ controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
}
- if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
+ if (controller_type == Core::HID::NpadStyleIndex::JoyconRight ||
+ controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
}
@@ -1108,9 +1110,9 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
shared_memory->sixaxis_dual_right_properties.raw = 0;
shared_memory->sixaxis_left_properties.raw = 0;
shared_memory->sixaxis_right_properties.raw = 0;
- shared_memory->battery_level_dual = 0;
- shared_memory->battery_level_left = 0;
- shared_memory->battery_level_right = 0;
+ shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty;
+ shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty;
+ shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty;
shared_memory->fullkey_color = {
.attribute = ColorAttribute::NoController,
.fullkey = {},
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 949e58a4c..e23b4986c 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -86,6 +86,13 @@ public:
Default = 3,
};
+ enum class NpadRevision : u32 {
+ Revision0 = 0,
+ Revision1 = 1,
+ Revision2 = 2,
+ Revision3 = 3,
+ };
+
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp
index 14c67e454..51a18335f 100644
--- a/src/core/hle/service/hid/controllers/palma.cpp
+++ b/src/core/hle/service/hid/controllers/palma.cpp
@@ -19,7 +19,9 @@ Controller_Palma::Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared
operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
}
-Controller_Palma::~Controller_Palma() = default;
+Controller_Palma::~Controller_Palma() {
+ service_context.CloseEvent(operation_complete_event);
+};
void Controller_Palma::OnInit() {}
@@ -42,7 +44,7 @@ Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
- ActivateController();
+ Activate();
return ResultSuccess;
}
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 4d70006c1..1b7381d8d 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1,2860 +1,39 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <array>
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "common/settings.h"
-#include "core/core.h"
-#include "core/core_timing.h"
-#include "core/hid/hid_core.h"
-#include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/kernel/k_shared_memory.h"
-#include "core/hle/kernel/k_transfer_memory.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid.h"
+#include "core/hle/service/hid/hid_debug_server.h"
+#include "core/hle/service/hid/hid_firmware_settings.h"
+#include "core/hle/service/hid/hid_server.h"
+#include "core/hle/service/hid/hid_system_server.h"
#include "core/hle/service/hid/hidbus.h"
#include "core/hle/service/hid/irs.h"
+#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/hid/xcd.h"
-#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/server_manager.h"
-#include "core/memory.h"
-
-#include "core/hle/service/hid/controllers/console_sixaxis.h"
-#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/hid/controllers/debug_pad.h"
-#include "core/hle/service/hid/controllers/gesture.h"
-#include "core/hle/service/hid/controllers/keyboard.h"
-#include "core/hle/service/hid/controllers/mouse.h"
-#include "core/hle/service/hid/controllers/npad.h"
-#include "core/hle/service/hid/controllers/palma.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 {
-// Updating period for each HID device.
-// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
-// Correct npad_update_ns is 4ms this is overclocked to lower input lag
-constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
-constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
-constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
-constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
-
-IAppletResource::IAppletResource(Core::System& system_,
- KernelHelpers::ServiceContext& service_context_)
- : ServiceFramework{system_, "IAppletResource"}, service_context{service_context_} {
- static const FunctionInfo functions[] = {
- {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
- };
- RegisterHandlers(functions);
- u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
- MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory);
- MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory);
- MakeController<Controller_Mouse>(HidController::Mouse, shared_memory);
- MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory);
- MakeController<Controller_XPad>(HidController::XPad, shared_memory);
- MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory);
- MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory);
- MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory);
- MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory);
- MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory);
- MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory);
- MakeController<Controller_Gesture>(HidController::Gesture, shared_memory);
- MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);
- MakeController<Controller_Stubbed>(HidController::DebugMouse, shared_memory);
- MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory);
-
- // Homebrew doesn't try to activate some controllers, so we activate them by default
- GetController<Controller_NPad>(HidController::NPad).ActivateController();
- GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController();
-
- GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
- GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
- GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
- GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
- GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
- GetController<Controller_Stubbed>(HidController::DebugMouse).SetCommonHeaderOffset(0x3DC00);
-
- // Register update callbacks
- npad_update_event = Core::Timing::CreateEvent(
- "HID::UpdatePadCallback",
- [this](std::uintptr_t user_data, s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- const auto guard = LockService();
- UpdateNpad(user_data, ns_late);
- return std::nullopt;
- });
- default_update_event = Core::Timing::CreateEvent(
- "HID::UpdateDefaultCallback",
- [this](std::uintptr_t user_data, s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- const auto guard = LockService();
- UpdateControllers(user_data, ns_late);
- return std::nullopt;
- });
- mouse_keyboard_update_event = Core::Timing::CreateEvent(
- "HID::UpdateMouseKeyboardCallback",
- [this](std::uintptr_t user_data, s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- const auto guard = LockService();
- UpdateMouseKeyboard(user_data, ns_late);
- return std::nullopt;
- });
- motion_update_event = Core::Timing::CreateEvent(
- "HID::UpdateMotionCallback",
- [this](std::uintptr_t user_data, s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- const auto guard = LockService();
- UpdateMotion(user_data, ns_late);
- return std::nullopt;
- });
-
- system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
- system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
- default_update_event);
- system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
- mouse_keyboard_update_event);
- system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
- motion_update_event);
-
- system.HIDCore().ReloadInputDevices();
-}
-
-void IAppletResource::ActivateController(HidController controller) {
- controllers[static_cast<size_t>(controller)]->ActivateController();
-}
-
-void IAppletResource::DeactivateController(HidController controller) {
- controllers[static_cast<size_t>(controller)]->DeactivateController();
-}
-
-IAppletResource::~IAppletResource() {
- system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
- system.CoreTiming().UnscheduleEvent(default_update_event, 0);
- system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
- system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
-}
-
-void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(&system.Kernel().GetHidSharedMem());
-}
-
-void IAppletResource::UpdateControllers(std::uintptr_t user_data,
- std::chrono::nanoseconds ns_late) {
- auto& core_timing = system.CoreTiming();
-
- for (const auto& controller : controllers) {
- // Keyboard has it's own update event
- if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
- continue;
- }
- // Mouse has it's own update event
- if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
- continue;
- }
- // Npad has it's own update event
- if (controller == controllers[static_cast<size_t>(HidController::NPad)]) {
- continue;
- }
- controller->OnUpdate(core_timing);
- }
-}
-
-void IAppletResource::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
- auto& core_timing = system.CoreTiming();
-
- controllers[static_cast<size_t>(HidController::NPad)]->OnUpdate(core_timing);
-}
-
-void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
- std::chrono::nanoseconds ns_late) {
- auto& core_timing = system.CoreTiming();
-
- controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing);
- controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);
-}
-
-void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
- auto& core_timing = system.CoreTiming();
-
- controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);
-}
-
-class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
-public:
- explicit IActiveVibrationDeviceList(Core::System& system_,
- std::shared_ptr<IAppletResource> applet_resource_)
- : ServiceFramework{system_, "IActiveVibrationDeviceList"},
- applet_resource(applet_resource_) {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void InitializeVibrationDevice(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
-
- if (applet_resource != nullptr) {
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .InitializeVibrationDevice(vibration_device_handle);
- }
-
- LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}",
- vibration_device_handle.npad_type, vibration_device_handle.npad_id,
- vibration_device_handle.device_index);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- std::shared_ptr<IAppletResource> applet_resource;
-};
-
-std::shared_ptr<IAppletResource> Hid::GetAppletResource() {
- if (applet_resource == nullptr) {
- applet_resource = std::make_shared<IAppletResource>(system, service_context);
- }
-
- return applet_resource;
-}
-
-Hid::Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_)
- : ServiceFramework{system_, "hid"}, applet_resource{applet_resource_}, service_context{
- system_,
- service_name} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &Hid::CreateAppletResource, "CreateAppletResource"},
- {1, &Hid::ActivateDebugPad, "ActivateDebugPad"},
- {11, &Hid::ActivateTouchScreen, "ActivateTouchScreen"},
- {21, &Hid::ActivateMouse, "ActivateMouse"},
- {26, nullptr, "ActivateDebugMouse"},
- {31, &Hid::ActivateKeyboard, "ActivateKeyboard"},
- {32, &Hid::SendKeyboardLockKeyEvent, "SendKeyboardLockKeyEvent"},
- {40, nullptr, "AcquireXpadIdEventHandle"},
- {41, nullptr, "ReleaseXpadIdEventHandle"},
- {51, &Hid::ActivateXpad, "ActivateXpad"},
- {55, &Hid::GetXpadIDs, "GetXpadIds"},
- {56, nullptr, "ActivateJoyXpad"},
- {58, nullptr, "GetJoyXpadLifoHandle"},
- {59, nullptr, "GetJoyXpadIds"},
- {60, &Hid::ActivateSixAxisSensor, "ActivateSixAxisSensor"},
- {61, &Hid::DeactivateSixAxisSensor, "DeactivateSixAxisSensor"},
- {62, nullptr, "GetSixAxisSensorLifoHandle"},
- {63, nullptr, "ActivateJoySixAxisSensor"},
- {64, nullptr, "DeactivateJoySixAxisSensor"},
- {65, nullptr, "GetJoySixAxisSensorLifoHandle"},
- {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
- {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
- {68, &Hid::IsSixAxisSensorFusionEnabled, "IsSixAxisSensorFusionEnabled"},
- {69, &Hid::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
- {70, &Hid::SetSixAxisSensorFusionParameters, "SetSixAxisSensorFusionParameters"},
- {71, &Hid::GetSixAxisSensorFusionParameters, "GetSixAxisSensorFusionParameters"},
- {72, &Hid::ResetSixAxisSensorFusionParameters, "ResetSixAxisSensorFusionParameters"},
- {73, nullptr, "SetAccelerometerParameters"},
- {74, nullptr, "GetAccelerometerParameters"},
- {75, nullptr, "ResetAccelerometerParameters"},
- {76, nullptr, "SetAccelerometerPlayMode"},
- {77, nullptr, "GetAccelerometerPlayMode"},
- {78, nullptr, "ResetAccelerometerPlayMode"},
- {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
- {80, &Hid::GetGyroscopeZeroDriftMode, "GetGyroscopeZeroDriftMode"},
- {81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
- {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
- {83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
- {84, &Hid::EnableSixAxisSensorUnalteredPassthrough, "EnableSixAxisSensorUnalteredPassthrough"},
- {85, &Hid::IsSixAxisSensorUnalteredPassthroughEnabled, "IsSixAxisSensorUnalteredPassthroughEnabled"},
- {86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
- {87, &Hid::LoadSixAxisSensorCalibrationParameter, "LoadSixAxisSensorCalibrationParameter"},
- {88, &Hid::GetSixAxisSensorIcInformation, "GetSixAxisSensorIcInformation"},
- {89, &Hid::ResetIsSixAxisSensorDeviceNewlyAssigned, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
- {91, &Hid::ActivateGesture, "ActivateGesture"},
- {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
- {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
- {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
- {103, &Hid::ActivateNpad, "ActivateNpad"},
- {104, &Hid::DeactivateNpad, "DeactivateNpad"},
- {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
- {107, &Hid::DisconnectNpad, "DisconnectNpad"},
- {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
- {109, &Hid::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
- {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
- {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
- {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
- {123, &Hid::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"},
- {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
- {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
- {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"},
- {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"},
- {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
- {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
- {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
- {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
- {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
- {133, &Hid::SetNpadJoyAssignmentModeSingleWithDestination, "SetNpadJoyAssignmentModeSingleWithDestination"},
- {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
- {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"},
- {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"},
- {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
- {201, &Hid::SendVibrationValue, "SendVibrationValue"},
- {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
- {203, &Hid::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
- {204, &Hid::PermitVibration, "PermitVibration"},
- {205, &Hid::IsVibrationPermitted, "IsVibrationPermitted"},
- {206, &Hid::SendVibrationValues, "SendVibrationValues"},
- {207, &Hid::SendVibrationGcErmCommand, "SendVibrationGcErmCommand"},
- {208, &Hid::GetActualVibrationGcErmCommand, "GetActualVibrationGcErmCommand"},
- {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
- {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"},
- {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
- {212, nullptr, "SendVibrationValueInBool"},
- {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
- {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
- {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"},
- {303, &Hid::ActivateSevenSixAxisSensor, "ActivateSevenSixAxisSensor"},
- {304, &Hid::StartSevenSixAxisSensor, "StartSevenSixAxisSensor"},
- {305, &Hid::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"},
- {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
- {307, &Hid::FinalizeSevenSixAxisSensor, "FinalizeSevenSixAxisSensor"},
- {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
- {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
- {310, &Hid::ResetSevenSixAxisSensorTimestamp, "ResetSevenSixAxisSensorTimestamp"},
- {400, &Hid::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
- {401, nullptr, "EnableUsbFullKeyController"},
- {402, nullptr, "IsUsbFullKeyControllerConnected"},
- {403, nullptr, "HasBattery"},
- {404, nullptr, "HasLeftRightBattery"},
- {405, nullptr, "GetNpadInterfaceType"},
- {406, nullptr, "GetNpadLeftRightInterfaceType"},
- {407, nullptr, "GetNpadOfHighestBatteryLevel"},
- {408, nullptr, "GetNpadOfHighestBatteryLevelForJoyRight"},
- {500, &Hid::GetPalmaConnectionHandle, "GetPalmaConnectionHandle"},
- {501, &Hid::InitializePalma, "InitializePalma"},
- {502, &Hid::AcquirePalmaOperationCompleteEvent, "AcquirePalmaOperationCompleteEvent"},
- {503, &Hid::GetPalmaOperationInfo, "GetPalmaOperationInfo"},
- {504, &Hid::PlayPalmaActivity, "PlayPalmaActivity"},
- {505, &Hid::SetPalmaFrModeType, "SetPalmaFrModeType"},
- {506, &Hid::ReadPalmaStep, "ReadPalmaStep"},
- {507, &Hid::EnablePalmaStep, "EnablePalmaStep"},
- {508, &Hid::ResetPalmaStep, "ResetPalmaStep"},
- {509, &Hid::ReadPalmaApplicationSection, "ReadPalmaApplicationSection"},
- {510, &Hid::WritePalmaApplicationSection, "WritePalmaApplicationSection"},
- {511, &Hid::ReadPalmaUniqueCode, "ReadPalmaUniqueCode"},
- {512, &Hid::SetPalmaUniqueCodeInvalid, "SetPalmaUniqueCodeInvalid"},
- {513, &Hid::WritePalmaActivityEntry, "WritePalmaActivityEntry"},
- {514, &Hid::WritePalmaRgbLedPatternEntry, "WritePalmaRgbLedPatternEntry"},
- {515, &Hid::WritePalmaWaveEntry, "WritePalmaWaveEntry"},
- {516, &Hid::SetPalmaDataBaseIdentificationVersion, "SetPalmaDataBaseIdentificationVersion"},
- {517, &Hid::GetPalmaDataBaseIdentificationVersion, "GetPalmaDataBaseIdentificationVersion"},
- {518, &Hid::SuspendPalmaFeature, "SuspendPalmaFeature"},
- {519, &Hid::GetPalmaOperationResult, "GetPalmaOperationResult"},
- {520, &Hid::ReadPalmaPlayLog, "ReadPalmaPlayLog"},
- {521, &Hid::ResetPalmaPlayLog, "ResetPalmaPlayLog"},
- {522, &Hid::SetIsPalmaAllConnectable, "SetIsPalmaAllConnectable"},
- {523, &Hid::SetIsPalmaPairedConnectable, "SetIsPalmaPairedConnectable"},
- {524, &Hid::PairPalma, "PairPalma"},
- {525, &Hid::SetPalmaBoostMode, "SetPalmaBoostMode"},
- {526, &Hid::CancelWritePalmaWaveEntry, "CancelWritePalmaWaveEntry"},
- {527, &Hid::EnablePalmaBoostMode, "EnablePalmaBoostMode"},
- {528, &Hid::GetPalmaBluetoothAddress, "GetPalmaBluetoothAddress"},
- {529, &Hid::SetDisallowedPalmaConnection, "SetDisallowedPalmaConnection"},
- {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"},
- {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"},
- {1002, &Hid::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"},
- {1003, &Hid::IsFirmwareUpdateNeededForNotification, "IsFirmwareUpdateNeededForNotification"},
- {2000, nullptr, "ActivateDigitizer"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-Hid::~Hid() = default;
-
-void Hid::CreateAppletResource(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- if (applet_resource == nullptr) {
- applet_resource = std::make_shared<IAppletResource>(system, service_context);
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAppletResource>(applet_resource);
-}
-
-void Hid::ActivateDebugPad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->ActivateController(HidController::DebugPad);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ActivateTouchScreen(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->ActivateController(HidController::Touchscreen);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ActivateMouse(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->ActivateController(HidController::Mouse);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ActivateKeyboard(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->ActivateController(HidController::Keyboard);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SendKeyboardLockKeyEvent(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto flags{rp.Pop<u32>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ActivateXpad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- u32 basic_xpad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- applet_resource->ActivateController(HidController::XPad);
-
- LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}",
- parameters.basic_xpad_id, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetXpadIDs(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(0);
-}
-
-void Hid::ActivateSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- u32 basic_xpad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- // This function does nothing on 10.0.0+
-
- LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
- parameters.basic_xpad_id, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::DeactivateSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- u32 basic_xpad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- // This function does nothing on 10.0.0+
-
- LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
- parameters.basic_xpad_id, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::StartSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, true);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::StopSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, false);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::IsSixAxisSensorFusionEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- bool is_enabled{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result =
- controller.IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(is_enabled);
-}
-
-void Hid::EnableSixAxisSensorFusion(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- bool enable_sixaxis_sensor_fusion;
- INSERT_PADDING_BYTES_NOINIT(3);
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle,
- parameters.enable_sixaxis_sensor_fusion);
-
- LOG_DEBUG(Service_HID,
- "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
- "device_index={}, applet_resource_user_id={}",
- parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
- parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
- parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::SetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- Core::HID::SixAxisSensorFusionParameters sixaxis_fusion;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result =
- controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
- "parameter2={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1,
- parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::GetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- Core::HID::SixAxisSensorFusionParameters fusion_parameters{};
- const auto& controller =
- GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result =
- controller.GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(result);
- rb.PushRaw(fusion_parameters);
-}
-
-void Hid::ResetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- // Since these parameters are unknown just use what HW outputs
- const Core::HID::SixAxisSensorFusionParameters fusion_parameters{
- .parameter1 = 0.03f,
- .parameter2 = 0.4f,
- };
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result1 =
- controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
- const auto result2 = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle, true);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- if (result1.IsError()) {
- rb.Push(result1);
- return;
- }
- rb.Push(result2);
-}
-
-void Hid::SetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
- const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
- "applet_resource_user_id={}",
- sixaxis_handle.npad_type, sixaxis_handle.npad_id, sixaxis_handle.device_index,
- drift_mode, applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::GetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.PushEnum(drift_mode);
-}
-
-void Hid::ResetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::IsSixAxisSensorAtRest(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- bool is_at_rest{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- controller.IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(is_at_rest);
-}
-
-void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- bool is_firmware_available{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- controller.IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
- is_firmware_available);
-
- LOG_WARNING(
- Service_HID,
- "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(is_firmware_available);
-}
-
-void Hid::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- bool enabled;
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.EnableSixAxisSensorUnalteredPassthrough(
- parameters.sixaxis_handle, parameters.enabled);
-
- LOG_DEBUG(Service_HID,
- "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
- "applet_resource_user_id={}",
- parameters.enabled, parameters.sixaxis_handle.npad_type,
- parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
- parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- bool is_unaltered_sisxaxis_enabled{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled(
- parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
-
- LOG_DEBUG(
- Service_HID,
- "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(is_unaltered_sisxaxis_enabled);
-}
-
-void Hid::LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- Core::HID::SixAxisSensorCalibrationParameter calibration{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result =
- controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
-
- LOG_WARNING(
- Service_HID,
- "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- if (result.IsSuccess()) {
- ctx.WriteBuffer(calibration);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::GetSixAxisSensorIcInformation(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- Core::HID::SixAxisSensorIcInformation ic_information{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result =
- controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
-
- LOG_WARNING(
- Service_HID,
- "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- if (result.IsSuccess()) {
- ctx.WriteBuffer(ic_information);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::SixAxisSensorHandle sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result =
- controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
-
- LOG_WARNING(
- Service_HID,
- "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
- parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::ActivateGesture(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- u32 unknown;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- applet_resource->ActivateController(HidController::Gesture);
-
- LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
- parameters.unknown, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetSupportedNpadStyleSet(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadStyleSet supported_styleset;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .SetSupportedStyleSet({parameters.supported_styleset});
-
- LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
- parameters.supported_styleset, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetSupportedNpadStyleSet(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .GetSupportedStyleSet()
- .raw);
-}
-
-void Hid::SetSupportedNpadIdType(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- const auto result = applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .SetSupportedNpadIdTypes(ctx.ReadBuffer());
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::ActivateNpad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->ActivateController(HidController::NPad);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::DeactivateNpad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->DeactivateController(HidController::NPad);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- u64 unknown;
- };
- static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
- parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown);
-
- // Games expect this event to be signaled after calling this function
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .SignalStyleSetChangedEvent(parameters.npad_id);
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .GetStyleSetChangedEvent(parameters.npad_id));
-}
-
-void Hid::DisconnectNpad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- controller.DisconnectNpad(parameters.npad_id);
-
- LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
- parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetPlayerLedPattern(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
-
- Core::HID::LedPattern pattern{0, 0, 0, 0};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.GetLedPattern(npad_id, pattern);
-
- LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(result);
- rb.Push(pattern.raw);
-}
-
-void Hid::ActivateNpadWithRevision(HLERequestContext& ctx) {
- // Should have no effect with how our npad sets up the data
- IPC::RequestParser rp{ctx};
- struct Parameters {
- s32 revision;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- applet_resource->ActivateController(HidController::NPad);
-
- LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
- parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetNpadJoyHoldType(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}",
- applet_resource_user_id, hold_type);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetNpadJoyHoldType(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad).GetHoldType());
-}
-
-void Hid::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- controller.SetNpadMode(new_npad_id, parameters.npad_id,
- Controller_NPad::NpadJoyDeviceType::Left,
- Controller_NPad::NpadJoyAssignmentMode::Single);
-
- LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
- parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
- };
- static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
- Controller_NPad::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,
- parameters.npad_joy_device_type);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- controller.SetNpadMode(new_npad_id, parameters.npad_id, {},
- Controller_NPad::NpadJoyAssignmentMode::Dual);
-
- LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
- parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
- const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
-
- LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
- npad_id_1, npad_id_2, applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::StartLrAssignmentMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad).StartLRAssignmentMode();
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::StopLrAssignmentMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad).StopLRAssignmentMode();
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .SetNpadHandheldActivationMode(activation_mode);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}",
- applet_resource_user_id, activation_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetNpadHandheldActivationMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .GetNpadHandheldActivationMode());
-}
-
-void Hid::SwapNpadAssignment(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
- const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2);
-
- LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
- npad_id_1, npad_id_2, applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- bool is_enabled = false;
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result =
- controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
-
- LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
- parameters.npad_id, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(is_enabled);
-}
-
-void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- bool unintended_home_button_input_protection;
- INSERT_PADDING_BYTES_NOINIT(3);
- Core::HID::NpadIdType npad_id;
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
- parameters.unintended_home_button_input_protection, parameters.npad_id);
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={},"
- "applet_resource_user_id={}",
- parameters.unintended_home_button_input_protection, parameters.npad_id,
- parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
- };
- static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- Core::HID::NpadIdType new_npad_id{};
- auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
- const auto is_reassigned =
- controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
- Controller_NPad::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,
- parameters.npad_joy_device_type);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(is_reassigned);
- rb.PushEnum(new_npad_id);
-}
-
-void Hid::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- bool analog_stick_use_center_clamp;
- INSERT_PADDING_BYTES_NOINIT(7);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- GetAppletResource()
- ->GetController<Controller_NPad>(HidController::NPad)
- .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
- parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetNpadCaptureButtonAssignment(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadStyleSet npad_styleset;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- Core::HID::NpadButton button;
- };
- static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, npad_styleset={}, applet_resource_user_id={}, button={}",
- parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
- applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetVibrationDeviceInfo(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
- const auto& controller =
- GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
-
- Core::HID::VibrationDeviceInfo vibration_device_info;
- bool check_device_index = false;
-
- switch (vibration_device_handle.npad_type) {
- case Core::HID::NpadStyleIndex::ProController:
- case Core::HID::NpadStyleIndex::Handheld:
- case Core::HID::NpadStyleIndex::JoyconDual:
- case Core::HID::NpadStyleIndex::JoyconLeft:
- case Core::HID::NpadStyleIndex::JoyconRight:
- vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
- check_device_index = true;
- break;
- case Core::HID::NpadStyleIndex::GameCube:
- vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
- break;
- case Core::HID::NpadStyleIndex::N64:
- vibration_device_info.type = Core::HID::VibrationDeviceType::N64;
- break;
- default:
- vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
- break;
- }
-
- vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
- if (check_device_index) {
- switch (vibration_device_handle.device_index) {
- case Core::HID::DeviceIndex::Left:
- vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
- break;
- case Core::HID::DeviceIndex::Right:
- vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
- break;
- case Core::HID::DeviceIndex::None:
- default:
- ASSERT_MSG(false, "DeviceIndex should never be None!");
- break;
- }
- }
-
- LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}",
- vibration_device_info.type, vibration_device_info.position);
-
- const auto result = controller.IsDeviceHandleValid(vibration_device_handle);
- if (result.IsError()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushRaw(vibration_device_info);
-}
-
-void Hid::SendVibrationValue(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::VibrationDeviceHandle vibration_device_handle;
- Core::HID::VibrationValue vibration_value;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .VibrateController(parameters.vibration_device_handle, parameters.vibration_value);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.vibration_device_handle.npad_type,
- parameters.vibration_device_handle.npad_id,
- parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetActualVibrationValue(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::VibrationDeviceHandle vibration_device_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.vibration_device_handle.npad_type,
- parameters.vibration_device_handle.npad_id,
- parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .GetLastVibration(parameters.vibration_device_handle));
-}
-
-void Hid::CreateActiveVibrationDeviceList(HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IActiveVibrationDeviceList>(system, applet_resource);
-}
-
-void Hid::PermitVibration(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto can_vibrate{rp.Pop<bool>()};
-
- // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
- // by converting it to a bool
- Settings::values.vibration_enabled.SetValue(can_vibrate);
-
- LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::IsVibrationPermitted(HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "called");
-
- // nnSDK checks if a float is greater than zero. We return the bool we stored earlier
- const auto is_enabled = Settings::values.vibration_enabled.GetValue();
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(is_enabled);
-}
-
-void Hid::SendVibrationValues(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- const auto handle_data = ctx.ReadBuffer(0);
- const auto handle_count = ctx.GetReadBufferNumElements<Core::HID::VibrationDeviceHandle>(0);
- const auto vibration_data = ctx.ReadBuffer(1);
- const auto vibration_count = ctx.GetReadBufferNumElements<Core::HID::VibrationValue>(1);
-
- auto vibration_device_handles =
- std::span(reinterpret_cast<const Core::HID::VibrationDeviceHandle*>(handle_data.data()),
- handle_count);
- auto vibration_values = std::span(
- reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .VibrateControllers(vibration_device_handles, vibration_values);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SendVibrationGcErmCommand(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::VibrationDeviceHandle vibration_device_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- Core::HID::VibrationGcErmCommand gc_erm_command;
- };
- static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- /**
- * Note: This uses yuzu-specific behavior such that the StopHard command produces
- * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below,
- * in order to differentiate between Stop and StopHard commands.
- * This is done to reuse the controller vibration functions made for regular controllers.
- */
- const auto vibration_value = [parameters] {
- switch (parameters.gc_erm_command) {
- case Core::HID::VibrationGcErmCommand::Stop:
- return Core::HID::VibrationValue{
- .low_amplitude = 0.0f,
- .low_frequency = 160.0f,
- .high_amplitude = 0.0f,
- .high_frequency = 320.0f,
- };
- case Core::HID::VibrationGcErmCommand::Start:
- return Core::HID::VibrationValue{
- .low_amplitude = 1.0f,
- .low_frequency = 160.0f,
- .high_amplitude = 1.0f,
- .high_frequency = 320.0f,
- };
- case Core::HID::VibrationGcErmCommand::StopHard:
- return Core::HID::VibrationValue{
- .low_amplitude = 0.0f,
- .low_frequency = 0.0f,
- .high_amplitude = 0.0f,
- .high_frequency = 0.0f,
- };
- default:
- return Core::HID::DEFAULT_VIBRATION_VALUE;
- }
- }();
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .VibrateController(parameters.vibration_device_handle, vibration_value);
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
- "gc_erm_command={}",
- parameters.vibration_device_handle.npad_type,
- parameters.vibration_device_handle.npad_id,
- parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id,
- parameters.gc_erm_command);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::VibrationDeviceHandle vibration_device_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- const auto last_vibration = applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .GetLastVibration(parameters.vibration_device_handle);
-
- const auto gc_erm_command = [last_vibration] {
- if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
- return Core::HID::VibrationGcErmCommand::Start;
- }
-
- /**
- * Note: This uses yuzu-specific behavior such that the StopHard command produces
- * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function
- * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
- * This is done to reuse the controller vibration functions made for regular controllers.
- */
- if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
- return Core::HID::VibrationGcErmCommand::StopHard;
- }
-
- return Core::HID::VibrationGcErmCommand::Stop;
- }();
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.vibration_device_handle.npad_type,
- parameters.vibration_device_handle.npad_id,
- parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(gc_erm_command);
-}
-
-void Hid::BeginPermitVibrationSession(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .SetPermitVibrationSession(true);
-
- LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::EndPermitVibrationSession(HLERequestContext& ctx) {
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .SetPermitVibrationSession(false);
-
- LOG_DEBUG(Service_HID, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::IsVibrationDeviceMounted(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::VibrationDeviceHandle vibration_device_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_DEBUG(Service_HID,
- "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
- parameters.vibration_device_handle.npad_type,
- parameters.vibration_device_handle.npad_id,
- parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .IsVibrationDeviceMounted(parameters.vibration_device_handle));
-}
-
-void Hid::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->ActivateController(HidController::ConsoleSixAxisSensor);
-
- LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::StartConsoleSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
- parameters.console_sixaxis_handle.unknown_1,
- parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::StopConsoleSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
- parameters.console_sixaxis_handle.unknown_1,
- parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ActivateSevenSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->ActivateController(HidController::ConsoleSixAxisSensor);
-
- LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::StartSevenSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
- applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::StopSevenSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
- applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto t_mem_1_size{rp.Pop<u64>()};
- const auto t_mem_2_size{rp.Pop<u64>()};
- const auto t_mem_1_handle{ctx.GetCopyHandle(0)};
- const auto t_mem_2_handle{ctx.GetCopyHandle(1)};
-
- ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
- ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
-
- auto t_mem_1 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
- t_mem_1_handle);
-
- if (t_mem_1.IsNull()) {
- LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- auto t_mem_2 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
- t_mem_2_handle);
-
- if (t_mem_2.IsNull()) {
- LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size");
- ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
-
- // Activate console six axis controller
- applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
- .ActivateController();
-
- applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
- .SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
-
- LOG_WARNING(Service_HID,
- "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
- "applet_resource_user_id={}",
- t_mem_1_handle, t_mem_2_handle, applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::FinalizeSevenSixAxisSensor(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
- applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
- .ResetTimestamp();
-
- LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(false);
-}
-
-void Hid::GetPalmaConnectionHandle(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- Core::HID::NpadIdType npad_id;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
- parameters.npad_id, parameters.applet_resource_user_id);
-
- Controller_Palma::PalmaConnectionHandle handle;
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.GetPalmaConnectionHandle(parameters.npad_id, handle);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(result);
- rb.PushRaw(handle);
-}
-
-void Hid::InitializePalma(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.InitializePalma(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(controller.AcquirePalmaOperationCompleteEvent(connection_handle));
-}
-
-void Hid::GetPalmaOperationInfo(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- Controller_Palma::PalmaOperationType operation_type;
- Controller_Palma::PalmaOperationData data;
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.GetPalmaOperationInfo(connection_handle, operation_type, data);
-
- if (result.IsError()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- ctx.WriteBuffer(data);
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(result);
- rb.Push(static_cast<u64>(operation_type));
-}
-
-void Hid::PlayPalmaActivity(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
- const auto palma_activity{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, palma_activity={}",
- connection_handle.npad_id, palma_activity);
-
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.PlayPalmaActivity(connection_handle, palma_activity);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::SetPalmaFrModeType(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
- const auto fr_mode{rp.PopEnum<Controller_Palma::PalmaFrModeType>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, fr_mode={}",
- connection_handle.npad_id, fr_mode);
-
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.SetPalmaFrModeType(connection_handle, fr_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::ReadPalmaStep(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.ReadPalmaStep(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::EnablePalmaStep(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- bool is_enabled;
- INSERT_PADDING_WORDS_NOINIT(1);
- Controller_Palma::PalmaConnectionHandle connection_handle;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, is_enabled={}",
- parameters.connection_handle.npad_id, parameters.is_enabled);
-
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result =
- controller.EnablePalmaStep(parameters.connection_handle, parameters.is_enabled);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::ResetPalmaStep(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
- const auto result = controller.ResetPalmaStep(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::ReadPalmaApplicationSection(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::WritePalmaApplicationSection(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ReadPalmaUniqueCode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .ReadPalmaUniqueCode(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .SetPalmaUniqueCodeInvalid(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::WritePalmaActivityEntry(HLERequestContext& ctx) {
- LOG_CRITICAL(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
- const auto unknown{rp.Pop<u64>()};
-
- [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
- connection_handle.npad_id, unknown);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .WritePalmaRgbLedPatternEntry(connection_handle, unknown);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::WritePalmaWaveEntry(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
- const auto wave_set{rp.PopEnum<Controller_Palma::PalmaWaveSet>()};
- const auto unknown{rp.Pop<u64>()};
- const auto t_mem_size{rp.Pop<u64>()};
- const auto t_mem_handle{ctx.GetCopyHandle(0)};
- const auto size{rp.Pop<u64>()};
-
- ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes");
-
- auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
- t_mem_handle);
-
- if (t_mem.IsNull()) {
- LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size");
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, connection_handle={}, wave_set={}, unknown={}, "
- "t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
- connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .WritePalmaWaveEntry(connection_handle, wave_set, t_mem->GetSourceAddress(), t_mem_size);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- s32 database_id_version;
- INSERT_PADDING_WORDS_NOINIT(1);
- Controller_Palma::PalmaConnectionHandle connection_handle;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, database_id_version={}",
- parameters.connection_handle.npad_id, parameters.database_id_version);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .SetPalmaDataBaseIdentificationVersion(parameters.connection_handle,
- parameters.database_id_version);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .GetPalmaDataBaseIdentificationVersion(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SuspendPalmaFeature(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetPalmaOperationResult(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- const auto result = applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .GetPalmaOperationResult(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void Hid::ReadPalmaPlayLog(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::ResetPalmaPlayLog(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetIsPalmaAllConnectable(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- bool is_palma_all_connectable;
- INSERT_PADDING_BYTES_NOINIT(7);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID,
- "(STUBBED) called, is_palma_all_connectable={},applet_resource_user_id={}",
- parameters.is_palma_all_connectable, parameters.applet_resource_user_id);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetIsPalmaPairedConnectable(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::PairPalma(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .PairPalma(connection_handle);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetPalmaBoostMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto palma_boost_mode{rp.Pop<bool>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode);
-
- applet_resource->GetController<Controller_Palma>(HidController::Palma)
- .SetPalmaBoostMode(palma_boost_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::CancelWritePalmaWaveEntry(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::EnablePalmaBoostMode(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetPalmaBluetoothAddress(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::SetNpadCommunicationMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()};
-
- applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .SetNpadCommunicationMode(communication_mode);
-
- LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}",
- applet_resource_user_id, communication_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
- .GetNpadCommunicationMode());
-}
-
-void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()};
- const auto applet_resource_user_id{rp.Pop<u64>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
- touchscreen_mode.mode, applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void Hid::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- struct Parameters {
- s32 unknown;
- INSERT_PADDING_WORDS_NOINIT(1);
- u64 applet_resource_user_id;
- };
- static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
-
- const auto parameters{rp.PopRaw<Parameters>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
- parameters.unknown, parameters.applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(false);
-}
-
-class HidDbg final : public ServiceFramework<HidDbg> {
-public:
- explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "DeactivateDebugPad"},
- {1, nullptr, "SetDebugPadAutoPilotState"},
- {2, nullptr, "UnsetDebugPadAutoPilotState"},
- {10, nullptr, "DeactivateTouchScreen"},
- {11, nullptr, "SetTouchScreenAutoPilotState"},
- {12, nullptr, "UnsetTouchScreenAutoPilotState"},
- {13, nullptr, "GetTouchScreenConfiguration"},
- {14, nullptr, "ProcessTouchScreenAutoTune"},
- {15, nullptr, "ForceStopTouchScreenManagement"},
- {16, nullptr, "ForceRestartTouchScreenManagement"},
- {17, nullptr, "IsTouchScreenManaged"},
- {20, nullptr, "DeactivateMouse"},
- {21, nullptr, "SetMouseAutoPilotState"},
- {22, nullptr, "UnsetMouseAutoPilotState"},
- {25, nullptr, "SetDebugMouseAutoPilotState"},
- {26, nullptr, "UnsetDebugMouseAutoPilotState"},
- {30, nullptr, "DeactivateKeyboard"},
- {31, nullptr, "SetKeyboardAutoPilotState"},
- {32, nullptr, "UnsetKeyboardAutoPilotState"},
- {50, nullptr, "DeactivateXpad"},
- {51, nullptr, "SetXpadAutoPilotState"},
- {52, nullptr, "UnsetXpadAutoPilotState"},
- {53, nullptr, "DeactivateJoyXpad"},
- {60, nullptr, "ClearNpadSystemCommonPolicy"},
- {61, nullptr, "DeactivateNpad"},
- {62, nullptr, "ForceDisconnectNpad"},
- {91, nullptr, "DeactivateGesture"},
- {110, nullptr, "DeactivateHomeButton"},
- {111, nullptr, "SetHomeButtonAutoPilotState"},
- {112, nullptr, "UnsetHomeButtonAutoPilotState"},
- {120, nullptr, "DeactivateSleepButton"},
- {121, nullptr, "SetSleepButtonAutoPilotState"},
- {122, nullptr, "UnsetSleepButtonAutoPilotState"},
- {123, nullptr, "DeactivateInputDetector"},
- {130, nullptr, "DeactivateCaptureButton"},
- {131, nullptr, "SetCaptureButtonAutoPilotState"},
- {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
- {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
- {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
- {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
- {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
- {140, nullptr, "DeactivateConsoleSixAxisSensor"},
- {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
- {142, nullptr, "DeactivateSevenSixAxisSensor"},
- {143, nullptr, "GetConsoleSixAxisSensorCountStates"},
- {144, nullptr, "GetAccelerometerFsr"},
- {145, nullptr, "SetAccelerometerFsr"},
- {146, nullptr, "GetAccelerometerOdr"},
- {147, nullptr, "SetAccelerometerOdr"},
- {148, nullptr, "GetGyroscopeFsr"},
- {149, nullptr, "SetGyroscopeFsr"},
- {150, nullptr, "GetGyroscopeOdr"},
- {151, nullptr, "SetGyroscopeOdr"},
- {152, nullptr, "GetWhoAmI"},
- {201, nullptr, "ActivateFirmwareUpdate"},
- {202, nullptr, "DeactivateFirmwareUpdate"},
- {203, nullptr, "StartFirmwareUpdate"},
- {204, nullptr, "GetFirmwareUpdateStage"},
- {205, nullptr, "GetFirmwareVersion"},
- {206, nullptr, "GetDestinationFirmwareVersion"},
- {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
- {208, nullptr, "StartFirmwareUpdateForRevert"},
- {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
- {210, nullptr, "IsFirmwareUpdatingDevice"},
- {211, nullptr, "StartFirmwareUpdateIndividual"},
- {215, nullptr, "SetUsbFirmwareForceUpdateEnabled"},
- {216, nullptr, "SetAllKuinaDevicesToFirmwareUpdateMode"},
- {221, nullptr, "UpdateControllerColor"},
- {222, nullptr, "ConnectUsbPadsAsync"},
- {223, nullptr, "DisconnectUsbPadsAsync"},
- {224, nullptr, "UpdateDesignInfo"},
- {225, nullptr, "GetUniquePadDriverState"},
- {226, nullptr, "GetSixAxisSensorDriverStates"},
- {227, nullptr, "GetRxPacketHistory"},
- {228, nullptr, "AcquireOperationEventHandle"},
- {229, nullptr, "ReadSerialFlash"},
- {230, nullptr, "WriteSerialFlash"},
- {231, nullptr, "GetOperationResult"},
- {232, nullptr, "EnableShipmentMode"},
- {233, nullptr, "ClearPairingInfo"},
- {234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
- {235, nullptr, "EnableAnalogStickPower"},
- {236, nullptr, "RequestKuinaUartClockCal"},
- {237, nullptr, "GetKuinaUartClockCal"},
- {238, nullptr, "SetKuinaUartClockTrim"},
- {239, nullptr, "KuinaLoopbackTest"},
- {240, nullptr, "RequestBatteryVoltage"},
- {241, nullptr, "GetBatteryVoltage"},
- {242, nullptr, "GetUniquePadPowerInfo"},
- {243, nullptr, "RebootUniquePad"},
- {244, nullptr, "RequestKuinaFirmwareVersion"},
- {245, nullptr, "GetKuinaFirmwareVersion"},
- {246, nullptr, "GetVidPid"},
- {247, nullptr, "GetAnalogStickCalibrationValue"},
- {248, nullptr, "GetUniquePadIdsFull"},
- {249, nullptr, "ConnectUniquePad"},
- {250, nullptr, "IsVirtual"},
- {251, nullptr, "GetAnalogStickModuleParam"},
- {301, nullptr, "GetAbstractedPadHandles"},
- {302, nullptr, "GetAbstractedPadState"},
- {303, nullptr, "GetAbstractedPadsState"},
- {321, nullptr, "SetAutoPilotVirtualPadState"},
- {322, nullptr, "UnsetAutoPilotVirtualPadState"},
- {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
- {324, nullptr, "AttachHdlsWorkBuffer"},
- {325, nullptr, "ReleaseHdlsWorkBuffer"},
- {326, nullptr, "DumpHdlsNpadAssignmentState"},
- {327, nullptr, "DumpHdlsStates"},
- {328, nullptr, "ApplyHdlsNpadAssignmentState"},
- {329, nullptr, "ApplyHdlsStateList"},
- {330, nullptr, "AttachHdlsVirtualDevice"},
- {331, nullptr, "DetachHdlsVirtualDevice"},
- {332, nullptr, "SetHdlsState"},
- {350, nullptr, "AddRegisteredDevice"},
- {400, nullptr, "DisableExternalMcuOnNxDevice"},
- {401, nullptr, "DisableRailDeviceFiltering"},
- {402, nullptr, "EnableWiredPairing"},
- {403, nullptr, "EnableShipmentModeAutoClear"},
- {404, nullptr, "SetRailEnabled"},
- {500, nullptr, "SetFactoryInt"},
- {501, nullptr, "IsFactoryBootEnabled"},
- {550, nullptr, "SetAnalogStickModelDataTemporarily"},
- {551, nullptr, "GetAnalogStickModelData"},
- {552, nullptr, "ResetAnalogStickModelData"},
- {600, nullptr, "ConvertPadState"},
- {650, nullptr, "AddButtonPlayData"},
- {651, nullptr, "StartButtonPlayData"},
- {652, nullptr, "StopButtonPlayData"},
- {2000, nullptr, "DeactivateDigitizer"},
- {2001, nullptr, "SetDigitizerAutoPilotState"},
- {2002, nullptr, "UnsetDigitizerAutoPilotState"},
- {2002, nullptr, "ReloadFirmwareDebugSettings"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class HidSys final : public ServiceFramework<HidSys> {
-public:
- explicit HidSys(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_)
- : ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"},
- applet_resource{applet_resource_} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {31, nullptr, "SendKeyboardLockKeyEvent"},
- {101, nullptr, "AcquireHomeButtonEventHandle"},
- {111, nullptr, "ActivateHomeButton"},
- {121, nullptr, "AcquireSleepButtonEventHandle"},
- {131, nullptr, "ActivateSleepButton"},
- {141, nullptr, "AcquireCaptureButtonEventHandle"},
- {151, nullptr, "ActivateCaptureButton"},
- {161, nullptr, "GetPlatformConfig"},
- {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
- {211, nullptr, "GetNpadsWithNfc"},
- {212, nullptr, "AcquireNfcActivateEventHandle"},
- {213, nullptr, "ActivateNfc"},
- {214, nullptr, "GetXcdHandleForNpadWithNfc"},
- {215, nullptr, "IsNfcActivated"},
- {230, nullptr, "AcquireIrSensorEventHandle"},
- {231, nullptr, "ActivateIrSensor"},
- {232, nullptr, "GetIrSensorState"},
- {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
- {301, nullptr, "ActivateNpadSystem"},
- {303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
- {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
- {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
- {306, &HidSys::GetLastActiveNpad, "GetLastActiveNpad"},
- {307, nullptr, "GetNpadSystemExtStyle"},
- {308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
- {309, nullptr, "GetNpadFullKeyGripColor"},
- {310, nullptr, "GetMaskedSupportedNpadStyleSet"},
- {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
- {312, nullptr, "SetSupportedNpadStyleSetAll"},
- {313, nullptr, "GetNpadCaptureButtonAssignment"},
- {314, nullptr, "GetAppletFooterUiType"},
- {315, nullptr, "GetAppletDetailedUiType"},
- {316, nullptr, "GetNpadInterfaceType"},
- {317, nullptr, "GetNpadLeftRightInterfaceType"},
- {318, nullptr, "HasBattery"},
- {319, nullptr, "HasLeftRightBattery"},
- {321, &HidSys::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
- {322, nullptr, "GetIrSensorState"},
- {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
- {324, nullptr, "GetUniquePadButtonSet"},
- {325, nullptr, "GetUniquePadColor"},
- {326, nullptr, "GetUniquePadAppletDetailedUiType"},
- {327, nullptr, "GetAbstractedPadIdDataFromNpad"},
- {328, nullptr, "AttachAbstractedPadToNpad"},
- {329, nullptr, "DetachAbstractedPadAll"},
- {330, nullptr, "CheckAbstractedPadConnection"},
- {500, nullptr, "SetAppletResourceUserId"},
- {501, nullptr, "RegisterAppletResourceUserId"},
- {502, nullptr, "UnregisterAppletResourceUserId"},
- {503, nullptr, "EnableAppletToGetInput"},
- {504, nullptr, "SetAruidValidForVibration"},
- {505, nullptr, "EnableAppletToGetSixAxisSensor"},
- {506, nullptr, "EnableAppletToGetPadInput"},
- {507, nullptr, "EnableAppletToGetTouchScreen"},
- {510, nullptr, "SetVibrationMasterVolume"},
- {511, nullptr, "GetVibrationMasterVolume"},
- {512, nullptr, "BeginPermitVibrationSession"},
- {513, nullptr, "EndPermitVibrationSession"},
- {514, nullptr, "Unknown514"},
- {520, nullptr, "EnableHandheldHids"},
- {521, nullptr, "DisableHandheldHids"},
- {522, nullptr, "SetJoyConRailEnabled"},
- {523, nullptr, "IsJoyConRailEnabled"},
- {524, nullptr, "IsHandheldHidsEnabled"},
- {525, nullptr, "IsJoyConAttachedOnAllRail"},
- {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
- {541, nullptr, "GetPlayReportControllerUsages"},
- {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
- {543, nullptr, "GetRegisteredDevicesOld"},
- {544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
- {545, nullptr, "SendConnectionTrigger"},
- {546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
- {547, nullptr, "GetAllowedBluetoothLinksCount"},
- {548, nullptr, "GetRegisteredDevices"},
- {549, nullptr, "GetConnectableRegisteredDevices"},
- {700, nullptr, "ActivateUniquePad"},
- {702, nullptr, "AcquireUniquePadConnectionEventHandle"},
- {703, nullptr, "GetUniquePadIds"},
- {751, &HidSys::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
- {800, nullptr, "ListSixAxisSensorHandles"},
- {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
- {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
- {803, nullptr, "StartSixAxisSensorUserCalibration"},
- {804, nullptr, "CancelSixAxisSensorUserCalibration"},
- {805, nullptr, "GetUniquePadBluetoothAddress"},
- {806, nullptr, "DisconnectUniquePad"},
- {807, nullptr, "GetUniquePadType"},
- {808, nullptr, "GetUniquePadInterface"},
- {809, nullptr, "GetUniquePadSerialNumber"},
- {810, nullptr, "GetUniquePadControllerNumber"},
- {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
- {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
- {821, nullptr, "StartAnalogStickManualCalibration"},
- {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
- {823, nullptr, "CancelAnalogStickManualCalibration"},
- {824, nullptr, "ResetAnalogStickManualCalibration"},
- {825, nullptr, "GetAnalogStickState"},
- {826, nullptr, "GetAnalogStickManualCalibrationStage"},
- {827, nullptr, "IsAnalogStickButtonPressed"},
- {828, nullptr, "IsAnalogStickInReleasePosition"},
- {829, nullptr, "IsAnalogStickInCircumference"},
- {830, nullptr, "SetNotificationLedPattern"},
- {831, nullptr, "SetNotificationLedPatternWithTimeout"},
- {832, nullptr, "PrepareHidsForNotificationWake"},
- {850, &HidSys::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
- {851, nullptr, "EnableUsbFullKeyController"},
- {852, nullptr, "IsUsbConnected"},
- {870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
- {900, nullptr, "ActivateInputDetector"},
- {901, nullptr, "NotifyInputDetector"},
- {1000, nullptr, "InitializeFirmwareUpdate"},
- {1001, nullptr, "GetFirmwareVersion"},
- {1002, nullptr, "GetAvailableFirmwareVersion"},
- {1003, nullptr, "IsFirmwareUpdateAvailable"},
- {1004, nullptr, "CheckFirmwareUpdateRequired"},
- {1005, nullptr, "StartFirmwareUpdate"},
- {1006, nullptr, "AbortFirmwareUpdate"},
- {1007, nullptr, "GetFirmwareUpdateState"},
- {1008, nullptr, "ActivateAudioControl"},
- {1009, nullptr, "AcquireAudioControlEventHandle"},
- {1010, nullptr, "GetAudioControlStates"},
- {1011, nullptr, "DeactivateAudioControl"},
- {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
- {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
- {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
- {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
- {1100, nullptr, "GetHidbusSystemServiceObject"},
- {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
- {1130, nullptr, "InitializeUsbFirmwareUpdate"},
- {1131, nullptr, "FinalizeUsbFirmwareUpdate"},
- {1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
- {1133, nullptr, "StartUsbFirmwareUpdate"},
- {1134, nullptr, "GetUsbFirmwareUpdateState"},
- {1150, nullptr, "SetTouchScreenMagnification"},
- {1151, nullptr, "GetTouchScreenFirmwareVersion"},
- {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
- {1153, &HidSys::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
- {1154, nullptr, "IsFirmwareAvailableForNotification"},
- {1155, nullptr, "SetForceHandheldStyleVibration"},
- {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
- {1157, nullptr, "CancelConnectionTrigger"},
- {1200, nullptr, "IsButtonConfigSupported"},
- {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
- {1202, nullptr, "DeleteButtonConfig"},
- {1203, nullptr, "DeleteButtonConfigEmbedded"},
- {1204, nullptr, "SetButtonConfigEnabled"},
- {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
- {1206, nullptr, "IsButtonConfigEnabled"},
- {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
- {1208, nullptr, "SetButtonConfigEmbedded"},
- {1209, nullptr, "SetButtonConfigFull"},
- {1210, nullptr, "SetButtonConfigLeft"},
- {1211, nullptr, "SetButtonConfigRight"},
- {1212, nullptr, "GetButtonConfigEmbedded"},
- {1213, nullptr, "GetButtonConfigFull"},
- {1214, nullptr, "GetButtonConfigLeft"},
- {1215, nullptr, "GetButtonConfigRight"},
- {1250, nullptr, "IsCustomButtonConfigSupported"},
- {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
- {1252, nullptr, "IsDefaultButtonConfigFull"},
- {1253, nullptr, "IsDefaultButtonConfigLeft"},
- {1254, nullptr, "IsDefaultButtonConfigRight"},
- {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
- {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
- {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
- {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
- {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
- {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
- {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
- {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
- {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
- {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
- {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
- {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
- {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
- {1268, nullptr, "DeleteButtonConfigStorageFull"},
- {1269, nullptr, "DeleteButtonConfigStorageLeft"},
- {1270, nullptr, "DeleteButtonConfigStorageRight"},
- {1271, nullptr, "IsUsingCustomButtonConfig"},
- {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
- {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
- {1274, nullptr, "SetDefaultButtonConfig"},
- {1275, nullptr, "SetAllDefaultButtonConfig"},
- {1276, nullptr, "SetHidButtonConfigEmbedded"},
- {1277, nullptr, "SetHidButtonConfigFull"},
- {1278, nullptr, "SetHidButtonConfigLeft"},
- {1279, nullptr, "SetHidButtonConfigRight"},
- {1280, nullptr, "GetHidButtonConfigEmbedded"},
- {1281, nullptr, "GetHidButtonConfigFull"},
- {1282, nullptr, "GetHidButtonConfigLeft"},
- {1283, nullptr, "GetHidButtonConfigRight"},
- {1284, nullptr, "GetButtonConfigStorageEmbedded"},
- {1285, nullptr, "GetButtonConfigStorageFull"},
- {1286, nullptr, "GetButtonConfigStorageLeft"},
- {1287, nullptr, "GetButtonConfigStorageRight"},
- {1288, nullptr, "SetButtonConfigStorageEmbedded"},
- {1289, nullptr, "SetButtonConfigStorageFull"},
- {1290, nullptr, "DeleteButtonConfigStorageRight"},
- {1291, nullptr, "DeleteButtonConfigStorageRight"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-
- joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
- }
-
-private:
- void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "called");
-
- GetAppletResource()
- ->GetController<Controller_NPad>(HidController::NPad)
- .ApplyNpadSystemCommonPolicy();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetLastActiveNpad(HLERequestContext& ctx) {
- LOG_DEBUG(Service_HID, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(system.HIDCore().GetLastActiveController());
- }
-
- void GetUniquePadsFromNpad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
-
- LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
-
- const std::vector<Core::HID::UniquePadId> unique_pads{};
-
- ctx.WriteBuffer(unique_pads);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u32>(unique_pads.size()));
- }
-
- void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
- LOG_INFO(Service_AM, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
- }
-
- void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
- const bool is_enabled = false;
-
- LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(is_enabled);
- }
-
- void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
-
- Core::HID::TouchScreenConfigurationForNx touchscreen_config{
- .mode = Core::HID::TouchScreenModeForNx::Finger,
- };
-
- if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
- touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
- touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
- }
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(touchscreen_config);
- }
-
- std::shared_ptr<IAppletResource> GetAppletResource() {
- if (applet_resource == nullptr) {
- applet_resource = std::make_shared<IAppletResource>(system, service_context);
- }
-
- return applet_resource;
- }
-
- Kernel::KEvent* joy_detach_event;
- KernelHelpers::ServiceContext service_context;
- std::shared_ptr<IAppletResource> applet_resource;
-};
-
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- std::shared_ptr<IAppletResource> applet_resource;
+ std::shared_ptr<ResourceManager> resouce_manager = std::make_shared<ResourceManager>(system);
+ std::shared_ptr<HidFirmwareSettings> firmware_settings =
+ std::make_shared<HidFirmwareSettings>();
+
+ server_manager->RegisterNamedService(
+ "hid", std::make_shared<IHidServer>(system, resouce_manager, firmware_settings));
+ server_manager->RegisterNamedService(
+ "hid:dbg", std::make_shared<IHidDebugServer>(system, resouce_manager));
+ server_manager->RegisterNamedService(
+ "hid:sys", std::make_shared<IHidSystemServer>(system, resouce_manager));
- server_manager->RegisterNamedService("hid", std::make_shared<Hid>(system, applet_resource));
server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system));
- server_manager->RegisterNamedService("hid:dbg", std::make_shared<HidDbg>(system));
- server_manager->RegisterNamedService("hid:sys",
- std::make_shared<HidSys>(system, applet_resource));
- server_manager->RegisterNamedService("irs", std::make_shared<Service::IRS::IRS>(system));
- server_manager->RegisterNamedService("irs:sys",
- std::make_shared<Service::IRS::IRS_SYS>(system));
+ server_manager->RegisterNamedService("irs", std::make_shared<IRS::IRS>(system));
+ server_manager->RegisterNamedService("irs:sys", std::make_shared<IRS::IRS_SYS>(system));
server_manager->RegisterNamedService("xcd:sys", std::make_shared<XCD_SYS>(system));
+
system.RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 0ca43de93..ec5463f4e 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -3,220 +3,12 @@
#pragma once
-#include <chrono>
-
-#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Core::Timing {
-struct EventType;
-}
-
-namespace Service::SM {
-class ServiceManager;
+namespace Core {
+class System;
}
namespace Service::HID {
-enum class HidController : std::size_t {
- DebugPad,
- Touchscreen,
- Mouse,
- Keyboard,
- XPad,
- HomeButton,
- SleepButton,
- CaptureButton,
- InputDetector,
- UniquePad,
- NPad,
- Gesture,
- ConsoleSixAxisSensor,
- DebugMouse,
- Palma,
-
- MaxControllers,
-};
-
-class IAppletResource final : public ServiceFramework<IAppletResource> {
-public:
- explicit IAppletResource(Core::System& system_,
- KernelHelpers::ServiceContext& service_context_);
- ~IAppletResource() override;
-
- void ActivateController(HidController controller);
- void DeactivateController(HidController controller);
-
- template <typename T>
- T& GetController(HidController controller) {
- return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
- }
-
- template <typename T>
- const T& GetController(HidController controller) const {
- return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
- }
-
-private:
- template <typename T>
- void MakeController(HidController controller, u8* shared_memory) {
- if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
- controllers[static_cast<std::size_t>(controller)] =
- std::make_unique<T>(system, shared_memory);
- } else {
- controllers[static_cast<std::size_t>(controller)] =
- std::make_unique<T>(system.HIDCore(), shared_memory);
- }
- }
-
- template <typename T>
- void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
- controllers[static_cast<std::size_t>(controller)] =
- std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
- }
-
- void GetSharedMemoryHandle(HLERequestContext& ctx);
- void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
- void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
- void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
- void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
-
- KernelHelpers::ServiceContext& service_context;
-
- std::shared_ptr<Core::Timing::EventType> npad_update_event;
- std::shared_ptr<Core::Timing::EventType> default_update_event;
- std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
- std::shared_ptr<Core::Timing::EventType> motion_update_event;
-
- std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
- controllers{};
-};
-
-class Hid final : public ServiceFramework<Hid> {
-public:
- explicit Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_);
- ~Hid() override;
-
- std::shared_ptr<IAppletResource> GetAppletResource();
-
-private:
- void CreateAppletResource(HLERequestContext& ctx);
- void ActivateDebugPad(HLERequestContext& ctx);
- void ActivateTouchScreen(HLERequestContext& ctx);
- void ActivateMouse(HLERequestContext& ctx);
- void ActivateKeyboard(HLERequestContext& ctx);
- void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
- void ActivateXpad(HLERequestContext& ctx);
- void GetXpadIDs(HLERequestContext& ctx);
- void ActivateSixAxisSensor(HLERequestContext& ctx);
- void DeactivateSixAxisSensor(HLERequestContext& ctx);
- void StartSixAxisSensor(HLERequestContext& ctx);
- void StopSixAxisSensor(HLERequestContext& ctx);
- void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
- void EnableSixAxisSensorFusion(HLERequestContext& ctx);
- void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
- void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
- void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
- void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
- void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
- void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
- void IsSixAxisSensorAtRest(HLERequestContext& ctx);
- void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
- void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
- void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
- void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
- void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
- void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
- void ActivateGesture(HLERequestContext& ctx);
- void SetSupportedNpadStyleSet(HLERequestContext& ctx);
- void GetSupportedNpadStyleSet(HLERequestContext& ctx);
- void SetSupportedNpadIdType(HLERequestContext& ctx);
- void ActivateNpad(HLERequestContext& ctx);
- void DeactivateNpad(HLERequestContext& ctx);
- void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
- void DisconnectNpad(HLERequestContext& ctx);
- void GetPlayerLedPattern(HLERequestContext& ctx);
- void ActivateNpadWithRevision(HLERequestContext& ctx);
- void SetNpadJoyHoldType(HLERequestContext& ctx);
- void GetNpadJoyHoldType(HLERequestContext& ctx);
- void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
- void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
- void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
- void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
- void StartLrAssignmentMode(HLERequestContext& ctx);
- void StopLrAssignmentMode(HLERequestContext& ctx);
- void SetNpadHandheldActivationMode(HLERequestContext& ctx);
- void GetNpadHandheldActivationMode(HLERequestContext& ctx);
- void SwapNpadAssignment(HLERequestContext& ctx);
- void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
- void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
- void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
- void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
- void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
- void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
- void GetVibrationDeviceInfo(HLERequestContext& ctx);
- void SendVibrationValue(HLERequestContext& ctx);
- void GetActualVibrationValue(HLERequestContext& ctx);
- void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
- void PermitVibration(HLERequestContext& ctx);
- void IsVibrationPermitted(HLERequestContext& ctx);
- void SendVibrationValues(HLERequestContext& ctx);
- void SendVibrationGcErmCommand(HLERequestContext& ctx);
- void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
- void BeginPermitVibrationSession(HLERequestContext& ctx);
- void EndPermitVibrationSession(HLERequestContext& ctx);
- void IsVibrationDeviceMounted(HLERequestContext& ctx);
- void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
- void StartConsoleSixAxisSensor(HLERequestContext& ctx);
- void StopConsoleSixAxisSensor(HLERequestContext& ctx);
- void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
- void StartSevenSixAxisSensor(HLERequestContext& ctx);
- void StopSevenSixAxisSensor(HLERequestContext& ctx);
- void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
- void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
- void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
- void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
- void GetPalmaConnectionHandle(HLERequestContext& ctx);
- void InitializePalma(HLERequestContext& ctx);
- void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
- void GetPalmaOperationInfo(HLERequestContext& ctx);
- void PlayPalmaActivity(HLERequestContext& ctx);
- void SetPalmaFrModeType(HLERequestContext& ctx);
- void ReadPalmaStep(HLERequestContext& ctx);
- void EnablePalmaStep(HLERequestContext& ctx);
- void ResetPalmaStep(HLERequestContext& ctx);
- void ReadPalmaApplicationSection(HLERequestContext& ctx);
- void WritePalmaApplicationSection(HLERequestContext& ctx);
- void ReadPalmaUniqueCode(HLERequestContext& ctx);
- void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
- void WritePalmaActivityEntry(HLERequestContext& ctx);
- void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
- void WritePalmaWaveEntry(HLERequestContext& ctx);
- void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
- void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
- void SuspendPalmaFeature(HLERequestContext& ctx);
- void GetPalmaOperationResult(HLERequestContext& ctx);
- void ReadPalmaPlayLog(HLERequestContext& ctx);
- void ResetPalmaPlayLog(HLERequestContext& ctx);
- void SetIsPalmaAllConnectable(HLERequestContext& ctx);
- void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
- void PairPalma(HLERequestContext& ctx);
- void SetPalmaBoostMode(HLERequestContext& ctx);
- void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
- void EnablePalmaBoostMode(HLERequestContext& ctx);
- void GetPalmaBluetoothAddress(HLERequestContext& ctx);
- void SetDisallowedPalmaConnection(HLERequestContext& ctx);
- void SetNpadCommunicationMode(HLERequestContext& ctx);
- void GetNpadCommunicationMode(HLERequestContext& ctx);
- void SetTouchScreenConfiguration(HLERequestContext& ctx);
- void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
-
- std::shared_ptr<IAppletResource> applet_resource;
-
- KernelHelpers::ServiceContext service_context;
-};
-
void LoopProcess(Core::System& system);
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_debug_server.cpp b/src/core/hle/service/hid/hid_debug_server.cpp
new file mode 100644
index 000000000..6294f3dfb
--- /dev/null
+++ b/src/core/hle/service/hid/hid_debug_server.cpp
@@ -0,0 +1,159 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/hid/hid_debug_server.h"
+#include "core/hle/service/hid/resource_manager.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::HID {
+
+IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
+ : ServiceFramework{system_, "hid:dbg"}, resource_manager{resource} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "DeactivateDebugPad"},
+ {1, nullptr, "SetDebugPadAutoPilotState"},
+ {2, nullptr, "UnsetDebugPadAutoPilotState"},
+ {10, nullptr, "DeactivateTouchScreen"},
+ {11, nullptr, "SetTouchScreenAutoPilotState"},
+ {12, nullptr, "UnsetTouchScreenAutoPilotState"},
+ {13, nullptr, "GetTouchScreenConfiguration"},
+ {14, nullptr, "ProcessTouchScreenAutoTune"},
+ {15, nullptr, "ForceStopTouchScreenManagement"},
+ {16, nullptr, "ForceRestartTouchScreenManagement"},
+ {17, nullptr, "IsTouchScreenManaged"},
+ {20, nullptr, "DeactivateMouse"},
+ {21, nullptr, "SetMouseAutoPilotState"},
+ {22, nullptr, "UnsetMouseAutoPilotState"},
+ {25, nullptr, "SetDebugMouseAutoPilotState"},
+ {26, nullptr, "UnsetDebugMouseAutoPilotState"},
+ {30, nullptr, "DeactivateKeyboard"},
+ {31, nullptr, "SetKeyboardAutoPilotState"},
+ {32, nullptr, "UnsetKeyboardAutoPilotState"},
+ {50, nullptr, "DeactivateXpad"},
+ {51, nullptr, "SetXpadAutoPilotState"},
+ {52, nullptr, "UnsetXpadAutoPilotState"},
+ {53, nullptr, "DeactivateJoyXpad"},
+ {60, nullptr, "ClearNpadSystemCommonPolicy"},
+ {61, nullptr, "DeactivateNpad"},
+ {62, nullptr, "ForceDisconnectNpad"},
+ {91, nullptr, "DeactivateGesture"},
+ {110, nullptr, "DeactivateHomeButton"},
+ {111, nullptr, "SetHomeButtonAutoPilotState"},
+ {112, nullptr, "UnsetHomeButtonAutoPilotState"},
+ {120, nullptr, "DeactivateSleepButton"},
+ {121, nullptr, "SetSleepButtonAutoPilotState"},
+ {122, nullptr, "UnsetSleepButtonAutoPilotState"},
+ {123, nullptr, "DeactivateInputDetector"},
+ {130, nullptr, "DeactivateCaptureButton"},
+ {131, nullptr, "SetCaptureButtonAutoPilotState"},
+ {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
+ {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
+ {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
+ {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
+ {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
+ {140, nullptr, "DeactivateConsoleSixAxisSensor"},
+ {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
+ {142, nullptr, "DeactivateSevenSixAxisSensor"},
+ {143, nullptr, "GetConsoleSixAxisSensorCountStates"},
+ {144, nullptr, "GetAccelerometerFsr"},
+ {145, nullptr, "SetAccelerometerFsr"},
+ {146, nullptr, "GetAccelerometerOdr"},
+ {147, nullptr, "SetAccelerometerOdr"},
+ {148, nullptr, "GetGyroscopeFsr"},
+ {149, nullptr, "SetGyroscopeFsr"},
+ {150, nullptr, "GetGyroscopeOdr"},
+ {151, nullptr, "SetGyroscopeOdr"},
+ {152, nullptr, "GetWhoAmI"},
+ {201, nullptr, "ActivateFirmwareUpdate"},
+ {202, nullptr, "DeactivateFirmwareUpdate"},
+ {203, nullptr, "StartFirmwareUpdate"},
+ {204, nullptr, "GetFirmwareUpdateStage"},
+ {205, nullptr, "GetFirmwareVersion"},
+ {206, nullptr, "GetDestinationFirmwareVersion"},
+ {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
+ {208, nullptr, "StartFirmwareUpdateForRevert"},
+ {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
+ {210, nullptr, "IsFirmwareUpdatingDevice"},
+ {211, nullptr, "StartFirmwareUpdateIndividual"},
+ {215, nullptr, "SetUsbFirmwareForceUpdateEnabled"},
+ {216, nullptr, "SetAllKuinaDevicesToFirmwareUpdateMode"},
+ {221, nullptr, "UpdateControllerColor"},
+ {222, nullptr, "ConnectUsbPadsAsync"},
+ {223, nullptr, "DisconnectUsbPadsAsync"},
+ {224, nullptr, "UpdateDesignInfo"},
+ {225, nullptr, "GetUniquePadDriverState"},
+ {226, nullptr, "GetSixAxisSensorDriverStates"},
+ {227, nullptr, "GetRxPacketHistory"},
+ {228, nullptr, "AcquireOperationEventHandle"},
+ {229, nullptr, "ReadSerialFlash"},
+ {230, nullptr, "WriteSerialFlash"},
+ {231, nullptr, "GetOperationResult"},
+ {232, nullptr, "EnableShipmentMode"},
+ {233, nullptr, "ClearPairingInfo"},
+ {234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
+ {235, nullptr, "EnableAnalogStickPower"},
+ {236, nullptr, "RequestKuinaUartClockCal"},
+ {237, nullptr, "GetKuinaUartClockCal"},
+ {238, nullptr, "SetKuinaUartClockTrim"},
+ {239, nullptr, "KuinaLoopbackTest"},
+ {240, nullptr, "RequestBatteryVoltage"},
+ {241, nullptr, "GetBatteryVoltage"},
+ {242, nullptr, "GetUniquePadPowerInfo"},
+ {243, nullptr, "RebootUniquePad"},
+ {244, nullptr, "RequestKuinaFirmwareVersion"},
+ {245, nullptr, "GetKuinaFirmwareVersion"},
+ {246, nullptr, "GetVidPid"},
+ {247, nullptr, "GetAnalogStickCalibrationValue"},
+ {248, nullptr, "GetUniquePadIdsFull"},
+ {249, nullptr, "ConnectUniquePad"},
+ {250, nullptr, "IsVirtual"},
+ {251, nullptr, "GetAnalogStickModuleParam"},
+ {301, nullptr, "GetAbstractedPadHandles"},
+ {302, nullptr, "GetAbstractedPadState"},
+ {303, nullptr, "GetAbstractedPadsState"},
+ {321, nullptr, "SetAutoPilotVirtualPadState"},
+ {322, nullptr, "UnsetAutoPilotVirtualPadState"},
+ {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
+ {324, nullptr, "AttachHdlsWorkBuffer"},
+ {325, nullptr, "ReleaseHdlsWorkBuffer"},
+ {326, nullptr, "DumpHdlsNpadAssignmentState"},
+ {327, nullptr, "DumpHdlsStates"},
+ {328, nullptr, "ApplyHdlsNpadAssignmentState"},
+ {329, nullptr, "ApplyHdlsStateList"},
+ {330, nullptr, "AttachHdlsVirtualDevice"},
+ {331, nullptr, "DetachHdlsVirtualDevice"},
+ {332, nullptr, "SetHdlsState"},
+ {350, nullptr, "AddRegisteredDevice"},
+ {400, nullptr, "DisableExternalMcuOnNxDevice"},
+ {401, nullptr, "DisableRailDeviceFiltering"},
+ {402, nullptr, "EnableWiredPairing"},
+ {403, nullptr, "EnableShipmentModeAutoClear"},
+ {404, nullptr, "SetRailEnabled"},
+ {500, nullptr, "SetFactoryInt"},
+ {501, nullptr, "IsFactoryBootEnabled"},
+ {550, nullptr, "SetAnalogStickModelDataTemporarily"},
+ {551, nullptr, "GetAnalogStickModelData"},
+ {552, nullptr, "ResetAnalogStickModelData"},
+ {600, nullptr, "ConvertPadState"},
+ {650, nullptr, "AddButtonPlayData"},
+ {651, nullptr, "StartButtonPlayData"},
+ {652, nullptr, "StopButtonPlayData"},
+ {2000, nullptr, "DeactivateDigitizer"},
+ {2001, nullptr, "SetDigitizerAutoPilotState"},
+ {2002, nullptr, "UnsetDigitizerAutoPilotState"},
+ {2002, nullptr, "ReloadFirmwareDebugSettings"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IHidDebugServer::~IHidDebugServer() = default;
+
+std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() {
+ resource_manager->Initialize();
+ return resource_manager;
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_debug_server.h b/src/core/hle/service/hid/hid_debug_server.h
new file mode 100644
index 000000000..406db2211
--- /dev/null
+++ b/src/core/hle/service/hid/hid_debug_server.h
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::HID {
+class ResourceManager;
+
+class IHidDebugServer final : public ServiceFramework<IHidDebugServer> {
+public:
+ explicit IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
+ ~IHidDebugServer() override;
+
+private:
+ std::shared_ptr<ResourceManager> GetResourceManager();
+
+ std::shared_ptr<ResourceManager> resource_manager;
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_firmware_settings.cpp b/src/core/hle/service/hid/hid_firmware_settings.cpp
new file mode 100644
index 000000000..59bd6825c
--- /dev/null
+++ b/src/core/hle/service/hid/hid_firmware_settings.cpp
@@ -0,0 +1,99 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hle/service/hid/hid_firmware_settings.h"
+
+namespace Service::HID {
+
+HidFirmwareSettings::HidFirmwareSettings() {
+ LoadSettings(true);
+}
+
+void HidFirmwareSettings::Reload() {
+ LoadSettings(true);
+}
+
+void HidFirmwareSettings::LoadSettings(bool reload_config) {
+ if (is_initalized && !reload_config) {
+ return;
+ }
+
+ // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values
+
+ is_debug_pad_enabled = true;
+ is_device_managed = true;
+ is_touch_i2c_managed = is_device_managed;
+ is_future_devices_emulated = false;
+ is_mcu_hardware_error_emulated = false;
+ is_rail_enabled = true;
+ is_firmware_update_failure_emulated = false;
+ is_firmware_update_failure = {};
+ is_ble_disabled = false;
+ is_dscale_disabled = false;
+ is_handheld_forced = true;
+ features_per_id_disabled = {};
+ is_touch_firmware_auto_update_disabled = false;
+ is_initalized = true;
+}
+
+bool HidFirmwareSettings::IsDebugPadEnabled() {
+ LoadSettings(false);
+ return is_debug_pad_enabled;
+}
+
+bool HidFirmwareSettings::IsDeviceManaged() {
+ LoadSettings(false);
+ return is_device_managed;
+}
+
+bool HidFirmwareSettings::IsEmulateFutureDevice() {
+ LoadSettings(false);
+ return is_future_devices_emulated;
+}
+
+bool HidFirmwareSettings::IsTouchI2cManaged() {
+ LoadSettings(false);
+ return is_touch_i2c_managed;
+}
+
+bool HidFirmwareSettings::IsHandheldForced() {
+ LoadSettings(false);
+ return is_handheld_forced;
+}
+
+bool HidFirmwareSettings::IsRailEnabled() {
+ LoadSettings(false);
+ return is_rail_enabled;
+}
+
+bool HidFirmwareSettings::IsHardwareErrorEmulated() {
+ LoadSettings(false);
+ return is_mcu_hardware_error_emulated;
+}
+
+bool HidFirmwareSettings::IsBleDisabled() {
+ LoadSettings(false);
+ return is_ble_disabled;
+}
+
+bool HidFirmwareSettings::IsDscaleDisabled() {
+ LoadSettings(false);
+ return is_dscale_disabled;
+}
+
+bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() {
+ LoadSettings(false);
+ return is_touch_firmware_auto_update_disabled;
+}
+
+HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() {
+ LoadSettings(false);
+ return is_firmware_update_failure;
+}
+
+HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() {
+ LoadSettings(false);
+ return features_per_id_disabled;
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_firmware_settings.h b/src/core/hle/service/hid/hid_firmware_settings.h
new file mode 100644
index 000000000..6c10c440b
--- /dev/null
+++ b/src/core/hle/service/hid/hid_firmware_settings.h
@@ -0,0 +1,54 @@
+// 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 {
+
+/// Loads firmware config from nn::settings::fwdbg
+class HidFirmwareSettings {
+public:
+ using FirmwareSetting = std::array<u8, 4>;
+ using FeaturesPerId = std::array<bool, 0xA8>;
+
+ HidFirmwareSettings();
+
+ void Reload();
+ void LoadSettings(bool reload_config);
+
+ bool IsDebugPadEnabled();
+ bool IsDeviceManaged();
+ bool IsEmulateFutureDevice();
+ bool IsTouchI2cManaged();
+ bool IsHandheldForced();
+ bool IsRailEnabled();
+ bool IsHardwareErrorEmulated();
+ bool IsBleDisabled();
+ bool IsDscaleDisabled();
+ bool IsTouchAutoUpdateDisabled();
+
+ FirmwareSetting GetFirmwareUpdateFailure();
+ FeaturesPerId FeaturesDisabledPerId();
+
+private:
+ bool is_initalized{};
+
+ // Debug settings
+ bool is_debug_pad_enabled{};
+ bool is_device_managed{};
+ bool is_touch_i2c_managed{};
+ bool is_future_devices_emulated{};
+ bool is_mcu_hardware_error_emulated{};
+ bool is_rail_enabled{};
+ bool is_firmware_update_failure_emulated{};
+ bool is_ble_disabled{};
+ bool is_dscale_disabled{};
+ bool is_handheld_forced{};
+ bool is_touch_firmware_auto_update_disabled{};
+ FirmwareSetting is_firmware_update_failure{};
+ FeaturesPerId features_per_id_disabled{};
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp
new file mode 100644
index 000000000..0be6a7186
--- /dev/null
+++ b/src/core/hle/service/hid/hid_server.cpp
@@ -0,0 +1,2440 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include <array>
+#include "common/common_types.h"
+#include "common/logging/log.h"
+#include "common/settings.h"
+#include "core/hid/hid_core.h"
+#include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/hid/errors.h"
+#include "core/hle/service/hid/hid_firmware_settings.h"
+#include "core/hle/service/hid/hid_server.h"
+#include "core/hle/service/hid/resource_manager.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/memory.h"
+
+#include "core/hle/service/hid/controllers/console_sixaxis.h"
+#include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/controllers/debug_pad.h"
+#include "core/hle/service/hid/controllers/gesture.h"
+#include "core/hle/service/hid/controllers/keyboard.h"
+#include "core/hle/service/hid/controllers/mouse.h"
+#include "core/hle/service/hid/controllers/npad.h"
+#include "core/hle/service/hid/controllers/palma.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 {
+
+class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
+public:
+ explicit IActiveVibrationDeviceList(Core::System& system_,
+ std::shared_ptr<ResourceManager> resource)
+ : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void InitializeVibrationDevice(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
+
+ if (resource_manager != nullptr) {
+ resource_manager->GetController<Controller_NPad>(HidController::NPad)
+ .InitializeVibrationDevice(vibration_device_handle);
+ }
+
+ LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}",
+ vibration_device_handle.npad_type, vibration_device_handle.npad_id,
+ vibration_device_handle.device_index);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+ }
+
+ std::shared_ptr<ResourceManager> resource_manager;
+};
+
+IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource,
+ std::shared_ptr<HidFirmwareSettings> settings)
+ : ServiceFramework{system_, "hid"}, resource_manager{resource}, firmware_settings{settings} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &IHidServer::CreateAppletResource, "CreateAppletResource"},
+ {1, &IHidServer::ActivateDebugPad, "ActivateDebugPad"},
+ {11, &IHidServer::ActivateTouchScreen, "ActivateTouchScreen"},
+ {21, &IHidServer::ActivateMouse, "ActivateMouse"},
+ {26, nullptr, "ActivateDebugMouse"},
+ {31, &IHidServer::ActivateKeyboard, "ActivateKeyboard"},
+ {32, &IHidServer::SendKeyboardLockKeyEvent, "SendKeyboardLockKeyEvent"},
+ {40, &IHidServer::AcquireXpadIdEventHandle, "AcquireXpadIdEventHandle"},
+ {41, &IHidServer::ReleaseXpadIdEventHandle, "ReleaseXpadIdEventHandle"},
+ {51, &IHidServer::ActivateXpad, "ActivateXpad"},
+ {55, &IHidServer::GetXpadIds, "GetXpadIds"},
+ {56, &IHidServer::ActivateJoyXpad, "ActivateJoyXpad"},
+ {58, &IHidServer::GetJoyXpadLifoHandle, "GetJoyXpadLifoHandle"},
+ {59, &IHidServer::GetJoyXpadIds, "GetJoyXpadIds"},
+ {60, &IHidServer::ActivateSixAxisSensor, "ActivateSixAxisSensor"},
+ {61, &IHidServer::DeactivateSixAxisSensor, "DeactivateSixAxisSensor"},
+ {62, &IHidServer::GetSixAxisSensorLifoHandle, "GetSixAxisSensorLifoHandle"},
+ {63, &IHidServer::ActivateJoySixAxisSensor, "ActivateJoySixAxisSensor"},
+ {64, &IHidServer::DeactivateJoySixAxisSensor, "DeactivateJoySixAxisSensor"},
+ {65, &IHidServer::GetJoySixAxisSensorLifoHandle, "GetJoySixAxisSensorLifoHandle"},
+ {66, &IHidServer::StartSixAxisSensor, "StartSixAxisSensor"},
+ {67, &IHidServer::StopSixAxisSensor, "StopSixAxisSensor"},
+ {68, &IHidServer::IsSixAxisSensorFusionEnabled, "IsSixAxisSensorFusionEnabled"},
+ {69, &IHidServer::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
+ {70, &IHidServer::SetSixAxisSensorFusionParameters, "SetSixAxisSensorFusionParameters"},
+ {71, &IHidServer::GetSixAxisSensorFusionParameters, "GetSixAxisSensorFusionParameters"},
+ {72, &IHidServer::ResetSixAxisSensorFusionParameters, "ResetSixAxisSensorFusionParameters"},
+ {73, nullptr, "SetAccelerometerParameters"},
+ {74, nullptr, "GetAccelerometerParameters"},
+ {75, nullptr, "ResetAccelerometerParameters"},
+ {76, nullptr, "SetAccelerometerPlayMode"},
+ {77, nullptr, "GetAccelerometerPlayMode"},
+ {78, nullptr, "ResetAccelerometerPlayMode"},
+ {79, &IHidServer::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
+ {80, &IHidServer::GetGyroscopeZeroDriftMode, "GetGyroscopeZeroDriftMode"},
+ {81, &IHidServer::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
+ {82, &IHidServer::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
+ {83, &IHidServer::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
+ {84, &IHidServer::EnableSixAxisSensorUnalteredPassthrough, "EnableSixAxisSensorUnalteredPassthrough"},
+ {85, &IHidServer::IsSixAxisSensorUnalteredPassthroughEnabled, "IsSixAxisSensorUnalteredPassthroughEnabled"},
+ {86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
+ {87, &IHidServer::LoadSixAxisSensorCalibrationParameter, "LoadSixAxisSensorCalibrationParameter"},
+ {88, &IHidServer::GetSixAxisSensorIcInformation, "GetSixAxisSensorIcInformation"},
+ {89, &IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
+ {91, &IHidServer::ActivateGesture, "ActivateGesture"},
+ {100, &IHidServer::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
+ {101, &IHidServer::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
+ {102, &IHidServer::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
+ {103, &IHidServer::ActivateNpad, "ActivateNpad"},
+ {104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
+ {106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
+ {107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
+ {108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"},
+ {109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
+ {120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
+ {121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
+ {122, &IHidServer::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
+ {123, &IHidServer::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"},
+ {124, &IHidServer::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
+ {125, &IHidServer::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
+ {126, &IHidServer::StartLrAssignmentMode, "StartLrAssignmentMode"},
+ {127, &IHidServer::StopLrAssignmentMode, "StopLrAssignmentMode"},
+ {128, &IHidServer::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
+ {129, &IHidServer::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
+ {130, &IHidServer::SwapNpadAssignment, "SwapNpadAssignment"},
+ {131, &IHidServer::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
+ {132, &IHidServer::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
+ {133, &IHidServer::SetNpadJoyAssignmentModeSingleWithDestination, "SetNpadJoyAssignmentModeSingleWithDestination"},
+ {134, &IHidServer::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
+ {135, &IHidServer::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"},
+ {136, &IHidServer::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"},
+ {200, &IHidServer::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
+ {201, &IHidServer::SendVibrationValue, "SendVibrationValue"},
+ {202, &IHidServer::GetActualVibrationValue, "GetActualVibrationValue"},
+ {203, &IHidServer::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
+ {204, &IHidServer::PermitVibration, "PermitVibration"},
+ {205, &IHidServer::IsVibrationPermitted, "IsVibrationPermitted"},
+ {206, &IHidServer::SendVibrationValues, "SendVibrationValues"},
+ {207, &IHidServer::SendVibrationGcErmCommand, "SendVibrationGcErmCommand"},
+ {208, &IHidServer::GetActualVibrationGcErmCommand, "GetActualVibrationGcErmCommand"},
+ {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
+ {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"},
+ {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
+ {212, nullptr, "SendVibrationValueInBool"},
+ {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
+ {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
+ {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"},
+ {303, &IHidServer::ActivateSevenSixAxisSensor, "ActivateSevenSixAxisSensor"},
+ {304, &IHidServer::StartSevenSixAxisSensor, "StartSevenSixAxisSensor"},
+ {305, &IHidServer::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"},
+ {306, &IHidServer::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
+ {307, &IHidServer::FinalizeSevenSixAxisSensor, "FinalizeSevenSixAxisSensor"},
+ {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
+ {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
+ {310, &IHidServer::ResetSevenSixAxisSensorTimestamp, "ResetSevenSixAxisSensorTimestamp"},
+ {400, &IHidServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
+ {401, nullptr, "EnableUsbFullKeyController"},
+ {402, nullptr, "IsUsbFullKeyControllerConnected"},
+ {403, nullptr, "HasBattery"},
+ {404, nullptr, "HasLeftRightBattery"},
+ {405, nullptr, "GetNpadInterfaceType"},
+ {406, nullptr, "GetNpadLeftRightInterfaceType"},
+ {407, nullptr, "GetNpadOfHighestBatteryLevel"},
+ {408, nullptr, "GetNpadOfHighestBatteryLevelForJoyRight"},
+ {500, &IHidServer::GetPalmaConnectionHandle, "GetPalmaConnectionHandle"},
+ {501, &IHidServer::InitializePalma, "InitializePalma"},
+ {502, &IHidServer::AcquirePalmaOperationCompleteEvent, "AcquirePalmaOperationCompleteEvent"},
+ {503, &IHidServer::GetPalmaOperationInfo, "GetPalmaOperationInfo"},
+ {504, &IHidServer::PlayPalmaActivity, "PlayPalmaActivity"},
+ {505, &IHidServer::SetPalmaFrModeType, "SetPalmaFrModeType"},
+ {506, &IHidServer::ReadPalmaStep, "ReadPalmaStep"},
+ {507, &IHidServer::EnablePalmaStep, "EnablePalmaStep"},
+ {508, &IHidServer::ResetPalmaStep, "ResetPalmaStep"},
+ {509, &IHidServer::ReadPalmaApplicationSection, "ReadPalmaApplicationSection"},
+ {510, &IHidServer::WritePalmaApplicationSection, "WritePalmaApplicationSection"},
+ {511, &IHidServer::ReadPalmaUniqueCode, "ReadPalmaUniqueCode"},
+ {512, &IHidServer::SetPalmaUniqueCodeInvalid, "SetPalmaUniqueCodeInvalid"},
+ {513, &IHidServer::WritePalmaActivityEntry, "WritePalmaActivityEntry"},
+ {514, &IHidServer::WritePalmaRgbLedPatternEntry, "WritePalmaRgbLedPatternEntry"},
+ {515, &IHidServer::WritePalmaWaveEntry, "WritePalmaWaveEntry"},
+ {516, &IHidServer::SetPalmaDataBaseIdentificationVersion, "SetPalmaDataBaseIdentificationVersion"},
+ {517, &IHidServer::GetPalmaDataBaseIdentificationVersion, "GetPalmaDataBaseIdentificationVersion"},
+ {518, &IHidServer::SuspendPalmaFeature, "SuspendPalmaFeature"},
+ {519, &IHidServer::GetPalmaOperationResult, "GetPalmaOperationResult"},
+ {520, &IHidServer::ReadPalmaPlayLog, "ReadPalmaPlayLog"},
+ {521, &IHidServer::ResetPalmaPlayLog, "ResetPalmaPlayLog"},
+ {522, &IHidServer::SetIsPalmaAllConnectable, "SetIsPalmaAllConnectable"},
+ {523, &IHidServer::SetIsPalmaPairedConnectable, "SetIsPalmaPairedConnectable"},
+ {524, &IHidServer::PairPalma, "PairPalma"},
+ {525, &IHidServer::SetPalmaBoostMode, "SetPalmaBoostMode"},
+ {526, &IHidServer::CancelWritePalmaWaveEntry, "CancelWritePalmaWaveEntry"},
+ {527, &IHidServer::EnablePalmaBoostMode, "EnablePalmaBoostMode"},
+ {528, &IHidServer::GetPalmaBluetoothAddress, "GetPalmaBluetoothAddress"},
+ {529, &IHidServer::SetDisallowedPalmaConnection, "SetDisallowedPalmaConnection"},
+ {1000, &IHidServer::SetNpadCommunicationMode, "SetNpadCommunicationMode"},
+ {1001, &IHidServer::GetNpadCommunicationMode, "GetNpadCommunicationMode"},
+ {1002, &IHidServer::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"},
+ {1003, &IHidServer::IsFirmwareUpdateNeededForNotification, "IsFirmwareUpdateNeededForNotification"},
+ {2000, nullptr, "ActivateDigitizer"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IHidServer::~IHidServer() = default;
+
+void IHidServer::CreateAppletResource(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<IAppletResource>(system, resource_manager);
+}
+
+void IHidServer::ActivateDebugPad(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ Result result = ResultSuccess;
+ auto& debug_pad =
+ GetResourceManager()->GetController<Controller_DebugPad>(HidController::DebugPad);
+
+ if (!firmware_settings->IsDeviceManaged()) {
+ result = debug_pad.Activate();
+ }
+
+ if (result.IsSuccess()) {
+ result = debug_pad.Activate(applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ActivateTouchScreen(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ Result result = ResultSuccess;
+ auto& touch_screen =
+ GetResourceManager()->GetController<Controller_Touchscreen>(HidController::Touchscreen);
+
+ if (!firmware_settings->IsDeviceManaged()) {
+ result = touch_screen.Activate();
+ }
+
+ if (result.IsSuccess()) {
+ result = touch_screen.Activate(applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ActivateMouse(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ Result result = ResultSuccess;
+ auto& mouse = GetResourceManager()->GetController<Controller_Mouse>(HidController::Mouse);
+
+ if (!firmware_settings->IsDeviceManaged()) {
+ result = mouse.Activate();
+ }
+
+ if (result.IsSuccess()) {
+ result = mouse.Activate(applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ActivateKeyboard(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ Result result = ResultSuccess;
+ auto& keyboard =
+ GetResourceManager()->GetController<Controller_Keyboard>(HidController::Keyboard);
+
+ if (!firmware_settings->IsDeviceManaged()) {
+ result = keyboard.Activate();
+ }
+
+ if (result.IsSuccess()) {
+ result = keyboard.Activate(applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::SendKeyboardLockKeyEvent(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto flags{rp.Pop<u32>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::AcquireXpadIdEventHandle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ // Handle returned is null here
+}
+
+void IHidServer::ReleaseXpadIdEventHandle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::ActivateXpad(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ u32 basic_xpad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}",
+ parameters.basic_xpad_id, parameters.applet_resource_user_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetXpadIds(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_HID, "called");
+
+ // This function has been hardcoded since 10.0.0+
+ const std::array<u32, 4> basic_xpad_id{0, 1, 2, 3};
+ ctx.WriteBuffer(basic_xpad_id);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.Push<s64>(basic_xpad_id.size());
+}
+
+void IHidServer::ActivateJoyXpad(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetJoyXpadLifoHandle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ // Handle returned is null here
+}
+
+void IHidServer::GetJoyXpadIds(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_HID, "called");
+
+ // This function has been hardcoded since 10.0.0+
+ const s64 basic_xpad_id_count{};
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.Push(basic_xpad_id_count);
+}
+
+void IHidServer::ActivateSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::DeactivateSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetSixAxisSensorLifoHandle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::ActivateJoySixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::DeactivateJoySixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetJoySixAxisSensorLifoHandle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto joy_xpad_id{rp.Pop<u32>()};
+
+ LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
+
+ // This function has been stubbed since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ // Handle returned is null here
+}
+
+void IHidServer::StartSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, true);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::StopSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, false);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::IsSixAxisSensorFusionEnabled(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ bool is_enabled{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result =
+ controller.IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(result);
+ rb.Push(is_enabled);
+}
+
+void IHidServer::EnableSixAxisSensorFusion(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool enable_sixaxis_sensor_fusion;
+ INSERT_PADDING_BYTES_NOINIT(3);
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle,
+ parameters.enable_sixaxis_sensor_fusion);
+
+ LOG_DEBUG(Service_HID,
+ "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
+ "device_index={}, applet_resource_user_id={}",
+ parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
+ parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
+ parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::SetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ Core::HID::SixAxisSensorFusionParameters sixaxis_fusion;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result =
+ controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
+ "parameter2={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1,
+ parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::GetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ Core::HID::SixAxisSensorFusionParameters fusion_parameters{};
+ const auto& controller =
+ GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result =
+ controller.GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(result);
+ rb.PushRaw(fusion_parameters);
+}
+
+void IHidServer::ResetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ // Since these parameters are unknown just use what HW outputs
+ const Core::HID::SixAxisSensorFusionParameters fusion_parameters{
+ .parameter1 = 0.03f,
+ .parameter2 = 0.4f,
+ };
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result1 =
+ controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
+ const auto result2 = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle, true);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ if (result1.IsError()) {
+ rb.Push(result1);
+ return;
+ }
+ rb.Push(result2);
+}
+
+void IHidServer::SetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
+ const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
+ "applet_resource_user_id={}",
+ sixaxis_handle.npad_type, sixaxis_handle.npad_id, sixaxis_handle.device_index,
+ drift_mode, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::GetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(result);
+ rb.PushEnum(drift_mode);
+}
+
+void IHidServer::ResetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::IsSixAxisSensorAtRest(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ bool is_at_rest{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ controller.IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(is_at_rest);
+}
+
+void IHidServer::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ bool is_firmware_available{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ controller.IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
+ is_firmware_available);
+
+ LOG_WARNING(
+ Service_HID,
+ "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(is_firmware_available);
+}
+
+void IHidServer::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool enabled;
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.EnableSixAxisSensorUnalteredPassthrough(
+ parameters.sixaxis_handle, parameters.enabled);
+
+ LOG_DEBUG(Service_HID,
+ "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
+ "applet_resource_user_id={}",
+ parameters.enabled, parameters.sixaxis_handle.npad_type,
+ parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
+ parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ bool is_unaltered_sisxaxis_enabled{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled(
+ parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
+
+ LOG_DEBUG(
+ Service_HID,
+ "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(result);
+ rb.Push(is_unaltered_sisxaxis_enabled);
+}
+
+void IHidServer::LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ Core::HID::SixAxisSensorCalibrationParameter calibration{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result =
+ controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
+
+ LOG_WARNING(
+ Service_HID,
+ "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ if (result.IsSuccess()) {
+ ctx.WriteBuffer(calibration);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::GetSixAxisSensorIcInformation(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ Core::HID::SixAxisSensorIcInformation ic_information{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result =
+ controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
+
+ LOG_WARNING(
+ Service_HID,
+ "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ if (result.IsSuccess()) {
+ ctx.WriteBuffer(ic_information);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::SixAxisSensorHandle sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result =
+ controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
+
+ LOG_WARNING(
+ Service_HID,
+ "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
+ parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ActivateGesture(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ u32 basic_gesture_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_INFO(Service_HID, "called, basic_gesture_id={}, applet_resource_user_id={}",
+ parameters.basic_gesture_id, parameters.applet_resource_user_id);
+
+ Result result = ResultSuccess;
+ auto& gesture = GetResourceManager()->GetController<Controller_Gesture>(HidController::Gesture);
+
+ if (!firmware_settings->IsDeviceManaged()) {
+ result = gesture.Activate();
+ }
+
+ if (result.IsSuccess()) {
+ // TODO: Use gesture id here
+ result = gesture.Activate(parameters.applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadStyleSet supported_styleset;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetSupportedStyleSet({parameters.supported_styleset});
+
+ LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
+ parameters.supported_styleset, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetSupportedNpadStyleSet(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.PushEnum(GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .GetSupportedStyleSet()
+ .raw);
+}
+
+void IHidServer::SetSupportedNpadIdType(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ const auto result = GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetSupportedNpadIdTypes(ctx.ReadBuffer());
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ActivateNpad(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+
+ // TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0);
+ const Result result = npad.Activate(applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::DeactivateNpad(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ // This function does nothing since 10.0.0+
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ u64 unknown;
+ };
+ static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
+ parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown);
+
+ // Games expect this event to be signaled after calling this function
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SignalStyleSetChangedEvent(parameters.npad_id);
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .GetStyleSetChangedEvent(parameters.npad_id));
+}
+
+void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ controller.DisconnectNpad(parameters.npad_id);
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
+ parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
+
+ Core::HID::LedPattern pattern{0, 0, 0, 0};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.GetLedPattern(npad_id, pattern);
+
+ LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(result);
+ rb.Push(pattern.raw);
+}
+
+void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Controller_NPad::NpadRevision revision;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
+ parameters.applet_resource_user_id);
+
+ auto& npad = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+
+ // TODO: npad->SetRevision(applet_resource_user_id, revision);
+ const auto result = npad.Activate(parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetHoldType(hold_type);
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}",
+ applet_resource_user_id, hold_type);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetNpadJoyHoldType(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.PushEnum(
+ GetResourceManager()->GetController<Controller_NPad>(HidController::NPad).GetHoldType());
+}
+
+void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ Core::HID::NpadIdType new_npad_id{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ controller.SetNpadMode(new_npad_id, parameters.npad_id,
+ Controller_NPad::NpadJoyDeviceType::Left,
+ Controller_NPad::NpadJoyAssignmentMode::Single);
+
+ LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
+ parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
+ };
+ static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ Core::HID::NpadIdType new_npad_id{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
+ Controller_NPad::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,
+ parameters.npad_joy_device_type);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ Core::HID::NpadIdType new_npad_id{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ controller.SetNpadMode(new_npad_id, parameters.npad_id, {},
+ Controller_NPad::NpadJoyAssignmentMode::Dual);
+
+ LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
+ parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
+ const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
+
+ LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
+ npad_id_1, npad_id_2, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::StartLrAssignmentMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .StartLRAssignmentMode();
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .StopLRAssignmentMode();
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetNpadHandheldActivationMode(activation_mode);
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}",
+ applet_resource_user_id, activation_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetNpadHandheldActivationMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.PushEnum(GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .GetNpadHandheldActivationMode());
+}
+
+void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
+ const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2);
+
+ LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
+ npad_id_1, npad_id_2, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ bool is_enabled = false;
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result =
+ controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
+ parameters.npad_id, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(result);
+ rb.Push(is_enabled);
+}
+
+void IHidServer::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool is_enabled;
+ INSERT_PADDING_BYTES_NOINIT(3);
+ Core::HID::NpadIdType npad_id;
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
+ parameters.is_enabled, parameters.npad_id);
+
+ LOG_DEBUG(Service_HID,
+ "(STUBBED) called, is_enabled={}, npad_id={}, applet_resource_user_id={}",
+ parameters.is_enabled, parameters.npad_id, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
+ };
+ static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ Core::HID::NpadIdType new_npad_id{};
+ auto& controller = GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+ const auto is_reassigned =
+ controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
+ Controller_NPad::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,
+ parameters.npad_joy_device_type);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.Push(is_reassigned);
+ rb.PushEnum(new_npad_id);
+}
+
+void IHidServer::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool analog_stick_use_center_clamp;
+ INSERT_PADDING_BYTES_NOINIT(7);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
+ parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetNpadCaptureButtonAssignment(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadStyleSet npad_styleset;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ Core::HID::NpadButton button;
+ };
+ static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, npad_styleset={}, applet_resource_user_id={}, button={}",
+ parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
+ const auto& controller =
+ GetResourceManager()->GetController<Controller_NPad>(HidController::NPad);
+
+ Core::HID::VibrationDeviceInfo vibration_device_info;
+ bool check_device_index = false;
+
+ switch (vibration_device_handle.npad_type) {
+ case Core::HID::NpadStyleIndex::ProController:
+ case Core::HID::NpadStyleIndex::Handheld:
+ case Core::HID::NpadStyleIndex::JoyconDual:
+ case Core::HID::NpadStyleIndex::JoyconLeft:
+ case Core::HID::NpadStyleIndex::JoyconRight:
+ vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
+ check_device_index = true;
+ break;
+ case Core::HID::NpadStyleIndex::GameCube:
+ vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
+ break;
+ case Core::HID::NpadStyleIndex::N64:
+ vibration_device_info.type = Core::HID::VibrationDeviceType::N64;
+ break;
+ default:
+ vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
+ break;
+ }
+
+ vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
+ if (check_device_index) {
+ switch (vibration_device_handle.device_index) {
+ case Core::HID::DeviceIndex::Left:
+ vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
+ break;
+ case Core::HID::DeviceIndex::Right:
+ vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
+ break;
+ case Core::HID::DeviceIndex::None:
+ default:
+ ASSERT_MSG(false, "DeviceIndex should never be None!");
+ break;
+ }
+ }
+
+ LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}",
+ vibration_device_info.type, vibration_device_info.position);
+
+ const auto result = controller.IsDeviceHandleValid(vibration_device_handle);
+ if (result.IsError()) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(vibration_device_info);
+}
+
+void IHidServer::SendVibrationValue(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::VibrationDeviceHandle vibration_device_handle;
+ Core::HID::VibrationValue vibration_value;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .VibrateController(parameters.vibration_device_handle, parameters.vibration_value);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.vibration_device_handle.npad_type,
+ parameters.vibration_device_handle.npad_id,
+ parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::VibrationDeviceHandle vibration_device_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.vibration_device_handle.npad_type,
+ parameters.vibration_device_handle.npad_id,
+ parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 6};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .GetLastVibration(parameters.vibration_device_handle));
+}
+
+void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_HID, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<IActiveVibrationDeviceList>(system, resource_manager);
+}
+
+void IHidServer::PermitVibration(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto can_vibrate{rp.Pop<bool>()};
+
+ // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
+ // by converting it to a bool
+ Settings::values.vibration_enabled.SetValue(can_vibrate);
+
+ LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_HID, "called");
+
+ // nnSDK checks if a float is greater than zero. We return the bool we stored earlier
+ const auto is_enabled = Settings::values.vibration_enabled.GetValue();
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(is_enabled);
+}
+
+void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ const auto handle_data = ctx.ReadBuffer(0);
+ const auto handle_count = ctx.GetReadBufferNumElements<Core::HID::VibrationDeviceHandle>(0);
+ const auto vibration_data = ctx.ReadBuffer(1);
+ const auto vibration_count = ctx.GetReadBufferNumElements<Core::HID::VibrationValue>(1);
+
+ auto vibration_device_handles =
+ std::span(reinterpret_cast<const Core::HID::VibrationDeviceHandle*>(handle_data.data()),
+ handle_count);
+ auto vibration_values = std::span(
+ reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .VibrateControllers(vibration_device_handles, vibration_values);
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::VibrationDeviceHandle vibration_device_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ Core::HID::VibrationGcErmCommand gc_erm_command;
+ };
+ static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ /**
+ * Note: This uses yuzu-specific behavior such that the StopHard command produces
+ * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below,
+ * in order to differentiate between Stop and StopHard commands.
+ * This is done to reuse the controller vibration functions made for regular controllers.
+ */
+ const auto vibration_value = [parameters] {
+ switch (parameters.gc_erm_command) {
+ case Core::HID::VibrationGcErmCommand::Stop:
+ return Core::HID::VibrationValue{
+ .low_amplitude = 0.0f,
+ .low_frequency = 160.0f,
+ .high_amplitude = 0.0f,
+ .high_frequency = 320.0f,
+ };
+ case Core::HID::VibrationGcErmCommand::Start:
+ return Core::HID::VibrationValue{
+ .low_amplitude = 1.0f,
+ .low_frequency = 160.0f,
+ .high_amplitude = 1.0f,
+ .high_frequency = 320.0f,
+ };
+ case Core::HID::VibrationGcErmCommand::StopHard:
+ return Core::HID::VibrationValue{
+ .low_amplitude = 0.0f,
+ .low_frequency = 0.0f,
+ .high_amplitude = 0.0f,
+ .high_frequency = 0.0f,
+ };
+ default:
+ return Core::HID::DEFAULT_VIBRATION_VALUE;
+ }
+ }();
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .VibrateController(parameters.vibration_device_handle, vibration_value);
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
+ "gc_erm_command={}",
+ parameters.vibration_device_handle.npad_type,
+ parameters.vibration_device_handle.npad_id,
+ parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id,
+ parameters.gc_erm_command);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::VibrationDeviceHandle vibration_device_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ const auto last_vibration = GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .GetLastVibration(parameters.vibration_device_handle);
+
+ const auto gc_erm_command = [last_vibration] {
+ if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
+ return Core::HID::VibrationGcErmCommand::Start;
+ }
+
+ /**
+ * Note: This uses yuzu-specific behavior such that the StopHard command produces
+ * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function
+ * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
+ * This is done to reuse the controller vibration functions made for regular controllers.
+ */
+ if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
+ return Core::HID::VibrationGcErmCommand::StopHard;
+ }
+
+ return Core::HID::VibrationGcErmCommand::Stop;
+ }();
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.vibration_device_handle.npad_type,
+ parameters.vibration_device_handle.npad_id,
+ parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.PushEnum(gc_erm_command);
+}
+
+void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetPermitVibrationSession(true);
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) {
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetPermitVibrationSession(false);
+
+ LOG_DEBUG(Service_HID, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::VibrationDeviceHandle vibration_device_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_DEBUG(Service_HID,
+ "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
+ parameters.vibration_device_handle.npad_type,
+ parameters.vibration_device_handle.npad_id,
+ parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .IsVibrationDeviceMounted(parameters.vibration_device_handle));
+}
+
+void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ Result result = ResultSuccess;
+ auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>(
+ HidController::ConsoleSixAxisSensor);
+
+ if (!firmware_settings->IsDeviceManaged()) {
+ result = console_sixaxis.Activate();
+ }
+
+ if (result.IsSuccess()) {
+ result = console_sixaxis.Activate(applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::StartConsoleSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
+ parameters.console_sixaxis_handle.unknown_1,
+ parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::StopConsoleSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
+ parameters.console_sixaxis_handle.unknown_1,
+ parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::ActivateSevenSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ Result result = ResultSuccess;
+ auto console_sixaxis = GetResourceManager()->GetController<Controller_ConsoleSixAxis>(
+ HidController::ConsoleSixAxisSensor);
+
+ if (!firmware_settings->IsDeviceManaged()) {
+ result = console_sixaxis.Activate();
+ }
+
+ if (result.IsSuccess()) {
+ console_sixaxis.Activate(applet_resource_user_id);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::StartSevenSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::StopSevenSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto t_mem_1_size{rp.Pop<u64>()};
+ const auto t_mem_2_size{rp.Pop<u64>()};
+ const auto t_mem_1_handle{ctx.GetCopyHandle(0)};
+ const auto t_mem_2_handle{ctx.GetCopyHandle(1)};
+
+ ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
+ ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
+
+ auto t_mem_1 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
+ t_mem_1_handle);
+
+ if (t_mem_1.IsNull()) {
+ LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultUnknown);
+ return;
+ }
+
+ auto t_mem_2 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
+ t_mem_2_handle);
+
+ if (t_mem_2.IsNull()) {
+ LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultUnknown);
+ return;
+ }
+
+ ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size");
+ ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
+
+ // Activate console six axis controller
+ GetResourceManager()
+ ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
+ .Activate();
+
+ GetResourceManager()
+ ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
+ .SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
+
+ LOG_WARNING(Service_HID,
+ "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
+ "applet_resource_user_id={}",
+ t_mem_1_handle, t_mem_2_handle, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::FinalizeSevenSixAxisSensor(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
+ applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ GetResourceManager()
+ ->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
+ .ResetTimestamp();
+
+ LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(false);
+}
+
+void IHidServer::GetPalmaConnectionHandle(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ Core::HID::NpadIdType npad_id;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
+ parameters.npad_id, parameters.applet_resource_user_id);
+
+ Controller_Palma::PalmaConnectionHandle handle;
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result = controller.GetPalmaConnectionHandle(parameters.npad_id, handle);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(result);
+ rb.PushRaw(handle);
+}
+
+void IHidServer::InitializePalma(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result = controller.InitializePalma(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(controller.AcquirePalmaOperationCompleteEvent(connection_handle));
+}
+
+void IHidServer::GetPalmaOperationInfo(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ Controller_Palma::PalmaOperationType operation_type;
+ Controller_Palma::PalmaOperationData data;
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result = controller.GetPalmaOperationInfo(connection_handle, operation_type, data);
+
+ if (result.IsError()) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ }
+
+ ctx.WriteBuffer(data);
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(result);
+ rb.Push(static_cast<u64>(operation_type));
+}
+
+void IHidServer::PlayPalmaActivity(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto palma_activity{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, palma_activity={}",
+ connection_handle.npad_id, palma_activity);
+
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result = controller.PlayPalmaActivity(connection_handle, palma_activity);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::SetPalmaFrModeType(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto fr_mode{rp.PopEnum<Controller_Palma::PalmaFrModeType>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, fr_mode={}",
+ connection_handle.npad_id, fr_mode);
+
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result = controller.SetPalmaFrModeType(connection_handle, fr_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ReadPalmaStep(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result = controller.ReadPalmaStep(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool is_enabled;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ Controller_Palma::PalmaConnectionHandle connection_handle;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, is_enabled={}",
+ parameters.connection_handle.npad_id, parameters.is_enabled);
+
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result =
+ controller.EnablePalmaStep(parameters.connection_handle, parameters.is_enabled);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ResetPalmaStep(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ auto& controller = GetResourceManager()->GetController<Controller_Palma>(HidController::Palma);
+ const auto result = controller.ResetPalmaStep(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ReadPalmaApplicationSection(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::WritePalmaApplicationSection(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::ReadPalmaUniqueCode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .ReadPalmaUniqueCode(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .SetPalmaUniqueCodeInvalid(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::WritePalmaActivityEntry(HLERequestContext& ctx) {
+ LOG_CRITICAL(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto unknown{rp.Pop<u64>()};
+
+ [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
+ connection_handle.npad_id, unknown);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .WritePalmaRgbLedPatternEntry(connection_handle, unknown);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+ const auto wave_set{rp.PopEnum<Controller_Palma::PalmaWaveSet>()};
+ const auto unknown{rp.Pop<u64>()};
+ const auto t_mem_size{rp.Pop<u64>()};
+ const auto t_mem_handle{ctx.GetCopyHandle(0)};
+ const auto size{rp.Pop<u64>()};
+
+ ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes");
+
+ auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
+ t_mem_handle);
+
+ if (t_mem.IsNull()) {
+ LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultUnknown);
+ return;
+ }
+
+ ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size");
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, connection_handle={}, wave_set={}, unknown={}, "
+ "t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
+ connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .WritePalmaWaveEntry(connection_handle, wave_set, t_mem->GetSourceAddress(), t_mem_size);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ s32 database_id_version;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ Controller_Palma::PalmaConnectionHandle connection_handle;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, database_id_version={}",
+ parameters.connection_handle.npad_id, parameters.database_id_version);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .SetPalmaDataBaseIdentificationVersion(parameters.connection_handle,
+ parameters.database_id_version);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .GetPalmaDataBaseIdentificationVersion(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SuspendPalmaFeature(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetPalmaOperationResult(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ const auto result = GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .GetPalmaOperationResult(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IHidServer::ReadPalmaPlayLog(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::ResetPalmaPlayLog(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetIsPalmaAllConnectable(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ bool is_palma_all_connectable;
+ INSERT_PADDING_BYTES_NOINIT(7);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, is_palma_all_connectable={},applet_resource_user_id={}",
+ parameters.is_palma_all_connectable, parameters.applet_resource_user_id);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetIsPalmaPairedConnectable(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::PairPalma(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .PairPalma(connection_handle);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetPalmaBoostMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto palma_boost_mode{rp.Pop<bool>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode);
+
+ GetResourceManager()
+ ->GetController<Controller_Palma>(HidController::Palma)
+ .SetPalmaBoostMode(palma_boost_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::CancelWritePalmaWaveEntry(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::EnablePalmaBoostMode(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetPalmaBluetoothAddress(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()};
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .SetNpadCommunicationMode(communication_mode);
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}",
+ applet_resource_user_id, communication_mode);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::GetNpadCommunicationMode(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.PushEnum(GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .GetNpadCommunicationMode());
+}
+
+void IHidServer::SetTouchScreenConfiguration(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
+ touchscreen_mode.mode, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidServer::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ struct Parameters {
+ s32 unknown;
+ INSERT_PADDING_WORDS_NOINIT(1);
+ u64 applet_resource_user_id;
+ };
+ static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
+ parameters.unknown, parameters.applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(false);
+}
+
+std::shared_ptr<ResourceManager> IHidServer::GetResourceManager() {
+ resource_manager->Initialize();
+ return resource_manager;
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h
new file mode 100644
index 000000000..eb2e8e7f4
--- /dev/null
+++ b/src/core/hle/service/hid/hid_server.h
@@ -0,0 +1,149 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::HID {
+class ResourceManager;
+class HidFirmwareSettings;
+
+class IHidServer final : public ServiceFramework<IHidServer> {
+public:
+ explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource,
+ std::shared_ptr<HidFirmwareSettings> settings);
+ ~IHidServer() override;
+
+ std::shared_ptr<ResourceManager> GetResourceManager();
+
+private:
+ void CreateAppletResource(HLERequestContext& ctx);
+ void ActivateDebugPad(HLERequestContext& ctx);
+ void ActivateTouchScreen(HLERequestContext& ctx);
+ void ActivateMouse(HLERequestContext& ctx);
+ void ActivateKeyboard(HLERequestContext& ctx);
+ void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
+ void AcquireXpadIdEventHandle(HLERequestContext& ctx);
+ void ReleaseXpadIdEventHandle(HLERequestContext& ctx);
+ void ActivateXpad(HLERequestContext& ctx);
+ void GetXpadIds(HLERequestContext& ctx);
+ void ActivateJoyXpad(HLERequestContext& ctx);
+ void GetJoyXpadLifoHandle(HLERequestContext& ctx);
+ void GetJoyXpadIds(HLERequestContext& ctx);
+ void ActivateSixAxisSensor(HLERequestContext& ctx);
+ void DeactivateSixAxisSensor(HLERequestContext& ctx);
+ void GetSixAxisSensorLifoHandle(HLERequestContext& ctx);
+ void ActivateJoySixAxisSensor(HLERequestContext& ctx);
+ void DeactivateJoySixAxisSensor(HLERequestContext& ctx);
+ void GetJoySixAxisSensorLifoHandle(HLERequestContext& ctx);
+ void StartSixAxisSensor(HLERequestContext& ctx);
+ void StopSixAxisSensor(HLERequestContext& ctx);
+ void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
+ void EnableSixAxisSensorFusion(HLERequestContext& ctx);
+ void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
+ void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
+ void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
+ void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
+ void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
+ void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
+ void IsSixAxisSensorAtRest(HLERequestContext& ctx);
+ void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
+ void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
+ void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
+ void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
+ void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
+ void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
+ void ActivateGesture(HLERequestContext& ctx);
+ void SetSupportedNpadStyleSet(HLERequestContext& ctx);
+ void GetSupportedNpadStyleSet(HLERequestContext& ctx);
+ void SetSupportedNpadIdType(HLERequestContext& ctx);
+ void ActivateNpad(HLERequestContext& ctx);
+ void DeactivateNpad(HLERequestContext& ctx);
+ void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
+ void DisconnectNpad(HLERequestContext& ctx);
+ void GetPlayerLedPattern(HLERequestContext& ctx);
+ void ActivateNpadWithRevision(HLERequestContext& ctx);
+ void SetNpadJoyHoldType(HLERequestContext& ctx);
+ void GetNpadJoyHoldType(HLERequestContext& ctx);
+ void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
+ void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
+ void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
+ void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
+ void StartLrAssignmentMode(HLERequestContext& ctx);
+ void StopLrAssignmentMode(HLERequestContext& ctx);
+ void SetNpadHandheldActivationMode(HLERequestContext& ctx);
+ void GetNpadHandheldActivationMode(HLERequestContext& ctx);
+ void SwapNpadAssignment(HLERequestContext& ctx);
+ void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
+ void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
+ void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
+ void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
+ void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
+ void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
+ void GetVibrationDeviceInfo(HLERequestContext& ctx);
+ void SendVibrationValue(HLERequestContext& ctx);
+ void GetActualVibrationValue(HLERequestContext& ctx);
+ void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
+ void PermitVibration(HLERequestContext& ctx);
+ void IsVibrationPermitted(HLERequestContext& ctx);
+ void SendVibrationValues(HLERequestContext& ctx);
+ void SendVibrationGcErmCommand(HLERequestContext& ctx);
+ void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
+ void BeginPermitVibrationSession(HLERequestContext& ctx);
+ void EndPermitVibrationSession(HLERequestContext& ctx);
+ void IsVibrationDeviceMounted(HLERequestContext& ctx);
+ void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
+ void StartConsoleSixAxisSensor(HLERequestContext& ctx);
+ void StopConsoleSixAxisSensor(HLERequestContext& ctx);
+ void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
+ void StartSevenSixAxisSensor(HLERequestContext& ctx);
+ void StopSevenSixAxisSensor(HLERequestContext& ctx);
+ void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
+ void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
+ void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
+ void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
+ void GetPalmaConnectionHandle(HLERequestContext& ctx);
+ void InitializePalma(HLERequestContext& ctx);
+ void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
+ void GetPalmaOperationInfo(HLERequestContext& ctx);
+ void PlayPalmaActivity(HLERequestContext& ctx);
+ void SetPalmaFrModeType(HLERequestContext& ctx);
+ void ReadPalmaStep(HLERequestContext& ctx);
+ void EnablePalmaStep(HLERequestContext& ctx);
+ void ResetPalmaStep(HLERequestContext& ctx);
+ void ReadPalmaApplicationSection(HLERequestContext& ctx);
+ void WritePalmaApplicationSection(HLERequestContext& ctx);
+ void ReadPalmaUniqueCode(HLERequestContext& ctx);
+ void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
+ void WritePalmaActivityEntry(HLERequestContext& ctx);
+ void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
+ void WritePalmaWaveEntry(HLERequestContext& ctx);
+ void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
+ void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
+ void SuspendPalmaFeature(HLERequestContext& ctx);
+ void GetPalmaOperationResult(HLERequestContext& ctx);
+ void ReadPalmaPlayLog(HLERequestContext& ctx);
+ void ResetPalmaPlayLog(HLERequestContext& ctx);
+ void SetIsPalmaAllConnectable(HLERequestContext& ctx);
+ void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
+ void PairPalma(HLERequestContext& ctx);
+ void SetPalmaBoostMode(HLERequestContext& ctx);
+ void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
+ void EnablePalmaBoostMode(HLERequestContext& ctx);
+ void GetPalmaBluetoothAddress(HLERequestContext& ctx);
+ void SetDisallowedPalmaConnection(HLERequestContext& ctx);
+ void SetNpadCommunicationMode(HLERequestContext& ctx);
+ void GetNpadCommunicationMode(HLERequestContext& ctx);
+ void SetTouchScreenConfiguration(HLERequestContext& ctx);
+ void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
+
+ std::shared_ptr<ResourceManager> resource_manager;
+ std::shared_ptr<HidFirmwareSettings> firmware_settings;
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp
new file mode 100644
index 000000000..83cfadada
--- /dev/null
+++ b/src/core/hle/service/hid/hid_system_server.cpp
@@ -0,0 +1,304 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "core/hid/hid_core.h"
+#include "core/hle/service/hid/controllers/npad.h"
+#include "core/hle/service/hid/controllers/touchscreen.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"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::HID {
+
+IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
+ : ServiceFramework{system_, "hid:sys"}, service_context{system_, service_name},
+ resource_manager{resource} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {31, nullptr, "SendKeyboardLockKeyEvent"},
+ {101, nullptr, "AcquireHomeButtonEventHandle"},
+ {111, nullptr, "ActivateHomeButton"},
+ {121, nullptr, "AcquireSleepButtonEventHandle"},
+ {131, nullptr, "ActivateSleepButton"},
+ {141, nullptr, "AcquireCaptureButtonEventHandle"},
+ {151, nullptr, "ActivateCaptureButton"},
+ {161, nullptr, "GetPlatformConfig"},
+ {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
+ {211, nullptr, "GetNpadsWithNfc"},
+ {212, nullptr, "AcquireNfcActivateEventHandle"},
+ {213, nullptr, "ActivateNfc"},
+ {214, nullptr, "GetXcdHandleForNpadWithNfc"},
+ {215, nullptr, "IsNfcActivated"},
+ {230, nullptr, "AcquireIrSensorEventHandle"},
+ {231, nullptr, "ActivateIrSensor"},
+ {232, nullptr, "GetIrSensorState"},
+ {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
+ {301, nullptr, "ActivateNpadSystem"},
+ {303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
+ {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
+ {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
+ {306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"},
+ {307, nullptr, "GetNpadSystemExtStyle"},
+ {308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
+ {309, nullptr, "GetNpadFullKeyGripColor"},
+ {310, nullptr, "GetMaskedSupportedNpadStyleSet"},
+ {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
+ {312, nullptr, "SetSupportedNpadStyleSetAll"},
+ {313, nullptr, "GetNpadCaptureButtonAssignment"},
+ {314, nullptr, "GetAppletFooterUiType"},
+ {315, nullptr, "GetAppletDetailedUiType"},
+ {316, nullptr, "GetNpadInterfaceType"},
+ {317, nullptr, "GetNpadLeftRightInterfaceType"},
+ {318, nullptr, "HasBattery"},
+ {319, nullptr, "HasLeftRightBattery"},
+ {321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
+ {322, nullptr, "GetIrSensorState"},
+ {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
+ {324, nullptr, "GetUniquePadButtonSet"},
+ {325, nullptr, "GetUniquePadColor"},
+ {326, nullptr, "GetUniquePadAppletDetailedUiType"},
+ {327, nullptr, "GetAbstractedPadIdDataFromNpad"},
+ {328, nullptr, "AttachAbstractedPadToNpad"},
+ {329, nullptr, "DetachAbstractedPadAll"},
+ {330, nullptr, "CheckAbstractedPadConnection"},
+ {500, nullptr, "SetAppletResourceUserId"},
+ {501, nullptr, "RegisterAppletResourceUserId"},
+ {502, nullptr, "UnregisterAppletResourceUserId"},
+ {503, nullptr, "EnableAppletToGetInput"},
+ {504, nullptr, "SetAruidValidForVibration"},
+ {505, nullptr, "EnableAppletToGetSixAxisSensor"},
+ {506, nullptr, "EnableAppletToGetPadInput"},
+ {507, nullptr, "EnableAppletToGetTouchScreen"},
+ {510, nullptr, "SetVibrationMasterVolume"},
+ {511, nullptr, "GetVibrationMasterVolume"},
+ {512, nullptr, "BeginPermitVibrationSession"},
+ {513, nullptr, "EndPermitVibrationSession"},
+ {514, nullptr, "Unknown514"},
+ {520, nullptr, "EnableHandheldHids"},
+ {521, nullptr, "DisableHandheldHids"},
+ {522, nullptr, "SetJoyConRailEnabled"},
+ {523, nullptr, "IsJoyConRailEnabled"},
+ {524, nullptr, "IsHandheldHidsEnabled"},
+ {525, nullptr, "IsJoyConAttachedOnAllRail"},
+ {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
+ {541, nullptr, "GetPlayReportControllerUsages"},
+ {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
+ {543, nullptr, "GetRegisteredDevicesOld"},
+ {544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
+ {545, nullptr, "SendConnectionTrigger"},
+ {546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
+ {547, nullptr, "GetAllowedBluetoothLinksCount"},
+ {548, nullptr, "GetRegisteredDevices"},
+ {549, nullptr, "GetConnectableRegisteredDevices"},
+ {700, nullptr, "ActivateUniquePad"},
+ {702, nullptr, "AcquireUniquePadConnectionEventHandle"},
+ {703, nullptr, "GetUniquePadIds"},
+ {751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
+ {800, nullptr, "ListSixAxisSensorHandles"},
+ {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
+ {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
+ {803, nullptr, "StartSixAxisSensorUserCalibration"},
+ {804, nullptr, "CancelSixAxisSensorUserCalibration"},
+ {805, nullptr, "GetUniquePadBluetoothAddress"},
+ {806, nullptr, "DisconnectUniquePad"},
+ {807, nullptr, "GetUniquePadType"},
+ {808, nullptr, "GetUniquePadInterface"},
+ {809, nullptr, "GetUniquePadSerialNumber"},
+ {810, nullptr, "GetUniquePadControllerNumber"},
+ {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
+ {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
+ {821, nullptr, "StartAnalogStickManualCalibration"},
+ {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
+ {823, nullptr, "CancelAnalogStickManualCalibration"},
+ {824, nullptr, "ResetAnalogStickManualCalibration"},
+ {825, nullptr, "GetAnalogStickState"},
+ {826, nullptr, "GetAnalogStickManualCalibrationStage"},
+ {827, nullptr, "IsAnalogStickButtonPressed"},
+ {828, nullptr, "IsAnalogStickInReleasePosition"},
+ {829, nullptr, "IsAnalogStickInCircumference"},
+ {830, nullptr, "SetNotificationLedPattern"},
+ {831, nullptr, "SetNotificationLedPatternWithTimeout"},
+ {832, nullptr, "PrepareHidsForNotificationWake"},
+ {850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
+ {851, nullptr, "EnableUsbFullKeyController"},
+ {852, nullptr, "IsUsbConnected"},
+ {870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
+ {900, nullptr, "ActivateInputDetector"},
+ {901, nullptr, "NotifyInputDetector"},
+ {1000, nullptr, "InitializeFirmwareUpdate"},
+ {1001, nullptr, "GetFirmwareVersion"},
+ {1002, nullptr, "GetAvailableFirmwareVersion"},
+ {1003, nullptr, "IsFirmwareUpdateAvailable"},
+ {1004, nullptr, "CheckFirmwareUpdateRequired"},
+ {1005, nullptr, "StartFirmwareUpdate"},
+ {1006, nullptr, "AbortFirmwareUpdate"},
+ {1007, nullptr, "GetFirmwareUpdateState"},
+ {1008, nullptr, "ActivateAudioControl"},
+ {1009, nullptr, "AcquireAudioControlEventHandle"},
+ {1010, nullptr, "GetAudioControlStates"},
+ {1011, nullptr, "DeactivateAudioControl"},
+ {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
+ {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
+ {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
+ {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
+ {1100, nullptr, "GetHidbusSystemServiceObject"},
+ {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
+ {1130, nullptr, "InitializeUsbFirmwareUpdate"},
+ {1131, nullptr, "FinalizeUsbFirmwareUpdate"},
+ {1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
+ {1133, nullptr, "StartUsbFirmwareUpdate"},
+ {1134, nullptr, "GetUsbFirmwareUpdateState"},
+ {1150, nullptr, "SetTouchScreenMagnification"},
+ {1151, nullptr, "GetTouchScreenFirmwareVersion"},
+ {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
+ {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
+ {1154, nullptr, "IsFirmwareAvailableForNotification"},
+ {1155, nullptr, "SetForceHandheldStyleVibration"},
+ {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
+ {1157, nullptr, "CancelConnectionTrigger"},
+ {1200, nullptr, "IsButtonConfigSupported"},
+ {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
+ {1202, nullptr, "DeleteButtonConfig"},
+ {1203, nullptr, "DeleteButtonConfigEmbedded"},
+ {1204, nullptr, "SetButtonConfigEnabled"},
+ {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
+ {1206, nullptr, "IsButtonConfigEnabled"},
+ {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
+ {1208, nullptr, "SetButtonConfigEmbedded"},
+ {1209, nullptr, "SetButtonConfigFull"},
+ {1210, nullptr, "SetButtonConfigLeft"},
+ {1211, nullptr, "SetButtonConfigRight"},
+ {1212, nullptr, "GetButtonConfigEmbedded"},
+ {1213, nullptr, "GetButtonConfigFull"},
+ {1214, nullptr, "GetButtonConfigLeft"},
+ {1215, nullptr, "GetButtonConfigRight"},
+ {1250, nullptr, "IsCustomButtonConfigSupported"},
+ {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
+ {1252, nullptr, "IsDefaultButtonConfigFull"},
+ {1253, nullptr, "IsDefaultButtonConfigLeft"},
+ {1254, nullptr, "IsDefaultButtonConfigRight"},
+ {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
+ {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
+ {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
+ {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
+ {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
+ {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
+ {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
+ {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
+ {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
+ {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
+ {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
+ {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
+ {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
+ {1268, nullptr, "DeleteButtonConfigStorageFull"},
+ {1269, nullptr, "DeleteButtonConfigStorageLeft"},
+ {1270, nullptr, "DeleteButtonConfigStorageRight"},
+ {1271, nullptr, "IsUsingCustomButtonConfig"},
+ {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
+ {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
+ {1274, nullptr, "SetDefaultButtonConfig"},
+ {1275, nullptr, "SetAllDefaultButtonConfig"},
+ {1276, nullptr, "SetHidButtonConfigEmbedded"},
+ {1277, nullptr, "SetHidButtonConfigFull"},
+ {1278, nullptr, "SetHidButtonConfigLeft"},
+ {1279, nullptr, "SetHidButtonConfigRight"},
+ {1280, nullptr, "GetHidButtonConfigEmbedded"},
+ {1281, nullptr, "GetHidButtonConfigFull"},
+ {1282, nullptr, "GetHidButtonConfigLeft"},
+ {1283, nullptr, "GetHidButtonConfigRight"},
+ {1284, nullptr, "GetButtonConfigStorageEmbedded"},
+ {1285, nullptr, "GetButtonConfigStorageFull"},
+ {1286, nullptr, "GetButtonConfigStorageLeft"},
+ {1287, nullptr, "GetButtonConfigStorageRight"},
+ {1288, nullptr, "SetButtonConfigStorageEmbedded"},
+ {1289, nullptr, "SetButtonConfigStorageFull"},
+ {1290, nullptr, "DeleteButtonConfigStorageRight"},
+ {1291, nullptr, "DeleteButtonConfigStorageRight"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+
+ joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
+}
+
+IHidSystemServer::~IHidSystemServer() {
+ service_context.CloseEvent(joy_detach_event);
+};
+
+void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "called");
+
+ GetResourceManager()
+ ->GetController<Controller_NPad>(HidController::NPad)
+ .ApplyNpadSystemCommonPolicy();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_HID, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.PushEnum(system.HIDCore().GetLastActiveController());
+}
+
+void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
+
+ const std::vector<Core::HID::UniquePadId> unique_pads{};
+
+ ctx.WriteBuffer(unique_pads);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(static_cast<u32>(unique_pads.size()));
+}
+
+void IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
+ LOG_INFO(Service_AM, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
+}
+
+void IHidSystemServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
+ const bool is_enabled = false;
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(is_enabled);
+}
+
+void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+
+ Core::HID::TouchScreenConfigurationForNx touchscreen_config{
+ .mode = Core::HID::TouchScreenModeForNx::Finger,
+ };
+
+ if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
+ touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
+ touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 6};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(touchscreen_config);
+}
+
+std::shared_ptr<ResourceManager> IHidSystemServer::GetResourceManager() {
+ resource_manager->Initialize();
+ return resource_manager;
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h
new file mode 100644
index 000000000..d4b3910fa
--- /dev/null
+++ b/src/core/hle/service/hid/hid_system_server.h
@@ -0,0 +1,40 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Kernel {
+class KEvent;
+}
+
+namespace Service::HID {
+class ResourceManager;
+
+class IHidSystemServer final : public ServiceFramework<IHidSystemServer> {
+public:
+ explicit IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
+ ~IHidSystemServer() override;
+
+private:
+ void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx);
+ void GetLastActiveNpad(HLERequestContext& ctx);
+ void GetUniquePadsFromNpad(HLERequestContext& ctx);
+ void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx);
+ void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
+ void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx);
+
+ std::shared_ptr<ResourceManager> GetResourceManager();
+
+ Kernel::KEvent* joy_detach_event;
+ KernelHelpers::ServiceContext service_context;
+ std::shared_ptr<ResourceManager> resource_manager;
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.cpp b/src/core/hle/service/hid/hidbus/hidbus_base.cpp
index ee522c36e..8c44f93e8 100644
--- a/src/core/hle/service/hid/hidbus/hidbus_base.cpp
+++ b/src/core/hle/service/hid/hidbus/hidbus_base.cpp
@@ -13,7 +13,10 @@ HidbusBase::HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& ser
: system(system_), service_context(service_context_) {
send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent");
}
-HidbusBase::~HidbusBase() = default;
+
+HidbusBase::~HidbusBase() {
+ service_context.CloseEvent(send_command_async_event);
+};
void HidbusBase::ActivateDevice() {
if (is_activated) {
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index 221c33b86..d383a266d 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -138,7 +138,7 @@ void IRS::RunMomentProcessor(HLERequestContext& ctx) {
if (result.IsSuccess()) {
auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
- MakeProcessor<MomentProcessor>(parameters.camera_handle, device);
+ MakeProcessorWithCoreContext<MomentProcessor>(parameters.camera_handle, device);
auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle);
image_transfer_processor.SetConfig(parameters.processor_config);
npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h
index a8fa19025..c8e6dab17 100644
--- a/src/core/hle/service/hid/irs.h
+++ b/src/core/hle/service/hid/irs.h
@@ -3,15 +3,12 @@
#pragma once
+#include "core/core.h"
#include "core/hid/hid_types.h"
#include "core/hid/irs_types.h"
#include "core/hle/service/hid/irsensor/processor_base.h"
#include "core/hle/service/service.h"
-namespace Core {
-class System;
-}
-
namespace Core::HID {
class EmulatedController;
} // namespace Core::HID
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.cpp b/src/core/hle/service/hid/irsensor/clustering_processor.cpp
index e2f4ae876..c559eb0d5 100644
--- a/src/core/hle/service/hid/irsensor/clustering_processor.cpp
+++ b/src/core/hle/service/hid/irsensor/clustering_processor.cpp
@@ -3,16 +3,18 @@
#include <queue>
+#include "core/core.h"
+#include "core/core_timing.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/irsensor/clustering_processor.h"
namespace Service::IRS {
-ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_,
+ClusteringProcessor::ClusteringProcessor(Core::System& system_,
Core::IrSensor::DeviceFormat& device_format,
std::size_t npad_index)
- : device{device_format} {
- npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index);
+ : device{device_format}, system{system_} {
+ npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor;
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
@@ -48,7 +50,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
}
next_state = {};
- const auto camera_data = npad_device->GetCamera();
+ const auto& camera_data = npad_device->GetCamera();
auto filtered_image = camera_data.data;
RemoveLowIntensityData(filtered_image);
@@ -83,7 +85,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
}
next_state.sampling_number = camera_data.sample;
- next_state.timestamp = next_state.timestamp + 131;
+ next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
shared_memory->clustering_lifo.WriteNextEntry(next_state);
@@ -202,14 +204,14 @@ ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster(
}
u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
- if ((y * width) + x > data.size()) {
+ if ((y * width) + x >= data.size()) {
return 0;
}
return data[(y * width) + x];
}
void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) {
- if ((y * width) + x > data.size()) {
+ if ((y * width) + x >= data.size()) {
return;
}
data[(y * width) + x] = value;
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.h b/src/core/hle/service/hid/irsensor/clustering_processor.h
index dc01a8ea7..83f34734a 100644
--- a/src/core/hle/service/hid/irsensor/clustering_processor.h
+++ b/src/core/hle/service/hid/irsensor/clustering_processor.h
@@ -8,6 +8,10 @@
#include "core/hle/service/hid/irs_ring_lifo.h"
#include "core/hle/service/hid/irsensor/processor_base.h"
+namespace Core {
+class System;
+}
+
namespace Core::HID {
class EmulatedController;
} // namespace Core::HID
@@ -15,8 +19,7 @@ class EmulatedController;
namespace Service::IRS {
class ClusteringProcessor final : public ProcessorBase {
public:
- explicit ClusteringProcessor(Core::HID::HIDCore& hid_core_,
- Core::IrSensor::DeviceFormat& device_format,
+ explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
std::size_t npad_index);
~ClusteringProcessor() override;
@@ -106,5 +109,7 @@ private:
Core::IrSensor::DeviceFormat& device;
Core::HID::EmulatedController* npad_device;
int callback_key{};
+
+ Core::System& system;
};
} // namespace Service::IRS
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
index 803a6277c..22067a591 100644
--- a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
+++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
@@ -49,7 +49,7 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
return;
}
- const auto camera_data = npad_device->GetCamera();
+ const auto& camera_data = npad_device->GetCamera();
// This indicates how much ambient light is present
processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.cpp b/src/core/hle/service/hid/irsensor/moment_processor.cpp
index dbaca420a..cf045bda7 100644
--- a/src/core/hle/service/hid/irsensor/moment_processor.cpp
+++ b/src/core/hle/service/hid/irsensor/moment_processor.cpp
@@ -1,24 +1,137 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
+#include "core/core.h"
+#include "core/core_timing.h"
+#include "core/hid/emulated_controller.h"
+#include "core/hid/hid_core.h"
#include "core/hle/service/hid/irsensor/moment_processor.h"
namespace Service::IRS {
-MomentProcessor::MomentProcessor(Core::IrSensor::DeviceFormat& device_format)
- : device(device_format) {
+static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30;
+static constexpr std::size_t ImageWidth = 40;
+static constexpr std::size_t ImageHeight = 30;
+
+MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
+ std::size_t npad_index)
+ : device(device_format), system{system_} {
+ npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
+
device.mode = Core::IrSensor::IrSensorMode::MomentProcessor;
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped;
+
+ shared_memory = std::construct_at(
+ reinterpret_cast<MomentSharedMemory*>(&device_format.state.processor_raw_data));
+
+ Core::HID::ControllerUpdateCallback engine_callback{
+ .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); },
+ .is_npad_service = true,
+ };
+ callback_key = npad_device->SetCallback(engine_callback);
}
-MomentProcessor::~MomentProcessor() = default;
+MomentProcessor::~MomentProcessor() {
+ npad_device->DeleteCallback(callback_key);
+};
-void MomentProcessor::StartProcessor() {}
+void MomentProcessor::StartProcessor() {
+ device.camera_status = Core::IrSensor::IrCameraStatus::Available;
+ device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready;
+}
void MomentProcessor::SuspendProcessor() {}
void MomentProcessor::StopProcessor() {}
+void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) {
+ if (type != Core::HID::ControllerTriggerType::IrSensor) {
+ return;
+ }
+
+ next_state = {};
+ const auto& camera_data = npad_device->GetCamera();
+
+ const auto window_width = static_cast<std::size_t>(current_config.window_of_interest.width);
+ const auto window_height = static_cast<std::size_t>(current_config.window_of_interest.height);
+ const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x);
+ const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y);
+
+ const std::size_t block_width = window_width / Columns;
+ const std::size_t block_height = window_height / Rows;
+
+ for (std::size_t row = 0; row < Rows; row++) {
+ for (std::size_t column = 0; column < Columns; column++) {
+ const size_t x_pos = (column * block_width) + window_start_x;
+ const size_t y_pos = (row * block_height) + window_start_y;
+ auto& statistic = next_state.statistic[column + (row * Columns)];
+ statistic = GetStatistic(camera_data.data, x_pos, y_pos, block_width, block_height);
+ }
+ }
+
+ next_state.sampling_number = camera_data.sample;
+ next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
+ next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
+ shared_memory->moment_lifo.WriteNextEntry(next_state);
+
+ if (!IsProcessorActive()) {
+ StartProcessor();
+ }
+}
+
+u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
+ if ((y * ImageWidth) + x >= data.size()) {
+ return 0;
+ }
+ return data[(y * ImageWidth) + x];
+}
+
+MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector<u8>& data,
+ std::size_t start_x,
+ std::size_t start_y,
+ std::size_t width,
+ std::size_t height) const {
+ // The actual implementation is always 320x240
+ static constexpr std::size_t RealWidth = 320;
+ static constexpr std::size_t RealHeight = 240;
+ static constexpr std::size_t Threshold = 30;
+ MomentStatistic statistic{};
+ std::size_t active_points{};
+
+ // Sum all data points on the block that meet with the threshold
+ for (std::size_t y = 0; y < width; y++) {
+ for (std::size_t x = 0; x < height; x++) {
+ const size_t x_pos = x + start_x;
+ const size_t y_pos = y + start_y;
+ const auto pixel =
+ GetPixel(data, x_pos * ImageWidth / RealWidth, y_pos * ImageHeight / RealHeight);
+
+ if (pixel < Threshold) {
+ continue;
+ }
+
+ statistic.average_intensity += pixel;
+
+ statistic.centroid.x += static_cast<float>(x_pos);
+ statistic.centroid.y += static_cast<float>(y_pos);
+
+ active_points++;
+ }
+ }
+
+ // Return an empty field if no points were available
+ if (active_points == 0) {
+ return {};
+ }
+
+ // Finally calculate the actual centroid and average intensity
+ statistic.centroid.x /= static_cast<float>(active_points);
+ statistic.centroid.y /= static_cast<float>(active_points);
+ statistic.average_intensity /= static_cast<f32>(width * height);
+
+ return statistic;
+}
+
void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) {
current_config.camera_config.exposure_time = config.camera_config.exposure_time;
current_config.camera_config.gain = config.camera_config.gain;
@@ -29,6 +142,8 @@ void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig conf
current_config.preprocess =
static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
+
+ npad_device->SetCameraFormat(format);
}
} // namespace Service::IRS
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.h b/src/core/hle/service/hid/irsensor/moment_processor.h
index d4bd22e0f..398cfbdc1 100644
--- a/src/core/hle/service/hid/irsensor/moment_processor.h
+++ b/src/core/hle/service/hid/irsensor/moment_processor.h
@@ -6,12 +6,22 @@
#include "common/bit_field.h"
#include "common/common_types.h"
#include "core/hid/irs_types.h"
+#include "core/hle/service/hid/irs_ring_lifo.h"
#include "core/hle/service/hid/irsensor/processor_base.h"
+namespace Core {
+class System;
+}
+
+namespace Core::HID {
+class EmulatedController;
+} // namespace Core::HID
+
namespace Service::IRS {
class MomentProcessor final : public ProcessorBase {
public:
- explicit MomentProcessor(Core::IrSensor::DeviceFormat& device_format);
+ explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
+ std::size_t npad_index);
~MomentProcessor() override;
// Called when the processor is initialized
@@ -27,6 +37,9 @@ public:
void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config);
private:
+ static constexpr std::size_t Columns = 8;
+ static constexpr std::size_t Rows = 6;
+
// This is nn::irsensor::MomentProcessorConfig
struct MomentProcessorConfig {
Core::IrSensor::CameraConfig camera_config;
@@ -50,12 +63,29 @@ private:
u64 timestamp;
Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level;
INSERT_PADDING_BYTES(4);
- std::array<MomentStatistic, 0x30> stadistic;
+ std::array<MomentStatistic, Columns * Rows> statistic;
};
static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size");
+ struct MomentSharedMemory {
+ Service::IRS::Lifo<MomentProcessorState, 6> moment_lifo;
+ };
+ static_assert(sizeof(MomentSharedMemory) == 0xE20, "MomentSharedMemory is an invalid size");
+
+ void OnControllerUpdate(Core::HID::ControllerTriggerType type);
+ u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const;
+ MomentStatistic GetStatistic(const std::vector<u8>& data, std::size_t start_x,
+ std::size_t start_y, std::size_t width, std::size_t height) const;
+
+ MomentSharedMemory* shared_memory = nullptr;
+ MomentProcessorState next_state{};
+
MomentProcessorConfig current_config{};
Core::IrSensor::DeviceFormat& device;
+ Core::HID::EmulatedController* npad_device;
+ int callback_key{};
+
+ Core::System& system;
};
} // namespace Service::IRS
diff --git a/src/core/hle/service/hid/resource_manager.cpp b/src/core/hle/service/hid/resource_manager.cpp
new file mode 100644
index 000000000..d6f42c646
--- /dev/null
+++ b/src/core/hle/service/hid/resource_manager.cpp
@@ -0,0 +1,184 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "common/logging/log.h"
+#include "core/core.h"
+#include "core/core_timing.h"
+#include "core/hid/hid_core.h"
+#include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/service/hid/resource_manager.h"
+#include "core/hle/service/ipc_helpers.h"
+
+#include "core/hle/service/hid/controllers/console_sixaxis.h"
+#include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/hid/controllers/debug_pad.h"
+#include "core/hle/service/hid/controllers/gesture.h"
+#include "core/hle/service/hid/controllers/keyboard.h"
+#include "core/hle/service/hid/controllers/mouse.h"
+#include "core/hle/service/hid/controllers/npad.h"
+#include "core/hle/service/hid/controllers/palma.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 {
+
+// Updating period for each HID device.
+// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
+// Correct npad_update_ns is 4ms this is overclocked to lower input lag
+constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
+constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
+constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
+constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
+
+ResourceManager::ResourceManager(Core::System& system_)
+ : system{system_}, service_context{system_, "hid"} {}
+
+ResourceManager::~ResourceManager() = default;
+
+void ResourceManager::Initialize() {
+ if (is_initialized) {
+ return;
+ }
+
+ u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
+ MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory);
+ MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory);
+ MakeController<Controller_Mouse>(HidController::Mouse, shared_memory);
+ MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory);
+ MakeController<Controller_XPad>(HidController::XPad, shared_memory);
+ MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory);
+ MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory);
+ MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory);
+ MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory);
+ MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory);
+ MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory);
+ MakeController<Controller_Gesture>(HidController::Gesture, shared_memory);
+ MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);
+ MakeController<Controller_Stubbed>(HidController::DebugMouse, shared_memory);
+ MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory);
+
+ // Homebrew doesn't try to activate some controllers, so we activate them by default
+ GetController<Controller_NPad>(HidController::NPad).Activate();
+ GetController<Controller_Touchscreen>(HidController::Touchscreen).Activate();
+
+ GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
+ GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
+ GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
+ GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
+ GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
+ GetController<Controller_Stubbed>(HidController::DebugMouse).SetCommonHeaderOffset(0x3DC00);
+
+ system.HIDCore().ReloadInputDevices();
+ is_initialized = true;
+}
+
+void ResourceManager::UpdateControllers(std::uintptr_t user_data,
+ std::chrono::nanoseconds ns_late) {
+ auto& core_timing = system.CoreTiming();
+
+ for (const auto& controller : controllers) {
+ // Keyboard has it's own update event
+ if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
+ continue;
+ }
+ // Mouse has it's own update event
+ if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
+ continue;
+ }
+ // Npad has it's own update event
+ if (controller == controllers[static_cast<size_t>(HidController::NPad)]) {
+ continue;
+ }
+ controller->OnUpdate(core_timing);
+ }
+}
+
+void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+ auto& core_timing = system.CoreTiming();
+
+ controllers[static_cast<size_t>(HidController::NPad)]->OnUpdate(core_timing);
+}
+
+void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
+ std::chrono::nanoseconds ns_late) {
+ auto& core_timing = system.CoreTiming();
+
+ controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing);
+ controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);
+}
+
+void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+ auto& core_timing = system.CoreTiming();
+
+ controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);
+}
+
+IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource)
+ : ServiceFramework{system_, "IAppletResource"} {
+ static const FunctionInfo functions[] = {
+ {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
+ };
+ RegisterHandlers(functions);
+
+ resource->Initialize();
+
+ // Register update callbacks
+ npad_update_event = Core::Timing::CreateEvent(
+ "HID::UpdatePadCallback",
+ [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
+ -> std::optional<std::chrono::nanoseconds> {
+ const auto guard = LockService();
+ resource->UpdateNpad(user_data, ns_late);
+ return std::nullopt;
+ });
+ default_update_event = Core::Timing::CreateEvent(
+ "HID::UpdateDefaultCallback",
+ [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
+ -> std::optional<std::chrono::nanoseconds> {
+ const auto guard = LockService();
+ resource->UpdateControllers(user_data, ns_late);
+ return std::nullopt;
+ });
+ mouse_keyboard_update_event = Core::Timing::CreateEvent(
+ "HID::UpdateMouseKeyboardCallback",
+ [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
+ -> std::optional<std::chrono::nanoseconds> {
+ const auto guard = LockService();
+ resource->UpdateMouseKeyboard(user_data, ns_late);
+ return std::nullopt;
+ });
+ motion_update_event = Core::Timing::CreateEvent(
+ "HID::UpdateMotionCallback",
+ [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
+ -> std::optional<std::chrono::nanoseconds> {
+ const auto guard = LockService();
+ resource->UpdateMotion(user_data, ns_late);
+ return std::nullopt;
+ });
+
+ system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
+ system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
+ default_update_event);
+ system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
+ mouse_keyboard_update_event);
+ system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
+ motion_update_event);
+}
+
+IAppletResource::~IAppletResource() {
+ system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
+ system.CoreTiming().UnscheduleEvent(default_update_event, 0);
+ system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
+ system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
+}
+
+void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_HID, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(&system.Kernel().GetHidSharedMem());
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/resource_manager.h b/src/core/hle/service/hid/resource_manager.h
new file mode 100644
index 000000000..34dbf36bc
--- /dev/null
+++ b/src/core/hle/service/hid/resource_manager.h
@@ -0,0 +1,104 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <chrono>
+
+#include "core/core.h"
+#include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Core::Timing {
+struct EventType;
+}
+
+namespace Core::HID {
+class HIDCore;
+}
+
+namespace Service::HID {
+
+enum class HidController : std::size_t {
+ DebugPad,
+ Touchscreen,
+ Mouse,
+ Keyboard,
+ XPad,
+ HomeButton,
+ SleepButton,
+ CaptureButton,
+ InputDetector,
+ UniquePad,
+ NPad,
+ Gesture,
+ ConsoleSixAxisSensor,
+ DebugMouse,
+ Palma,
+
+ MaxControllers,
+};
+class ResourceManager {
+public:
+ explicit ResourceManager(Core::System& system_);
+ ~ResourceManager();
+
+ template <typename T>
+ T& GetController(HidController controller) {
+ return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
+ }
+
+ template <typename T>
+ const T& GetController(HidController controller) const {
+ return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
+ }
+
+ void Initialize();
+
+ void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+ void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+ void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+ void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+
+private:
+ template <typename T>
+ void MakeController(HidController controller, u8* shared_memory) {
+ if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
+ controllers[static_cast<std::size_t>(controller)] =
+ std::make_unique<T>(system, shared_memory);
+ } else {
+ controllers[static_cast<std::size_t>(controller)] =
+ std::make_unique<T>(system.HIDCore(), shared_memory);
+ }
+ }
+
+ template <typename T>
+ void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
+ controllers[static_cast<std::size_t>(controller)] =
+ std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
+ }
+
+ bool is_initialized{false};
+ std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
+ controllers{};
+
+ Core::System& system;
+ KernelHelpers::ServiceContext service_context;
+};
+
+class IAppletResource final : public ServiceFramework<IAppletResource> {
+public:
+ explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource);
+ ~IAppletResource() override;
+
+private:
+ void GetSharedMemoryHandle(HLERequestContext& ctx);
+
+ std::shared_ptr<Core::Timing::EventType> npad_update_event;
+ std::shared_ptr<Core::Timing::EventType> default_update_event;
+ std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
+ std::shared_ptr<Core::Timing::EventType> motion_update_event;
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
index 65eb7ea02..0816784e0 100644
--- a/src/core/hle/service/hid/ring_lifo.h
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -32,15 +32,15 @@ struct Lifo {
}
std::size_t GetPreviousEntryIndex() const {
- return static_cast<size_t>((buffer_tail + total_buffer_count - 1) % total_buffer_count);
+ return static_cast<size_t>((buffer_tail + max_buffer_size - 1) % max_buffer_size);
}
std::size_t GetNextEntryIndex() const {
- return static_cast<size_t>((buffer_tail + 1) % total_buffer_count);
+ return static_cast<size_t>((buffer_tail + 1) % max_buffer_size);
}
void WriteNextEntry(const State& new_state) {
- if (buffer_count < total_buffer_count - 1) {
+ if (buffer_count < static_cast<s64>(max_buffer_size) - 1) {
buffer_count++;
}
buffer_tail = GetNextEntryIndex();
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index c73035c77..97b6a9385 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -286,9 +286,14 @@ public:
rb.Push(ResultSuccess);
}
- bool ValidateRegionForMap(Kernel::KPageTable& page_table, VAddr start, std::size_t size) const {
+ bool ValidateRegionForMap(Kernel::KProcessPageTable& page_table, VAddr start,
+ std::size_t size) const {
const std::size_t padding_size{page_table.GetNumGuardPages() * Kernel::PageSize};
- const auto start_info{page_table.QueryInfo(start - 1)};
+
+ Kernel::KMemoryInfo start_info;
+ Kernel::Svc::PageInfo page_info;
+ R_ASSERT(
+ page_table.QueryInfo(std::addressof(start_info), std::addressof(page_info), start - 1));
if (start_info.GetState() != Kernel::KMemoryState::Free) {
return {};
@@ -298,7 +303,9 @@ public:
return {};
}
- const auto end_info{page_table.QueryInfo(start + size)};
+ Kernel::KMemoryInfo end_info;
+ R_ASSERT(page_table.QueryInfo(std::addressof(end_info), std::addressof(page_info),
+ start + size));
if (end_info.GetState() != Kernel::KMemoryState::Free) {
return {};
@@ -307,7 +314,7 @@ public:
return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize());
}
- Result GetAvailableMapRegion(Kernel::KPageTable& page_table, u64 size, VAddr& out_addr) {
+ Result GetAvailableMapRegion(Kernel::KProcessPageTable& page_table, u64 size, VAddr& out_addr) {
size = Common::AlignUp(size, Kernel::PageSize);
size += page_table.GetNumGuardPages() * Kernel::PageSize * 4;
@@ -391,12 +398,8 @@ public:
if (bss_size) {
auto block_guard = detail::ScopeExit([&] {
- page_table.UnmapCodeMemory(
- addr + nro_size, bss_addr, bss_size,
- Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange);
- page_table.UnmapCodeMemory(
- addr, nro_addr, nro_size,
- Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange);
+ page_table.UnmapCodeMemory(addr + nro_size, bss_addr, bss_size);
+ page_table.UnmapCodeMemory(addr, nro_addr, nro_size);
});
const Result result{page_table.MapCodeMemory(addr + nro_size, bss_addr, bss_size)};
@@ -578,21 +581,17 @@ public:
auto& page_table{system.ApplicationProcess()->GetPageTable()};
if (info.bss_size != 0) {
- R_TRY(page_table.UnmapCodeMemory(
- info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address,
- info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
+ R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size +
+ info.data_size,
+ info.bss_address, info.bss_size));
}
- R_TRY(page_table.UnmapCodeMemory(
- info.nro_address + info.text_size + info.ro_size,
- info.src_addr + info.text_size + info.ro_size, info.data_size,
- Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
- R_TRY(page_table.UnmapCodeMemory(
- info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size,
- Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
- R_TRY(page_table.UnmapCodeMemory(
- info.nro_address, info.src_addr, info.text_size,
- Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
+ R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size,
+ info.src_addr + info.text_size + info.ro_size,
+ info.data_size));
+ R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size,
+ info.src_addr + info.text_size, info.ro_size));
+ R_TRY(page_table.UnmapCodeMemory(info.nro_address, info.src_addr, info.text_size));
return ResultSuccess;
}
diff --git a/src/core/hle/service/nvdrv/devices/ioctl_serialization.h b/src/core/hle/service/nvdrv/devices/ioctl_serialization.h
new file mode 100644
index 000000000..b12bcd138
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/ioctl_serialization.h
@@ -0,0 +1,159 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <span>
+#include <vector>
+
+#include "common/concepts.h"
+#include "core/hle/service/nvdrv/devices/nvdevice.h"
+
+namespace Service::Nvidia::Devices {
+
+struct IoctlOneArgTraits {
+ template <typename T, typename R, typename A, typename... B>
+ static A GetFirstArgImpl(R (T::*)(A, B...));
+};
+
+struct IoctlTwoArgTraits {
+ template <typename T, typename R, typename A, typename B, typename... C>
+ static A GetFirstArgImpl(R (T::*)(A, B, C...));
+
+ template <typename T, typename R, typename A, typename B, typename... C>
+ static B GetSecondArgImpl(R (T::*)(A, B, C...));
+};
+
+struct Null {};
+
+// clang-format off
+
+template <typename FixedArg, typename VarArg, typename InlInVarArg, typename InlOutVarArg, typename F>
+NvResult WrapGeneric(F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, std::span<u8> inline_output) {
+ constexpr bool HasFixedArg = !std::is_same_v<FixedArg, Null>;
+ constexpr bool HasVarArg = !std::is_same_v<VarArg, Null>;
+ constexpr bool HasInlInVarArg = !std::is_same_v<InlInVarArg, Null>;
+ constexpr bool HasInlOutVarArg = !std::is_same_v<InlOutVarArg, Null>;
+
+ // Declare the fixed-size input value.
+ FixedArg fixed{};
+ size_t var_offset = 0;
+
+ if constexpr (HasFixedArg) {
+ // Read the fixed-size input value.
+ var_offset = std::min(sizeof(FixedArg), input.size());
+ if (var_offset > 0) {
+ std::memcpy(&fixed, input.data(), var_offset);
+ }
+ }
+
+ // Read the variable-sized inputs.
+ const size_t num_var_args = HasVarArg ? ((input.size() - var_offset) / sizeof(VarArg)) : 0;
+ std::vector<VarArg> var_args(num_var_args);
+ if constexpr (HasVarArg) {
+ if (num_var_args > 0) {
+ std::memcpy(var_args.data(), input.data() + var_offset, num_var_args * sizeof(VarArg));
+ }
+ }
+
+ const size_t num_inl_in_var_args = HasInlInVarArg ? (inline_input.size() / sizeof(InlInVarArg)) : 0;
+ std::vector<InlInVarArg> inl_in_var_args(num_inl_in_var_args);
+ if constexpr (HasInlInVarArg) {
+ if (num_inl_in_var_args > 0) {
+ std::memcpy(inl_in_var_args.data(), inline_input.data(), num_inl_in_var_args * sizeof(InlInVarArg));
+ }
+ }
+
+ // Construct inline output data.
+ const size_t num_inl_out_var_args = HasInlOutVarArg ? (inline_output.size() / sizeof(InlOutVarArg)) : 0;
+ std::vector<InlOutVarArg> inl_out_var_args(num_inl_out_var_args);
+
+ // Perform the call.
+ NvResult result = callable(fixed, var_args, inl_in_var_args, inl_out_var_args);
+
+ // Copy outputs.
+ if constexpr (HasFixedArg) {
+ if (output.size() > 0) {
+ std::memcpy(output.data(), &fixed, std::min(output.size(), sizeof(FixedArg)));
+ }
+ }
+
+ if constexpr (HasVarArg) {
+ if (num_var_args > 0 && output.size() > var_offset) {
+ const size_t max_var_size = output.size() - var_offset;
+ std::memcpy(output.data() + var_offset, var_args.data(), std::min(max_var_size, num_var_args * sizeof(VarArg)));
+ }
+ }
+
+ // Copy inline outputs.
+ if constexpr (HasInlOutVarArg) {
+ if (num_inl_out_var_args > 0) {
+ std::memcpy(inline_output.data(), inl_out_var_args.data(), num_inl_out_var_args * sizeof(InlOutVarArg));
+ }
+ }
+
+ // We're done.
+ return result;
+}
+
+template <typename Self, typename F, typename... Rest>
+NvResult WrapFixed(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) {
+ using FixedArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>;
+
+ const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
+ return (self->*callable)(fixed, std::forward<Rest>(rest)...);
+ };
+
+ return WrapGeneric<FixedArg, Null, Null, Null>(std::move(Callable), input, {}, output, {});
+}
+
+template <typename Self, typename F, typename... Rest>
+NvResult WrapFixedInlOut(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, std::span<u8> inline_output, Rest&&... rest) {
+ using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>;
+ using InlOutVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type;
+
+ const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
+ return (self->*callable)(fixed, inl_out, std::forward<Rest>(rest)...);
+ };
+
+ return WrapGeneric<FixedArg, Null, Null, InlOutVarArg>(std::move(Callable), input, {}, output, inline_output);
+}
+
+template <typename Self, typename F, typename... Rest>
+NvResult WrapVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) {
+ using VarArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>::value_type;
+
+ const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
+ return (self->*callable)(var, std::forward<Rest>(rest)...);
+ };
+
+ return WrapGeneric<Null, VarArg, Null, Null>(std::move(Callable), input, {}, output, {});
+}
+
+template <typename Self, typename F, typename... Rest>
+NvResult WrapFixedVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) {
+ using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>;
+ using VarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type;
+
+ const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
+ return (self->*callable)(fixed, var, std::forward<Rest>(rest)...);
+ };
+
+ return WrapGeneric<FixedArg, VarArg, Null, Null>(std::move(Callable), input, {}, output, {});
+}
+
+template <typename Self, typename F, typename... Rest>
+NvResult WrapFixedInlIn(Self* self, F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, Rest&&... rest) {
+ using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>;
+ using InlInVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type;
+
+ const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
+ return (self->*callable)(fixed, inl_in, std::forward<Rest>(rest)...);
+ };
+
+ return WrapGeneric<FixedArg, Null, InlInVarArg, Null>(std::move(Callable), input, inline_input, output, {});
+}
+
+// clang-format on
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 7d7bb8687..6b3639008 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -11,6 +11,7 @@
#include "core/core.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
#include "core/hle/service/nvdrv/nvdrv.h"
@@ -33,21 +34,21 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> i
case 'A':
switch (command.cmd) {
case 0x1:
- return BindChannel(input, output);
+ return WrapFixed(this, &nvhost_as_gpu::BindChannel, input, output);
case 0x2:
- return AllocateSpace(input, output);
+ return WrapFixed(this, &nvhost_as_gpu::AllocateSpace, input, output);
case 0x3:
- return FreeSpace(input, output);
+ return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output);
case 0x5:
- return UnmapBuffer(input, output);
+ return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output);
case 0x6:
- return MapBufferEx(input, output);
+ return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output);
case 0x8:
- return GetVARegions(input, output);
+ return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output);
case 0x9:
- return AllocAsEx(input, output);
+ return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output);
case 0x14:
- return Remap(input, output);
+ return WrapVariable(this, &nvhost_as_gpu::Remap, input, output);
default:
break;
}
@@ -72,7 +73,8 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
case 'A':
switch (command.cmd) {
case 0x8:
- return GetVARegions(input, output, inline_output);
+ return WrapFixedInlOut(this, &nvhost_as_gpu::GetVARegions3, input, output,
+ inline_output);
default:
break;
}
@@ -87,10 +89,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
void nvhost_as_gpu::OnOpen(DeviceFD fd) {}
void nvhost_as_gpu::OnClose(DeviceFD fd) {}
-NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> output) {
- IoctlAllocAsEx params{};
- std::memcpy(&params, input.data(), input.size());
-
+NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size);
std::scoped_lock lock(mutex);
@@ -141,10 +140,7 @@ NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> outpu
return NvResult::Success;
}
-NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> output) {
- IoctlAllocSpace params{};
- std::memcpy(&params, input.data(), input.size());
-
+NvResult nvhost_as_gpu::AllocateSpace(IoctlAllocSpace& params) {
LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages,
params.page_size, params.flags);
@@ -194,7 +190,6 @@ NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> o
.big_pages = params.page_size != VM::YUZU_PAGESIZE,
};
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
@@ -222,10 +217,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {
mapping_map.erase(offset);
}
-NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> output) {
- IoctlFreeSpace params{};
- std::memcpy(&params, input.data(), input.size());
-
+NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) {
LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset,
params.pages, params.page_size);
@@ -264,18 +256,11 @@ NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> outpu
return NvResult::BadValue;
}
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) {
- const auto num_entries = input.size() / sizeof(IoctlRemapEntry);
-
- LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries);
-
- std::scoped_lock lock(mutex);
- entries.resize_destructive(num_entries);
- std::memcpy(entries.data(), input.data(), input.size());
+NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
+ LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size());
if (!vm.initialised) {
return NvResult::BadValue;
@@ -317,14 +302,10 @@ NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) {
}
}
- std::memcpy(output.data(), entries.data(), output.size());
return NvResult::Success;
}
-NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> output) {
- IoctlMapBufferEx params{};
- std::memcpy(&params, input.data(), input.size());
-
+NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
LOG_DEBUG(Service_NVDRV,
"called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
", offset={}",
@@ -421,14 +402,10 @@ NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> out
mapping_map[params.offset] = mapping;
}
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> output) {
- IoctlUnmapBuffer params{};
- std::memcpy(&params, input.data(), input.size());
-
+NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
std::scoped_lock lock(mutex);
@@ -464,9 +441,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> out
return NvResult::Success;
}
-NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::span<u8> output) {
- IoctlBindChannel params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_as_gpu::BindChannel(IoctlBindChannel& params) {
LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
auto gpu_channel_device = module.GetDevice<nvhost_gpu>(params.fd);
@@ -493,10 +468,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) {
};
}
-NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output) {
- IoctlGetVaRegions params{};
- std::memcpy(&params, input.data(), input.size());
-
+NvResult nvhost_as_gpu::GetVARegions1(IoctlGetVaRegions& params) {
LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr,
params.buf_size);
@@ -508,15 +480,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou
GetVARegionsImpl(params);
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output,
- std::span<u8> inline_output) {
- IoctlGetVaRegions params{};
- std::memcpy(&params, input.data(), input.size());
-
+NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions) {
LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr,
params.buf_size);
@@ -528,9 +495,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou
GetVARegionsImpl(params);
- std::memcpy(output.data(), &params, output.size());
- std::memcpy(inline_output.data(), &params.regions[0], sizeof(VaRegion));
- std::memcpy(inline_output.data() + sizeof(VaRegion), &params.regions[1], sizeof(VaRegion));
+ const size_t num_regions = std::min(params.regions.size(), regions.size());
+ for (size_t i = 0; i < num_regions; i++) {
+ regions[i] = params.regions[i];
+ }
return NvResult::Success;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index 2af3e1260..932997e75 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -139,18 +139,17 @@ private:
static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2,
"IoctlGetVaRegions is incorrect size");
- NvResult AllocAsEx(std::span<const u8> input, std::span<u8> output);
- NvResult AllocateSpace(std::span<const u8> input, std::span<u8> output);
- NvResult Remap(std::span<const u8> input, std::span<u8> output);
- NvResult MapBufferEx(std::span<const u8> input, std::span<u8> output);
- NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output);
- NvResult FreeSpace(std::span<const u8> input, std::span<u8> output);
- NvResult BindChannel(std::span<const u8> input, std::span<u8> output);
+ NvResult AllocAsEx(IoctlAllocAsEx& params);
+ NvResult AllocateSpace(IoctlAllocSpace& params);
+ NvResult Remap(std::span<IoctlRemapEntry> params);
+ NvResult MapBufferEx(IoctlMapBufferEx& params);
+ NvResult UnmapBuffer(IoctlUnmapBuffer& params);
+ NvResult FreeSpace(IoctlFreeSpace& params);
+ NvResult BindChannel(IoctlBindChannel& params);
void GetVARegionsImpl(IoctlGetVaRegions& params);
- NvResult GetVARegions(std::span<const u8> input, std::span<u8> output);
- NvResult GetVARegions(std::span<const u8> input, std::span<u8> output,
- std::span<u8> inline_output);
+ NvResult GetVARegions1(IoctlGetVaRegions& params);
+ NvResult GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions);
void FreeMappingLocked(u64 offset);
@@ -213,7 +212,6 @@ private:
bool initialised{};
} vm;
std::shared_ptr<Tegra::MemoryManager> gmmu;
- Common::ScratchBuffer<IoctlRemapEntry> entries;
// s32 channel{};
// u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 4d55554b4..b8dd34e24 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -14,6 +14,7 @@
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
#include "video_core/gpu.h"
#include "video_core/host1x/host1x.h"
@@ -40,19 +41,19 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inp
case 0x0:
switch (command.cmd) {
case 0x1b:
- return NvOsGetConfigU32(input, output);
+ return WrapFixed(this, &nvhost_ctrl::NvOsGetConfigU32, input, output);
case 0x1c:
- return IocCtrlClearEventWait(input, output);
+ return WrapFixed(this, &nvhost_ctrl::IocCtrlClearEventWait, input, output);
case 0x1d:
- return IocCtrlEventWait(input, output, true);
+ return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, true);
case 0x1e:
- return IocCtrlEventWait(input, output, false);
+ return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, false);
case 0x1f:
- return IocCtrlEventRegister(input, output);
+ return WrapFixed(this, &nvhost_ctrl::IocCtrlEventRegister, input, output);
case 0x20:
- return IocCtrlEventUnregister(input, output);
+ return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregister, input, output);
case 0x21:
- return IocCtrlEventUnregisterBatch(input, output);
+ return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregisterBatch, input, output);
}
break;
default:
@@ -79,25 +80,19 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {}
void nvhost_ctrl::OnClose(DeviceFD fd) {}
-NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output) {
- IocGetConfigParams params{};
- std::memcpy(&params, input.data(), sizeof(params));
+NvResult nvhost_ctrl::NvOsGetConfigU32(IocGetConfigParams& params) {
LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
params.param_str.data());
return NvResult::ConfigVarNotFound; // Returns error on production mode
}
-NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::span<u8> output,
- bool is_allocation) {
- IocCtrlEventWaitParams params{};
- std::memcpy(&params, input.data(), sizeof(params));
+NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation) {
LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}",
params.fence.id, params.fence.value, params.timeout, is_allocation);
bool must_unmark_fail = !is_allocation;
const u32 event_id = params.value.raw;
SCOPE_EXIT({
- std::memcpy(output.data(), &params, sizeof(params));
if (must_unmark_fail) {
events[event_id].fails = 0;
}
@@ -231,9 +226,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) {
return NvResult::Success;
}
-NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output) {
- IocCtrlEventRegisterParams params{};
- std::memcpy(&params, input.data(), sizeof(params));
+NvResult nvhost_ctrl::IocCtrlEventRegister(IocCtrlEventRegisterParams& params) {
const u32 event_id = params.user_event_id;
LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id);
if (event_id >= MaxNvEvents) {
@@ -252,9 +245,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<
return NvResult::Success;
}
-NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output) {
- IocCtrlEventUnregisterParams params{};
- std::memcpy(&params, input.data(), sizeof(params));
+NvResult nvhost_ctrl::IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params) {
const u32 event_id = params.user_event_id & 0x00FF;
LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id);
@@ -262,9 +253,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::spa
return FreeEvent(event_id);
}
-NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output) {
- IocCtrlEventUnregisterBatchParams params{};
- std::memcpy(&params, input.data(), sizeof(params));
+NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params) {
u64 event_mask = params.user_events;
LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask);
@@ -280,10 +269,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std
return NvResult::Success;
}
-NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output) {
- IocCtrlEventClearParams params{};
- std::memcpy(&params, input.data(), sizeof(params));
-
+NvResult nvhost_ctrl::IocCtrlClearEventWait(IocCtrlEventClearParams& params) {
u32 event_id = params.event_id.slot;
LOG_DEBUG(Service_NVDRV, "called, event_id: {:X}", event_id);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 2efed4862..992124b60 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -186,12 +186,12 @@ private:
static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8,
"IocCtrlEventKill is incorrect size");
- NvResult NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output);
- NvResult IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation);
- NvResult IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output);
- NvResult IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output);
- NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output);
- NvResult IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output);
+ NvResult NvOsGetConfigU32(IocGetConfigParams& params);
+ NvResult IocCtrlEventRegister(IocCtrlEventRegisterParams& params);
+ NvResult IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params);
+ NvResult IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params);
+ NvResult IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation);
+ NvResult IocCtrlClearEventWait(IocCtrlEventClearParams& params);
NvResult FreeEvent(u32 slot);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 6081d92e9..61a2df121 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -6,6 +6,7 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/core_timing.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
#include "core/hle/service/nvdrv/nvdrv.h"
@@ -27,23 +28,23 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8>
case 'G':
switch (command.cmd) {
case 0x1:
- return ZCullGetCtxSize(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetCtxSize, input, output);
case 0x2:
- return ZCullGetInfo(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetInfo, input, output);
case 0x3:
- return ZBCSetTable(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::ZBCSetTable, input, output);
case 0x4:
- return ZBCQueryTable(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::ZBCQueryTable, input, output);
case 0x5:
- return GetCharacteristics(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::GetCharacteristics1, input, output);
case 0x6:
- return GetTPCMasks(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::GetTPCMasks1, input, output);
case 0x7:
- return FlushL2(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::FlushL2, input, output);
case 0x14:
- return GetActiveSlotMask(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::GetActiveSlotMask, input, output);
case 0x1c:
- return GetGpuTime(input, output);
+ return WrapFixed(this, &nvhost_ctrl_gpu::GetGpuTime, input, output);
default:
break;
}
@@ -65,9 +66,11 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
case 'G':
switch (command.cmd) {
case 0x5:
- return GetCharacteristics(input, output, inline_output);
+ return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetCharacteristics3, input, output,
+ inline_output);
case 0x6:
- return GetTPCMasks(input, output, inline_output);
+ return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetTPCMasks3, input, output,
+ inline_output);
default:
break;
}
@@ -82,10 +85,8 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {}
void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {}
-NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) {
LOG_DEBUG(Service_NVDRV, "called");
- IoctlCharacteristics params{};
- std::memcpy(&params, input.data(), input.size());
params.gc.arch = 0x120;
params.gc.impl = 0xb;
params.gc.rev = 0xa1;
@@ -123,15 +124,13 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa
params.gc.gr_compbit_store_base_hw = 0x0;
params.gpu_characteristics_buf_size = 0xA0;
params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output,
- std::span<u8> inline_output) {
+NvResult nvhost_ctrl_gpu::GetCharacteristics3(
+ IoctlCharacteristics& params, std::span<IoctlGpuCharacteristics> gpu_characteristics) {
LOG_DEBUG(Service_NVDRV, "called");
- IoctlCharacteristics params{};
- std::memcpy(&params, input.data(), input.size());
+
params.gc.arch = 0x120;
params.gc.impl = 0xb;
params.gc.rev = 0xa1;
@@ -169,70 +168,47 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa
params.gc.gr_compbit_store_base_hw = 0x0;
params.gpu_characteristics_buf_size = 0xA0;
params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
-
- std::memcpy(output.data(), &params, output.size());
- std::memcpy(inline_output.data(), &params.gc, inline_output.size());
+ if (!gpu_characteristics.empty()) {
+ gpu_characteristics.front() = params.gc;
+ }
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output) {
- IoctlGpuGetTpcMasksArgs params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) {
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
if (params.mask_buffer_size != 0) {
params.tcp_mask = 3;
}
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output,
- std::span<u8> inline_output) {
- IoctlGpuGetTpcMasksArgs params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask) {
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
if (params.mask_buffer_size != 0) {
params.tcp_mask = 3;
}
- std::memcpy(output.data(), &params, output.size());
- std::memcpy(inline_output.data(), &params.tcp_mask, inline_output.size());
+ if (!tpc_mask.empty()) {
+ tpc_mask.front() = params.tcp_mask;
+ }
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::GetActiveSlotMask(IoctlActiveSlotMask& params) {
LOG_DEBUG(Service_NVDRV, "called");
- IoctlActiveSlotMask params{};
- if (input.size() > 0) {
- std::memcpy(&params, input.data(), input.size());
- }
params.slot = 0x07;
params.mask = 0x01;
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(IoctlZcullGetCtxSize& params) {
LOG_DEBUG(Service_NVDRV, "called");
-
- IoctlZcullGetCtxSize params{};
- if (input.size() > 0) {
- std::memcpy(&params, input.data(), input.size());
- }
params.size = 0x1;
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) {
LOG_DEBUG(Service_NVDRV, "called");
-
- IoctlNvgpuGpuZcullGetInfoArgs params{};
-
- if (input.size() > 0) {
- std::memcpy(&params, input.data(), input.size());
- }
-
params.width_align_pixels = 0x20;
params.height_align_pixels = 0x20;
params.pixel_squares_by_aliquots = 0x400;
@@ -243,53 +219,28 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8>
params.subregion_width_align_pixels = 0x20;
params.subregion_height_align_pixels = 0x40;
params.subregion_count = 0x10;
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
-
- IoctlZbcSetTable params{};
- std::memcpy(&params, input.data(), input.size());
// TODO(ogniK): What does this even actually do?
-
- // Prevent null pointer being passed as arg 1
- if (output.empty()) {
- LOG_WARNING(Service_NVDRV, "Avoiding passing null pointer to memcpy");
- } else {
- std::memcpy(output.data(), &params, output.size());
- }
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
-
- IoctlZbcQueryTable params{};
- std::memcpy(&params, input.data(), input.size());
- // TODO : To implement properly
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
-
- IoctlFlushL2 params{};
- std::memcpy(&params, input.data(), input.size());
- // TODO : To implement properly
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_ctrl_gpu::GetGpuTime(IoctlGetGpuTime& params) {
LOG_DEBUG(Service_NVDRV, "called");
-
- IoctlGetGpuTime params{};
- std::memcpy(&params, input.data(), input.size());
params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count());
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
index 97995551c..d170299bd 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -151,21 +151,20 @@ private:
};
static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size");
- NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output);
- NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output,
- std::span<u8> inline_output);
-
- NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output);
- NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output,
- std::span<u8> inline_output);
-
- NvResult GetActiveSlotMask(std::span<const u8> input, std::span<u8> output);
- NvResult ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output);
- NvResult ZCullGetInfo(std::span<const u8> input, std::span<u8> output);
- NvResult ZBCSetTable(std::span<const u8> input, std::span<u8> output);
- NvResult ZBCQueryTable(std::span<const u8> input, std::span<u8> output);
- NvResult FlushL2(std::span<const u8> input, std::span<u8> output);
- NvResult GetGpuTime(std::span<const u8> input, std::span<u8> output);
+ NvResult GetCharacteristics1(IoctlCharacteristics& params);
+ NvResult GetCharacteristics3(IoctlCharacteristics& params,
+ std::span<IoctlGpuCharacteristics> gpu_characteristics);
+
+ NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params);
+ NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask);
+
+ NvResult GetActiveSlotMask(IoctlActiveSlotMask& params);
+ NvResult ZCullGetCtxSize(IoctlZcullGetCtxSize& params);
+ NvResult ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params);
+ NvResult ZBCSetTable(IoctlZbcSetTable& params);
+ NvResult ZBCQueryTable(IoctlZbcQueryTable& params);
+ NvResult FlushL2(IoctlFlushL2& params);
+ NvResult GetGpuTime(IoctlGetGpuTime& params);
EventInterface& events_interface;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 46a25fcab..b0395c2f0 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -8,6 +8,7 @@
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/memory.h"
@@ -52,7 +53,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
case 0x0:
switch (command.cmd) {
case 0x3:
- return GetWaitbase(input, output);
+ return WrapFixed(this, &nvhost_gpu::GetWaitbase, input, output);
default:
break;
}
@@ -60,25 +61,25 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
case 'H':
switch (command.cmd) {
case 0x1:
- return SetNVMAPfd(input, output);
+ return WrapFixed(this, &nvhost_gpu::SetNVMAPfd, input, output);
case 0x3:
- return ChannelSetTimeout(input, output);
+ return WrapFixed(this, &nvhost_gpu::ChannelSetTimeout, input, output);
case 0x8:
- return SubmitGPFIFOBase(input, output, false);
+ return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, false);
case 0x9:
- return AllocateObjectContext(input, output);
+ return WrapFixed(this, &nvhost_gpu::AllocateObjectContext, input, output);
case 0xb:
- return ZCullBind(input, output);
+ return WrapFixed(this, &nvhost_gpu::ZCullBind, input, output);
case 0xc:
- return SetErrorNotifier(input, output);
+ return WrapFixed(this, &nvhost_gpu::SetErrorNotifier, input, output);
case 0xd:
- return SetChannelPriority(input, output);
+ return WrapFixed(this, &nvhost_gpu::SetChannelPriority, input, output);
case 0x1a:
- return AllocGPFIFOEx2(input, output);
+ return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output);
case 0x1b:
- return SubmitGPFIFOBase(input, output, true);
+ return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, true);
case 0x1d:
- return ChannelSetTimeslice(input, output);
+ return WrapFixed(this, &nvhost_gpu::ChannelSetTimeslice, input, output);
default:
break;
}
@@ -86,9 +87,9 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
case 'G':
switch (command.cmd) {
case 0x14:
- return SetClientData(input, output);
+ return WrapFixed(this, &nvhost_gpu::SetClientData, input, output);
case 0x15:
- return GetClientData(input, output);
+ return WrapFixed(this, &nvhost_gpu::GetClientData, input, output);
default:
break;
}
@@ -104,7 +105,8 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> inpu
case 'H':
switch (command.cmd) {
case 0x1b:
- return SubmitGPFIFOBase(input, inline_input, output);
+ return WrapFixedInlIn(this, &nvhost_gpu::SubmitGPFIFOBase2, input, inline_input,
+ output);
}
break;
}
@@ -121,63 +123,45 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
void nvhost_gpu::OnOpen(DeviceFD fd) {}
void nvhost_gpu::OnClose(DeviceFD fd) {}
-NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) {
- IoctlSetNvmapFD params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) {
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
return NvResult::Success;
}
-NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_gpu::SetClientData(IoctlClientData& params) {
LOG_DEBUG(Service_NVDRV, "called");
-
- IoctlClientData params{};
- std::memcpy(&params, input.data(), input.size());
user_data = params.data;
return NvResult::Success;
}
-NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::span<u8> output) {
+NvResult nvhost_gpu::GetClientData(IoctlClientData& params) {
LOG_DEBUG(Service_NVDRV, "called");
-
- IoctlClientData params{};
- std::memcpy(&params, input.data(), input.size());
params.data = user_data;
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::span<u8> output) {
- std::memcpy(&zcull_params, input.data(), input.size());
+NvResult nvhost_gpu::ZCullBind(IoctlZCullBind& params) {
+ zcull_params = params;
LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
zcull_params.mode);
-
- std::memcpy(output.data(), &zcull_params, output.size());
return NvResult::Success;
}
-NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::span<u8> output) {
- IoctlSetErrorNotifier params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset,
params.size, params.mem);
-
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::span<u8> output) {
- std::memcpy(&channel_priority, input.data(), input.size());
+NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) {
+ channel_priority = params.priority;
LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
-
return NvResult::Success;
}
-NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output) {
- IoctlAllocGpfifoEx2 params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params) {
LOG_WARNING(Service_NVDRV,
"(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, "
"unk1={:X}, unk2={:X}, unk3={:X}",
@@ -193,18 +177,14 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> out
params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint);
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::span<u8> output) {
- IoctlAllocObjCtx params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
params.flags);
params.obj_id = 0x0;
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
@@ -248,8 +228,7 @@ static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementW
return result;
}
-NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output,
- Tegra::CommandList&& entries) {
+NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries) {
LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address,
params.num_entries, params.flags.raw);
@@ -290,65 +269,55 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> o
flags.raw = 0;
- std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
return NvResult::Success;
}
-NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output,
- bool kickoff) {
- if (input.size() < sizeof(IoctlSubmitGpfifo)) {
+NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
+ std::span<Tegra::CommandListHeader> commands, bool kickoff) {
+ if (params.num_entries > commands.size()) {
UNIMPLEMENTED();
return NvResult::InvalidSize;
}
- IoctlSubmitGpfifo params{};
- std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
- Tegra::CommandList entries(params.num_entries);
+ Tegra::CommandList entries(params.num_entries);
if (kickoff) {
system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(),
params.num_entries * sizeof(Tegra::CommandListHeader));
} else {
- std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)],
+ std::memcpy(entries.command_lists.data(), commands.data(),
params.num_entries * sizeof(Tegra::CommandListHeader));
}
- return SubmitGPFIFOImpl(params, output, std::move(entries));
+ return SubmitGPFIFOImpl(params, std::move(entries));
}
-NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
- std::span<u8> output) {
- if (input.size() < sizeof(IoctlSubmitGpfifo)) {
+NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,
+ std::span<const Tegra::CommandListHeader> commands) {
+ if (params.num_entries > commands.size()) {
UNIMPLEMENTED();
return NvResult::InvalidSize;
}
- IoctlSubmitGpfifo params{};
- std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
+
Tegra::CommandList entries(params.num_entries);
- std::memcpy(entries.command_lists.data(), input_inline.data(), input_inline.size());
- return SubmitGPFIFOImpl(params, output, std::move(entries));
+ std::memcpy(entries.command_lists.data(), commands.data(),
+ params.num_entries * sizeof(Tegra::CommandListHeader));
+ return SubmitGPFIFOImpl(params, std::move(entries));
}
-NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::span<u8> output) {
- IoctlGetWaitbase params{};
- std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
+NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) {
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
params.value = 0; // Seems to be hard coded at 0
- std::memcpy(output.data(), &params, output.size());
return NvResult::Success;
}
-NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::span<u8> output) {
- IoctlChannelSetTimeout params{};
- std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
+NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) {
LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
return NvResult::Success;
}
-NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output) {
- IoctlSetTimeslice params{};
- std::memcpy(&params, input.data(), sizeof(IoctlSetTimeslice));
+NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) {
LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);
channel_timeslice = params.timeslice;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 529c20526..88fd228ff 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -186,23 +186,24 @@ private:
u32_le channel_priority{};
u32_le channel_timeslice{};
- NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output);
- NvResult SetClientData(std::span<const u8> input, std::span<u8> output);
- NvResult GetClientData(std::span<const u8> input, std::span<u8> output);
- NvResult ZCullBind(std::span<const u8> input, std::span<u8> output);
- NvResult SetErrorNotifier(std::span<const u8> input, std::span<u8> output);
- NvResult SetChannelPriority(std::span<const u8> input, std::span<u8> output);
- NvResult AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output);
- NvResult AllocateObjectContext(std::span<const u8> input, std::span<u8> output);
- NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output,
- Tegra::CommandList&& entries);
- NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output,
- bool kickoff = false);
- NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
- std::span<u8> output);
- NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output);
- NvResult ChannelSetTimeout(std::span<const u8> input, std::span<u8> output);
- NvResult ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output);
+ NvResult SetNVMAPfd(IoctlSetNvmapFD& params);
+ NvResult SetClientData(IoctlClientData& params);
+ NvResult GetClientData(IoctlClientData& params);
+ NvResult ZCullBind(IoctlZCullBind& params);
+ NvResult SetErrorNotifier(IoctlSetErrorNotifier& params);
+ NvResult SetChannelPriority(IoctlChannelSetPriority& params);
+ NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params);
+ NvResult AllocateObjectContext(IoctlAllocObjCtx& params);
+
+ NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries);
+ NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
+ std::span<Tegra::CommandListHeader> commands, bool kickoff = false);
+ NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,
+ std::span<const Tegra::CommandListHeader> commands);
+
+ NvResult GetWaitbase(IoctlGetWaitbase& params);
+ NvResult ChannelSetTimeout(IoctlChannelSetTimeout& params);
+ NvResult ChannelSetTimeslice(IoctlSetTimeslice& params);
EventInterface& events_interface;
NvCore::Container& core;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index a174442a6..f43914e1b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -6,6 +6,7 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/core/container.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
#include "video_core/renderer_base.h"
@@ -25,18 +26,18 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
if (!host1x_file.fd_to_id.contains(fd)) {
host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++;
}
- return Submit(fd, input, output);
+ return WrapFixedVariable(this, &nvhost_nvdec::Submit, input, output, fd);
}
case 0x2:
- return GetSyncpoint(input, output);
+ return WrapFixed(this, &nvhost_nvdec::GetSyncpoint, input, output);
case 0x3:
- return GetWaitbase(input, output);
+ return WrapFixed(this, &nvhost_nvdec::GetWaitbase, input, output);
case 0x7:
- return SetSubmitTimeout(input, output);
+ return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output);
case 0x9:
- return MapBuffer(input, output);
+ return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output);
case 0xa:
- return UnmapBuffer(input, output);
+ return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output);
default:
break;
}
@@ -44,7 +45,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
case 'H':
switch (command.cmd) {
case 0x1:
- return SetNVMAPfd(input);
+ return WrapFixed(this, &nvhost_nvdec::SetNVMAPfd, input, output);
default:
break;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 61649aa4a..74c701b95 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -29,6 +29,9 @@ std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::si
return 0;
}
const size_t bytes_copied = count * sizeof(T);
+ if (input.size() < offset + bytes_copied) {
+ return 0;
+ }
std::memcpy(dst.data(), input.data() + offset, bytes_copied);
return bytes_copied;
}
@@ -41,6 +44,9 @@ std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size
return 0;
}
const size_t bytes_copied = src.size() * sizeof(T);
+ if (dst.size() < offset + bytes_copied) {
+ return 0;
+ }
std::memcpy(dst.data() + offset, src.data(), bytes_copied);
return bytes_copied;
}
@@ -63,18 +69,14 @@ nvhost_nvdec_common::~nvhost_nvdec_common() {
core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint);
}
-NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) {
- IoctlSetNvmapFD params{};
- std::memcpy(&params, input.data(), sizeof(IoctlSetNvmapFD));
+NvResult nvhost_nvdec_common::SetNVMAPfd(IoctlSetNvmapFD& params) {
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) {
- IoctlSubmit params{};
- std::memcpy(&params, input.data(), sizeof(IoctlSubmit));
+NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, DeviceFD fd) {
LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count);
// Instantiate param buffers
@@ -85,12 +87,12 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std
std::vector<u32> fence_thresholds(params.fence_count);
// Slice input into their respective buffers
- std::size_t offset = sizeof(IoctlSubmit);
- offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset);
- offset += SliceVectors(input, relocs, params.relocation_count, offset);
- offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset);
- offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset);
- offset += SliceVectors(input, fence_thresholds, params.fence_count, offset);
+ std::size_t offset = 0;
+ offset += SliceVectors(data, command_buffers, params.cmd_buffer_count, offset);
+ offset += SliceVectors(data, relocs, params.relocation_count, offset);
+ offset += SliceVectors(data, reloc_shifts, params.relocation_count, offset);
+ offset += SliceVectors(data, syncpt_increments, params.syncpoint_count, offset);
+ offset += SliceVectors(data, fence_thresholds, params.fence_count, offset);
auto& gpu = system.GPU();
if (gpu.UseNvdec()) {
@@ -108,72 +110,51 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std
cmdlist.size() * sizeof(u32));
gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
}
- std::memcpy(output.data(), &params, sizeof(IoctlSubmit));
// Some games expect command_buffers to be written back
- offset = sizeof(IoctlSubmit);
- offset += WriteVectors(output, command_buffers, offset);
- offset += WriteVectors(output, relocs, offset);
- offset += WriteVectors(output, reloc_shifts, offset);
- offset += WriteVectors(output, syncpt_increments, offset);
- offset += WriteVectors(output, fence_thresholds, offset);
+ offset = 0;
+ offset += WriteVectors(data, command_buffers, offset);
+ offset += WriteVectors(data, relocs, offset);
+ offset += WriteVectors(data, reloc_shifts, offset);
+ offset += WriteVectors(data, syncpt_increments, offset);
+ offset += WriteVectors(data, fence_thresholds, offset);
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::span<u8> output) {
- IoctlGetSyncpoint params{};
- std::memcpy(&params, input.data(), sizeof(IoctlGetSyncpoint));
+NvResult nvhost_nvdec_common::GetSyncpoint(IoctlGetSyncpoint& params) {
LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param);
-
- // const u32 id{NvCore::SyncpointManager::channel_syncpoints[static_cast<u32>(channel_type)]};
params.value = channel_syncpoint;
- std::memcpy(output.data(), &params, sizeof(IoctlGetSyncpoint));
-
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::span<u8> output) {
- IoctlGetWaitbase params{};
+NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) {
LOG_CRITICAL(Service_NVDRV, "called WAITBASE");
- std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
params.value = 0; // Seems to be hard coded at 0
- std::memcpy(output.data(), &params, sizeof(IoctlGetWaitbase));
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) {
- IoctlMapBuffer params{};
- std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
- std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
-
- SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
-
- for (auto& cmd_buffer : cmd_buffer_handles) {
- cmd_buffer.map_address = nvmap.PinHandle(cmd_buffer.map_handle);
+NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries) {
+ const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
+ for (size_t i = 0; i < num_entries; i++) {
+ entries[i].map_address = nvmap.PinHandle(entries[i].map_handle);
}
- std::memcpy(output.data(), &params, sizeof(IoctlMapBuffer));
- std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(),
- cmd_buffer_handles.size() * sizeof(MapBufferEntry));
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) {
- IoctlMapBuffer params{};
- std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
- std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
-
- SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
- for (auto& cmd_buffer : cmd_buffer_handles) {
- nvmap.UnpinHandle(cmd_buffer.map_handle);
+NvResult nvhost_nvdec_common::UnmapBuffer(IoctlMapBuffer& params,
+ std::span<MapBufferEntry> entries) {
+ const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
+ for (size_t i = 0; i < num_entries; i++) {
+ nvmap.UnpinHandle(entries[i].map_handle);
+ entries[i] = {};
}
- std::memset(output.data(), 0, output.size());
+ params = {};
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::span<u8> output) {
- std::memcpy(&submit_timeout, input.data(), input.size());
+NvResult nvhost_nvdec_common::SetSubmitTimeout(u32 timeout) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
return NvResult::Success;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
index 9bb573bfe..7ce748e18 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
@@ -107,13 +107,13 @@ protected:
static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size");
/// Ioctl command implementations
- NvResult SetNVMAPfd(std::span<const u8> input);
- NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output);
- NvResult GetSyncpoint(std::span<const u8> input, std::span<u8> output);
- NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output);
- NvResult MapBuffer(std::span<const u8> input, std::span<u8> output);
- NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output);
- NvResult SetSubmitTimeout(std::span<const u8> input, std::span<u8> output);
+ NvResult SetNVMAPfd(IoctlSetNvmapFD&);
+ NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd);
+ NvResult GetSyncpoint(IoctlGetSyncpoint& params);
+ NvResult GetWaitbase(IoctlGetWaitbase& params);
+ NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries);
+ NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries);
+ NvResult SetSubmitTimeout(u32 timeout);
Kernel::KEvent* QueryEvent(u32 event_id) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
index a05c8cdae..9e6b86458 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -5,6 +5,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h"
namespace Service::Nvidia::Devices {
@@ -18,7 +19,7 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
case 'H':
switch (command.cmd) {
case 0x1:
- return SetNVMAPfd(input, output);
+ return WrapFixed(this, &nvhost_nvjpg::SetNVMAPfd, input, output);
default:
break;
}
@@ -46,9 +47,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
void nvhost_nvjpg::OnOpen(DeviceFD fd) {}
void nvhost_nvjpg::OnClose(DeviceFD fd) {}
-NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) {
- IoctlSetNvmapFD params{};
- std::memcpy(&params, input.data(), input.size());
+NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) {
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
nvmap_fd = params.nvmap_fd;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
index 5623e0d47..790c97f6a 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -33,7 +33,7 @@ private:
s32_le nvmap_fd{};
- NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output);
+ NvResult SetNVMAPfd(IoctlSetNvmapFD& params);
};
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index c0b8684c3..87f8d7c22 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -5,6 +5,7 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/core/container.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
#include "video_core/renderer_base.h"
@@ -25,16 +26,16 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
if (!host1x_file.fd_to_id.contains(fd)) {
host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++;
}
- return Submit(fd, input, output);
+ return WrapFixedVariable(this, &nvhost_vic::Submit, input, output, fd);
}
case 0x2:
- return GetSyncpoint(input, output);
+ return WrapFixed(this, &nvhost_vic::GetSyncpoint, input, output);
case 0x3:
- return GetWaitbase(input, output);
+ return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output);
case 0x9:
- return MapBuffer(input, output);
+ return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output);
case 0xa:
- return UnmapBuffer(input, output);
+ return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output);
default:
break;
}
@@ -42,7 +43,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
case 'H':
switch (command.cmd) {
case 0x1:
- return SetNVMAPfd(input);
+ return WrapFixed(this, &nvhost_vic::SetNVMAPfd, input, output);
default:
break;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 968eaa175..71b2e62ec 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -13,6 +13,7 @@
#include "core/hle/kernel/k_process.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
+#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "core/memory.h"
@@ -31,17 +32,17 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
case 0x1:
switch (command.cmd) {
case 0x1:
- return IocCreate(input, output);
+ return WrapFixed(this, &nvmap::IocCreate, input, output);
case 0x3:
- return IocFromId(input, output);
+ return WrapFixed(this, &nvmap::IocFromId, input, output);
case 0x4:
- return IocAlloc(input, output);
+ return WrapFixed(this, &nvmap::IocAlloc, input, output);
case 0x5:
- return IocFree(input, output);
+ return WrapFixed(this, &nvmap::IocFree, input, output);
case 0x9:
- return IocParam(input, output);
+ return WrapFixed(this, &nvmap::IocParam, input, output);
case 0xe:
- return IocGetId(input, output);
+ return WrapFixed(this, &nvmap::IocGetId, input, output);
default:
break;
}
@@ -69,9 +70,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, st
void nvmap::OnOpen(DeviceFD fd) {}
void nvmap::OnClose(DeviceFD fd) {}
-NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) {
- IocCreateParams params;
- std::memcpy(&params, input.data(), sizeof(params));
+NvResult nvmap::IocCreate(IocCreateParams& params) {
LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size);
std::shared_ptr<NvCore::NvMap::Handle> handle_description{};
@@ -85,13 +84,10 @@ NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) {
params.handle = handle_description->id;
LOG_DEBUG(Service_NVDRV, "handle: {}, size: 0x{:X}", handle_description->id, params.size);
- std::memcpy(output.data(), &params, sizeof(params));
return NvResult::Success;
}
-NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {
- IocAllocParams params;
- std::memcpy(&params, input.data(), sizeof(params));
+NvResult nvmap::IocAlloc(IocAllocParams& params) {
LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address);
if (!params.handle) {
@@ -133,14 +129,10 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {
handle_description->size,
Kernel::KMemoryPermission::None, true, false)
.IsSuccess());
- std::memcpy(output.data(), &params, sizeof(params));
return result;
}
-NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) {
- IocGetIdParams params;
- std::memcpy(&params, input.data(), sizeof(params));
-
+NvResult nvmap::IocGetId(IocGetIdParams& params) {
LOG_DEBUG(Service_NVDRV, "called");
// See the comment in FromId for extra info on this function
@@ -157,14 +149,10 @@ NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) {
}
params.id = handle_description->id;
- std::memcpy(output.data(), &params, sizeof(params));
return NvResult::Success;
}
-NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) {
- IocFromIdParams params;
- std::memcpy(&params, input.data(), sizeof(params));
-
+NvResult nvmap::IocFromId(IocFromIdParams& params) {
LOG_DEBUG(Service_NVDRV, "called, id:{}", params.id);
// Handles and IDs are always the same value in nvmap however IDs can be used globally given the
@@ -188,16 +176,12 @@ NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) {
return result;
}
params.handle = handle_description->id;
- std::memcpy(output.data(), &params, sizeof(params));
return NvResult::Success;
}
-NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) {
+NvResult nvmap::IocParam(IocParamParams& params) {
enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 };
- IocParamParams params;
- std::memcpy(&params, input.data(), sizeof(params));
-
LOG_DEBUG(Service_NVDRV, "called type={}", params.param);
if (!params.handle) {
@@ -237,14 +221,10 @@ NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) {
return NvResult::BadValue;
}
- std::memcpy(output.data(), &params, sizeof(params));
return NvResult::Success;
}
-NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {
- IocFreeParams params;
- std::memcpy(&params, input.data(), sizeof(params));
-
+NvResult nvmap::IocFree(IocFreeParams& params) {
LOG_DEBUG(Service_NVDRV, "called");
if (!params.handle) {
@@ -267,7 +247,6 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {
// This is possible when there's internal dups or other duplicates.
}
- std::memcpy(output.data(), &params, sizeof(params));
return NvResult::Success;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 4c0cc71cd..049c11028 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -99,12 +99,12 @@ public:
};
static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size");
- NvResult IocCreate(std::span<const u8> input, std::span<u8> output);
- NvResult IocAlloc(std::span<const u8> input, std::span<u8> output);
- NvResult IocGetId(std::span<const u8> input, std::span<u8> output);
- NvResult IocFromId(std::span<const u8> input, std::span<u8> output);
- NvResult IocParam(std::span<const u8> input, std::span<u8> output);
- NvResult IocFree(std::span<const u8> input, std::span<u8> output);
+ NvResult IocCreate(IocCreateParams& params);
+ NvResult IocAlloc(IocAllocParams& params);
+ NvResult IocGetId(IocGetIdParams& params);
+ NvResult IocFromId(IocFromIdParams& params);
+ NvResult IocParam(IocParamParams& params);
+ NvResult IocFree(IocFreeParams& params);
private:
/// Id to use for the next handle that is created.
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
index 1179ab6a6..d91886bed 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
@@ -171,6 +171,25 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_
return Status::NoError;
}
+Status BufferQueueConsumer::Disconnect() {
+ LOG_DEBUG(Service_Nvnflinger, "called");
+
+ std::scoped_lock lock{core->mutex};
+
+ if (core->consumer_listener == nullptr) {
+ LOG_ERROR(Service_Nvnflinger, "no consumer is connected");
+ return Status::BadValue;
+ }
+
+ core->is_abandoned = true;
+ core->consumer_listener = nullptr;
+ core->queue.clear();
+ core->FreeAllBuffersLocked();
+ core->SignalDequeueCondition();
+
+ return Status::NoError;
+}
+
Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
if (out_slot_mask == nullptr) {
LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr");
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
index b90f70c9a..0a61e8dbd 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
@@ -27,6 +27,7 @@ public:
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app);
+ Status Disconnect();
Status GetReleasedBuffers(u64* out_slot_mask);
private:
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
index ed66f6f5b..4ed5e5978 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
@@ -14,24 +14,12 @@ BufferQueueCore::BufferQueueCore() = default;
BufferQueueCore::~BufferQueueCore() = default;
-void BufferQueueCore::NotifyShutdown() {
- std::scoped_lock lock{mutex};
-
- is_shutting_down = true;
-
- SignalDequeueCondition();
-}
-
void BufferQueueCore::SignalDequeueCondition() {
dequeue_possible.store(true);
dequeue_condition.notify_all();
}
bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) {
- if (is_shutting_down) {
- return false;
- }
-
dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); });
dequeue_possible.store(false);
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.h b/src/core/hle/service/nvnflinger/buffer_queue_core.h
index 9164f08a0..e513d183b 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_core.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_core.h
@@ -34,8 +34,6 @@ public:
BufferQueueCore();
~BufferQueueCore();
- void NotifyShutdown();
-
private:
void SignalDequeueCondition();
bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk);
@@ -74,7 +72,6 @@ private:
u32 transform_hint{};
bool is_allocating{};
mutable std::condition_variable_any is_allocating_condition;
- bool is_shutting_down{};
};
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_transform_flags.h b/src/core/hle/service/nvnflinger/buffer_transform_flags.h
index 67aa5dad6..ffe579718 100644
--- a/src/core/hle/service/nvnflinger/buffer_transform_flags.h
+++ b/src/core/hle/service/nvnflinger/buffer_transform_flags.h
@@ -3,6 +3,7 @@
#pragma once
+#include "common/common_funcs.h"
#include "common/common_types.h"
namespace Service::android {
@@ -21,5 +22,6 @@ enum class BufferTransformFlags : u32 {
/// Rotate source image 270 degrees clockwise
Rotate270 = 0x07,
};
+DECLARE_ENUM_FLAG_OPERATORS(BufferTransformFlags);
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp
index 4dcda8dac..1059e72bf 100644
--- a/src/core/hle/service/nvnflinger/consumer_base.cpp
+++ b/src/core/hle/service/nvnflinger/consumer_base.cpp
@@ -27,6 +27,26 @@ void ConsumerBase::Connect(bool controlled_by_app) {
consumer->Connect(shared_from_this(), controlled_by_app);
}
+void ConsumerBase::Abandon() {
+ LOG_DEBUG(Service_Nvnflinger, "called");
+
+ std::scoped_lock lock{mutex};
+
+ if (!is_abandoned) {
+ this->AbandonLocked();
+ is_abandoned = true;
+ }
+}
+
+void ConsumerBase::AbandonLocked() {
+ for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
+ this->FreeBufferLocked(i);
+ }
+ // disconnect from the BufferQueue
+ consumer->Disconnect();
+ consumer = nullptr;
+}
+
void ConsumerBase::FreeBufferLocked(s32 slot_index) {
LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index);
diff --git a/src/core/hle/service/nvnflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h
index 264829414..ea3e9e97a 100644
--- a/src/core/hle/service/nvnflinger/consumer_base.h
+++ b/src/core/hle/service/nvnflinger/consumer_base.h
@@ -24,6 +24,7 @@ class BufferQueueConsumer;
class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> {
public:
void Connect(bool controlled_by_app);
+ void Abandon();
protected:
explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
@@ -34,6 +35,7 @@ protected:
void OnBuffersReleased() override;
void OnSidebandStreamChanged() override;
+ void AbandonLocked();
void FreeBufferLocked(s32 slot_index);
Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when);
Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer);
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
index f260c94b6..d7db24f42 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
@@ -71,24 +71,17 @@ Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address,
R_SUCCEED();
}
-template <typename T>
-std::span<u8> SerializeIoc(T& params) {
- return std::span(reinterpret_cast<u8*>(std::addressof(params)), sizeof(T));
-}
-
Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) {
// Create a handle.
- Nvidia::Devices::nvmap::IocCreateParams create_in_params{
+ Nvidia::Devices::nvmap::IocCreateParams create_params{
.size = size,
.handle = 0,
};
- Nvidia::Devices::nvmap::IocCreateParams create_out_params{};
- R_UNLESS(nvmap.IocCreate(SerializeIoc(create_in_params), SerializeIoc(create_out_params)) ==
- Nvidia::NvResult::Success,
+ R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success,
VI::ResultOperationFailed);
// Assign the output handle.
- *out_nv_map_handle = create_out_params.handle;
+ *out_nv_map_handle = create_params.handle;
// We succeeded.
R_SUCCEED();
@@ -96,13 +89,10 @@ Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap,
Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) {
// Free the handle.
- Nvidia::Devices::nvmap::IocFreeParams free_in_params{
+ Nvidia::Devices::nvmap::IocFreeParams free_params{
.handle = handle,
};
- Nvidia::Devices::nvmap::IocFreeParams free_out_params{};
- R_UNLESS(nvmap.IocFree(SerializeIoc(free_in_params), SerializeIoc(free_out_params)) ==
- Nvidia::NvResult::Success,
- VI::ResultOperationFailed);
+ R_UNLESS(nvmap.IocFree(free_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed);
// We succeeded.
R_SUCCEED();
@@ -111,7 +101,7 @@ Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) {
Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer,
u32 size) {
// Assign the allocated memory to the handle.
- Nvidia::Devices::nvmap::IocAllocParams alloc_in_params{
+ Nvidia::Devices::nvmap::IocAllocParams alloc_params{
.handle = handle,
.heap_mask = 0,
.flags = {},
@@ -119,10 +109,7 @@ Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::Proce
.kind = 0,
.address = GetInteger(buffer),
};
- Nvidia::Devices::nvmap::IocAllocParams alloc_out_params{};
- R_UNLESS(nvmap.IocAlloc(SerializeIoc(alloc_in_params), SerializeIoc(alloc_out_params)) ==
- Nvidia::NvResult::Success,
- VI::ResultOperationFailed);
+ R_UNLESS(nvmap.IocAlloc(alloc_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed);
// We succeeded.
R_SUCCEED();
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index bebb45eae..0745434c5 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -47,7 +47,10 @@ void Nvnflinger::SplitVSync(std::stop_token stop_token) {
vsync_signal.Wait();
const auto lock_guard = Lock();
- Compose();
+
+ if (!is_abandoned) {
+ Compose();
+ }
}
}
@@ -98,7 +101,6 @@ Nvnflinger::~Nvnflinger() {
}
ShutdownLayers();
- vsync_thread = {};
if (nvdrv) {
nvdrv->Close(disp_fd);
@@ -106,12 +108,20 @@ Nvnflinger::~Nvnflinger() {
}
void Nvnflinger::ShutdownLayers() {
- const auto lock_guard = Lock();
- for (auto& display : displays) {
- for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
- display.GetLayer(layer).Core().NotifyShutdown();
+ // Abandon consumers.
+ {
+ const auto lock_guard = Lock();
+ for (auto& display : displays) {
+ for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
+ display.GetLayer(layer).GetConsumer().Abandon();
+ }
}
+
+ is_abandoned = true;
}
+
+ // Join the vsync thread, if it exists.
+ vsync_thread = {};
}
void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index 959d8b46b..f5d73acdb 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -140,6 +140,8 @@ private:
s32 swap_interval = 1;
+ bool is_abandoned = false;
+
/// Event that handles screen composition.
std::shared_ptr<Core::Timing::EventType> multi_composition_event;
std::shared_ptr<Core::Timing::EventType> single_composition_event;
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp
index 938330dd0..6a7fd72bc 100644
--- a/src/core/hle/service/pctl/pctl_module.cpp
+++ b/src/core/hle/service/pctl/pctl_module.cpp
@@ -141,6 +141,12 @@ public:
service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent");
}
+ ~IParentalControlService() {
+ service_context.CloseEvent(synchronization_event);
+ service_context.CloseEvent(unlinked_event);
+ service_context.CloseEvent(request_suspension_event);
+ };
+
private:
bool CheckFreeCommunicationPermissionImpl() const {
if (states.temporary_unlocked) {
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 85849d5f3..dd652ca42 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -39,6 +39,18 @@ bool IsConnectionBased(Type type) {
}
}
+template <typename T>
+T GetValue(std::span<const u8> buffer) {
+ T t{};
+ std::memcpy(&t, buffer.data(), std::min(sizeof(T), buffer.size()));
+ return t;
+}
+
+template <typename T>
+void PutValue(std::span<u8> buffer, const T& t) {
+ std::memcpy(buffer.data(), &t, std::min(sizeof(T), buffer.size()));
+}
+
} // Anonymous namespace
void BSD::PollWork::Execute(BSD* bsd) {
@@ -316,22 +328,12 @@ void BSD::SetSockOpt(HLERequestContext& ctx) {
const s32 fd = rp.Pop<s32>();
const u32 level = rp.Pop<u32>();
const OptName optname = static_cast<OptName>(rp.Pop<u32>());
-
- const auto buffer = ctx.ReadBuffer();
- const u8* optval = buffer.empty() ? nullptr : buffer.data();
- size_t optlen = buffer.size();
-
- std::array<u64, 2> values;
- if ((optname == OptName::SNDTIMEO || optname == OptName::RCVTIMEO) && buffer.size() == 8) {
- std::memcpy(values.data(), buffer.data(), sizeof(values));
- optlen = sizeof(values);
- optval = reinterpret_cast<const u8*>(values.data());
- }
+ const auto optval = ctx.ReadBuffer();
LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level,
- static_cast<u32>(optname), optlen);
+ static_cast<u32>(optname), optval.size());
- BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval));
+ BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
}
void BSD::Shutdown(HLERequestContext& ctx) {
@@ -521,18 +523,19 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco
std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
s32 nfds, s32 timeout) {
- if (write_buffer.size() < nfds * sizeof(PollFD)) {
- return {-1, Errno::INVAL};
- }
-
- if (nfds == 0) {
+ if (nfds <= 0) {
// When no entries are provided, -1 is returned with errno zero
return {-1, Errno::SUCCESS};
}
+ if (read_buffer.size() < nfds * sizeof(PollFD)) {
+ return {-1, Errno::INVAL};
+ }
+ if (write_buffer.size() < nfds * sizeof(PollFD)) {
+ return {-1, Errno::INVAL};
+ }
- const size_t length = std::min(read_buffer.size(), write_buffer.size());
std::vector<PollFD> fds(nfds);
- std::memcpy(fds.data(), read_buffer.data(), length);
+ std::memcpy(fds.data(), read_buffer.data(), nfds * sizeof(PollFD));
if (timeout >= 0) {
const s64 seconds = timeout / 1000;
@@ -580,7 +583,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
for (size_t i = 0; i < num; ++i) {
fds[i].revents = Translate(host_pollfds[i].revents);
}
- std::memcpy(write_buffer.data(), fds.data(), length);
+ std::memcpy(write_buffer.data(), fds.data(), nfds * sizeof(PollFD));
return Translate(result);
}
@@ -608,8 +611,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
new_descriptor.is_connection_based = descriptor.is_connection_based;
const SockAddrIn guest_addr_in = Translate(result.sockaddr_in);
- const size_t length = std::min(sizeof(guest_addr_in), write_buffer.size());
- std::memcpy(write_buffer.data(), &guest_addr_in, length);
+ PutValue(write_buffer, guest_addr_in);
return {new_fd, Errno::SUCCESS};
}
@@ -619,8 +621,7 @@ Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
return Errno::BADF;
}
ASSERT(addr.size() == sizeof(SockAddrIn));
- SockAddrIn addr_in;
- std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
+ auto addr_in = GetValue<SockAddrIn>(addr);
return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
}
@@ -631,8 +632,7 @@ Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
}
UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn));
- SockAddrIn addr_in;
- std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
+ auto addr_in = GetValue<SockAddrIn>(addr);
return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
}
@@ -650,7 +650,7 @@ Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
ASSERT(write_buffer.size() >= sizeof(guest_addrin));
write_buffer.resize(sizeof(guest_addrin));
- std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin));
+ PutValue(write_buffer, guest_addrin);
return Translate(bsd_errno);
}
@@ -667,7 +667,7 @@ Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
ASSERT(write_buffer.size() >= sizeof(guest_addrin));
write_buffer.resize(sizeof(guest_addrin));
- std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin));
+ PutValue(write_buffer, guest_addrin);
return Translate(bsd_errno);
}
@@ -725,7 +725,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
optval.size() == sizeof(Errno), { return Errno::INVAL; },
"Incorrect getsockopt option size");
optval.resize(sizeof(Errno));
- memcpy(optval.data(), &translated_pending_err, sizeof(Errno));
+ PutValue(optval, translated_pending_err);
}
return Translate(getsockopt_err);
}
@@ -735,7 +735,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
}
}
-Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) {
+Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -748,17 +748,15 @@ Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, con
Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
if (optname == OptName::LINGER) {
- ASSERT(optlen == sizeof(Linger));
- Linger linger;
- std::memcpy(&linger, optval, sizeof(linger));
+ ASSERT(optval.size() == sizeof(Linger));
+ auto linger = GetValue<Linger>(optval);
ASSERT(linger.onoff == 0 || linger.onoff == 1);
return Translate(socket->SetLinger(linger.onoff != 0, linger.linger));
}
- ASSERT(optlen == sizeof(u32));
- u32 value;
- std::memcpy(&value, optval, sizeof(value));
+ ASSERT(optval.size() == sizeof(u32));
+ auto value = GetValue<u32>(optval);
switch (optname) {
case OptName::REUSEADDR:
@@ -862,7 +860,7 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess
} else {
ASSERT(addr.size() == sizeof(SockAddrIn));
const SockAddrIn result = Translate(addr_in);
- std::memcpy(addr.data(), &result, sizeof(result));
+ PutValue(addr, result);
}
}
@@ -886,8 +884,7 @@ std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> mes
Network::SockAddrIn* p_addr_in = nullptr;
if (!addr.empty()) {
ASSERT(addr.size() == sizeof(SockAddrIn));
- SockAddrIn guest_addr_in;
- std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in));
+ auto guest_addr_in = GetValue<SockAddrIn>(addr);
addr_in = Translate(guest_addr_in);
p_addr_in = &addr_in;
}
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index 161f22b9b..4f69d382c 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -163,7 +163,7 @@ private:
Errno ListenImpl(s32 fd, s32 backlog);
std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg);
Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval);
- Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval);
+ Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval);
Errno ShutdownImpl(s32 fd, s32 how);
std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,