summaryrefslogtreecommitdiff
path: root/src/core/hle/service
diff options
context:
space:
mode:
authorGravatar Ameer J2023-11-26 21:08:53 -0500
committerGravatar GitHub2023-11-26 21:08:53 -0500
commit1d11fe00a3000efbf6a0a4bb690e0d544a1b7b4a (patch)
treec219aacab776c0a1e3956614b60a01fa2f6164cb /src/core/hle/service
parentshader_recompiler: Align SSBO offsets in GlobalMemory functions (diff)
parentMerge pull request #11535 from GPUCode/upload_cmdbuf (diff)
downloadyuzu-1d11fe00a3000efbf6a0a4bb690e0d544a1b7b4a.tar.gz
yuzu-1d11fe00a3000efbf6a0a4bb690e0d544a1b7b4a.tar.xz
yuzu-1d11fe00a3000efbf6a0a4bb690e0d544a1b7b4a.zip
Merge branch 'master' into ssbo-align
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/acc/acc.cpp56
-rw-r--r--src/core/hle/service/am/am.cpp91
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp3
-rw-r--r--src/core/hle/service/am/applets/applet_controller.h2
-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/btm/btm.cpp56
-rw-r--r--src/core/hle/service/friend/friend.cpp13
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.cpp42
-rw-r--r--src/core/hle/service/hid/controllers/console_six_axis.h43
-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/debug_pad.cpp10
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h6
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp54
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h6
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp10
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h6
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h6
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp588
-rw-r--r--src/core/hle/service/hid/controllers/npad.h205
-rw-r--r--src/core/hle/service/hid/controllers/palma.cpp88
-rw-r--r--src/core/hle/service/hid/controllers/palma.h8
-rw-r--r--src/core/hle/service/hid/controllers/seven_six_axis.cpp (renamed from src/core/hle/service/hid/controllers/console_sixaxis.cpp)38
-rw-r--r--src/core/hle/service/hid/controllers/seven_six_axis.h (renamed from src/core/hle/service/hid/controllers/console_sixaxis.h)31
-rw-r--r--src/core/hle/service/hid/controllers/six_axis.cpp413
-rw-r--r--src/core/hle/service/hid/controllers/six_axis.h111
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h6
-rw-r--r--src/core/hle/service/hid/controllers/xpad.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h6
-rw-r--r--src/core/hle/service/hid/hid.cpp2861
-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.cpp2371
-rw-r--r--src/core/hle/service/hid/hid_server.h149
-rw-r--r--src/core/hle/service/hid/hid_system_server.cpp539
-rw-r--r--src/core/hle/service/hid/hid_system_server.h63
-rw-r--r--src/core/hle/service/hid/hid_util.h146
-rw-r--r--src/core/hle/service/hid/irs.cpp7
-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.cpp241
-rw-r--r--src/core/hle/service/hid/resource_manager.h111
-rw-r--r--src/core/hle/service/hid/ring_lifo.h6
-rw-r--r--src/core/hle/service/ldn/ldn.cpp10
-rw-r--r--src/core/hle/service/ldr/ldr.cpp45
-rw-r--r--src/core/hle/service/nfc/common/device_manager.cpp3
-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_item.h2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp27
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.h9
-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_queue_producer.cpp19
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.h3
-rw-r--r--src/core/hle/service/nvnflinger/buffer_slot.h2
-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.cpp29
-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/nvnflinger/status.h2
-rw-r--r--src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp34
-rw-r--r--src/core/hle/service/nvnflinger/ui/graphic_buffer.h25
-rw-r--r--src/core/hle/service/set/set_sys.cpp96
-rw-r--r--src/core/hle/service/set/set_sys.h36
-rw-r--r--src/core/hle/service/sockets/bsd.cpp77
-rw-r--r--src/core/hle/service/sockets/bsd.h2
-rw-r--r--src/core/hle/service/time/clock_types.h5
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp2
97 files changed, 6028 insertions, 4478 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 @@
3 3
4#include <algorithm> 4#include <algorithm>
5#include <array> 5#include <array>
6
6#include "common/common_types.h" 7#include "common/common_types.h"
7#include "common/fs/file.h" 8#include "common/fs/file.h"
8#include "common/fs/path_util.h" 9#include "common/fs/path_util.h"
9#include "common/logging/log.h" 10#include "common/logging/log.h"
10#include "common/polyfill_ranges.h" 11#include "common/polyfill_ranges.h"
12#include "common/stb.h"
11#include "common/string_util.h" 13#include "common/string_util.h"
12#include "common/swap.h" 14#include "common/swap.h"
13#include "core/constants.h" 15#include "core/constants.h"
@@ -38,9 +40,36 @@ static std::filesystem::path GetImagePath(const Common::UUID& uuid) {
38 fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString()); 40 fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString());
39} 41}
40 42
41static constexpr u32 SanitizeJPEGSize(std::size_t size) { 43static void JPGToMemory(void* context, void* data, int len) {
44 std::vector<u8>* jpg_image = static_cast<std::vector<u8>*>(context);
45 unsigned char* jpg = static_cast<unsigned char*>(data);
46 jpg_image->insert(jpg_image->end(), jpg, jpg + len);
47}
48
49static void SanitizeJPEGImageSize(std::vector<u8>& image) {
42 constexpr std::size_t max_jpeg_image_size = 0x20000; 50 constexpr std::size_t max_jpeg_image_size = 0x20000;
43 return static_cast<u32>(std::min(size, max_jpeg_image_size)); 51 constexpr int profile_dimensions = 256;
52 int original_width, original_height, color_channels;
53
54 const auto plain_image =
55 stbi_load_from_memory(image.data(), static_cast<int>(image.size()), &original_width,
56 &original_height, &color_channels, STBI_rgb);
57
58 // Resize image to match 256*256
59 if (original_width != profile_dimensions || original_height != profile_dimensions) {
60 // Use vector instead of array to avoid overflowing the stack
61 std::vector<u8> out_image(profile_dimensions * profile_dimensions * STBI_rgb);
62 stbir_resize_uint8_srgb(plain_image, original_width, original_height, 0, out_image.data(),
63 profile_dimensions, profile_dimensions, 0, STBI_rgb, 0,
64 STBIR_FILTER_BOX);
65 image.clear();
66 if (!stbi_write_jpg_to_func(JPGToMemory, &image, profile_dimensions, profile_dimensions,
67 STBI_rgb, out_image.data(), 0)) {
68 LOG_ERROR(Service_ACC, "Failed to resize the user provided image.");
69 }
70 }
71
72 image.resize(std::min(image.size(), max_jpeg_image_size));
44} 73}
45 74
46class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> { 75class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> {
@@ -339,19 +368,20 @@ protected:
339 LOG_WARNING(Service_ACC, 368 LOG_WARNING(Service_ACC,
340 "Failed to load user provided image! Falling back to built-in backup..."); 369 "Failed to load user provided image! Falling back to built-in backup...");
341 ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG); 370 ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG);
342 rb.Push(SanitizeJPEGSize(Core::Constants::ACCOUNT_BACKUP_JPEG.size())); 371 rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
343 return; 372 return;
344 } 373 }
345 374
346 const u32 size = SanitizeJPEGSize(image.GetSize()); 375 std::vector<u8> buffer(image.GetSize());
347 std::vector<u8> buffer(size);
348 376
349 if (image.Read(buffer) != buffer.size()) { 377 if (image.Read(buffer) != buffer.size()) {
350 LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image."); 378 LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
351 } 379 }
352 380
381 SanitizeJPEGImageSize(buffer);
382
353 ctx.WriteBuffer(buffer); 383 ctx.WriteBuffer(buffer);
354 rb.Push<u32>(size); 384 rb.Push(static_cast<u32>(buffer.size()));
355 } 385 }
356 386
357 void GetImageSize(HLERequestContext& ctx) { 387 void GetImageSize(HLERequestContext& ctx) {
@@ -365,10 +395,18 @@ protected:
365 if (!image.IsOpen()) { 395 if (!image.IsOpen()) {
366 LOG_WARNING(Service_ACC, 396 LOG_WARNING(Service_ACC,
367 "Failed to load user provided image! Falling back to built-in backup..."); 397 "Failed to load user provided image! Falling back to built-in backup...");
368 rb.Push(SanitizeJPEGSize(Core::Constants::ACCOUNT_BACKUP_JPEG.size())); 398 rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
369 } else { 399 return;
370 rb.Push(SanitizeJPEGSize(image.GetSize()));
371 } 400 }
401
402 std::vector<u8> buffer(image.GetSize());
403
404 if (image.Read(buffer) != buffer.size()) {
405 LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
406 }
407
408 SanitizeJPEGImageSize(buffer);
409 rb.Push(static_cast<u32>(buffer.size()));
372 } 410 }
373 411
374 void Store(HLERequestContext& ctx) { 412 void Store(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index cc643ea09..a266d7c21 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -13,6 +13,7 @@
13#include "core/file_sys/patch_manager.h" 13#include "core/file_sys/patch_manager.h"
14#include "core/file_sys/registered_cache.h" 14#include "core/file_sys/registered_cache.h"
15#include "core/file_sys/savedata_factory.h" 15#include "core/file_sys/savedata_factory.h"
16#include "core/hid/hid_types.h"
16#include "core/hle/kernel/k_event.h" 17#include "core/hle/kernel/k_event.h"
17#include "core/hle/kernel/k_transfer_memory.h" 18#include "core/hle/kernel/k_transfer_memory.h"
18#include "core/hle/result.h" 19#include "core/hle/result.h"
@@ -21,6 +22,7 @@
21#include "core/hle/service/am/applet_ae.h" 22#include "core/hle/service/am/applet_ae.h"
22#include "core/hle/service/am/applet_oe.h" 23#include "core/hle/service/am/applet_oe.h"
23#include "core/hle/service/am/applets/applet_cabinet.h" 24#include "core/hle/service/am/applets/applet_cabinet.h"
25#include "core/hle/service/am/applets/applet_controller.h"
24#include "core/hle/service/am/applets/applet_mii_edit_types.h" 26#include "core/hle/service/am/applets/applet_mii_edit_types.h"
25#include "core/hle/service/am/applets/applet_profile_select.h" 27#include "core/hle/service/am/applets/applet_profile_select.h"
26#include "core/hle/service/am/applets/applet_software_keyboard_types.h" 28#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
@@ -35,6 +37,7 @@
35#include "core/hle/service/caps/caps_su.h" 37#include "core/hle/service/caps/caps_su.h"
36#include "core/hle/service/caps/caps_types.h" 38#include "core/hle/service/caps/caps_types.h"
37#include "core/hle/service/filesystem/filesystem.h" 39#include "core/hle/service/filesystem/filesystem.h"
40#include "core/hle/service/hid/controllers/npad.h"
38#include "core/hle/service/ipc_helpers.h" 41#include "core/hle/service/ipc_helpers.h"
39#include "core/hle/service/ns/ns.h" 42#include "core/hle/service/ns/ns.h"
40#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" 43#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
@@ -73,7 +76,7 @@ IWindowController::IWindowController(Core::System& system_)
73 static const FunctionInfo functions[] = { 76 static const FunctionInfo functions[] = {
74 {0, nullptr, "CreateWindow"}, 77 {0, nullptr, "CreateWindow"},
75 {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, 78 {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
76 {2, nullptr, "GetAppletResourceUserIdOfCallerApplet"}, 79 {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"},
77 {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, 80 {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
78 {11, nullptr, "ReleaseForegroundRights"}, 81 {11, nullptr, "ReleaseForegroundRights"},
79 {12, nullptr, "RejectToChangeIntoBackground"}, 82 {12, nullptr, "RejectToChangeIntoBackground"},
@@ -97,6 +100,16 @@ void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
97 rb.Push<u64>(process_id); 100 rb.Push<u64>(process_id);
98} 101}
99 102
103void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
104 const u64 process_id = 0;
105
106 LOG_WARNING(Service_AM, "(STUBBED) called");
107
108 IPC::ResponseBuilder rb{ctx, 4};
109 rb.Push(ResultSuccess);
110 rb.Push<u64>(process_id);
111}
112
100void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { 113void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
101 LOG_WARNING(Service_AM, "(STUBBED) called"); 114 LOG_WARNING(Service_AM, "(STUBBED) called");
102 IPC::ResponseBuilder rb{ctx, 2}; 115 IPC::ResponseBuilder rb{ctx, 2};
@@ -1565,7 +1578,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
1565 {6, nullptr, "GetPopInteractiveInDataEvent"}, 1578 {6, nullptr, "GetPopInteractiveInDataEvent"},
1566 {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, 1579 {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
1567 {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, 1580 {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
1568 {12, nullptr, "GetMainAppletIdentityInfo"}, 1581 {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
1569 {13, nullptr, "CanUseApplicationCore"}, 1582 {13, nullptr, "CanUseApplicationCore"},
1570 {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, 1583 {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
1571 {15, nullptr, "GetMainAppletApplicationControlProperty"}, 1584 {15, nullptr, "GetMainAppletApplicationControlProperty"},
@@ -1609,6 +1622,9 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
1609 case Applets::AppletId::SoftwareKeyboard: 1622 case Applets::AppletId::SoftwareKeyboard:
1610 PushInShowSoftwareKeyboard(); 1623 PushInShowSoftwareKeyboard();
1611 break; 1624 break;
1625 case Applets::AppletId::Controller:
1626 PushInShowController();
1627 break;
1612 default: 1628 default:
1613 break; 1629 break;
1614 } 1630 }
@@ -1666,13 +1682,33 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
1666 rb.PushRaw(applet_info); 1682 rb.PushRaw(applet_info);
1667} 1683}
1668 1684
1669void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { 1685void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
1670 struct AppletIdentityInfo { 1686 struct AppletIdentityInfo {
1671 Applets::AppletId applet_id; 1687 Applets::AppletId applet_id;
1672 INSERT_PADDING_BYTES(0x4); 1688 INSERT_PADDING_BYTES(0x4);
1673 u64 application_id; 1689 u64 application_id;
1674 }; 1690 };
1691 static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
1692
1693 LOG_WARNING(Service_AM, "(STUBBED) called");
1694
1695 const AppletIdentityInfo applet_info{
1696 .applet_id = Applets::AppletId::QLaunch,
1697 .application_id = 0x0100000000001000ull,
1698 };
1699
1700 IPC::ResponseBuilder rb{ctx, 6};
1701 rb.Push(ResultSuccess);
1702 rb.PushRaw(applet_info);
1703}
1675 1704
1705void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
1706 struct AppletIdentityInfo {
1707 Applets::AppletId applet_id;
1708 INSERT_PADDING_BYTES(0x4);
1709 u64 application_id;
1710 };
1711 static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
1676 LOG_WARNING(Service_AM, "(STUBBED) called"); 1712 LOG_WARNING(Service_AM, "(STUBBED) called");
1677 1713
1678 const AppletIdentityInfo applet_info{ 1714 const AppletIdentityInfo applet_info{
@@ -1737,6 +1773,55 @@ void ILibraryAppletSelfAccessor::PushInShowAlbum() {
1737 queue_data.emplace_back(std::move(settings_data)); 1773 queue_data.emplace_back(std::move(settings_data));
1738} 1774}
1739 1775
1776void ILibraryAppletSelfAccessor::PushInShowController() {
1777 const Applets::CommonArguments common_args = {
1778 .arguments_version = Applets::CommonArgumentVersion::Version3,
1779 .size = Applets::CommonArgumentSize::Version3,
1780 .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8),
1781 .theme_color = Applets::ThemeColor::BasicBlack,
1782 .play_startup_sound = true,
1783 .system_tick = system.CoreTiming().GetClockTicks(),
1784 };
1785
1786 Applets::ControllerSupportArgNew user_args = {
1787 .header = {.player_count_min = 1,
1788 .player_count_max = 4,
1789 .enable_take_over_connection = true,
1790 .enable_left_justify = false,
1791 .enable_permit_joy_dual = true,
1792 .enable_single_mode = false,
1793 .enable_identification_color = false},
1794 .identification_colors = {},
1795 .enable_explain_text = false,
1796 .explain_text = {},
1797 };
1798
1799 Applets::ControllerSupportArgPrivate private_args = {
1800 .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate),
1801 .arg_size = sizeof(Applets::ControllerSupportArgNew),
1802 .is_home_menu = true,
1803 .flag_1 = true,
1804 .mode = Applets::ControllerSupportMode::ShowControllerSupport,
1805 .caller = Applets::ControllerSupportCaller::
1806 Application, // switchbrew: Always zero except with
1807 // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
1808 // which sets this to the input param
1809 .style_set = Core::HID::NpadStyleSet::None,
1810 .joy_hold_type = 0,
1811 };
1812 std::vector<u8> common_args_data(sizeof(common_args));
1813 std::vector<u8> private_args_data(sizeof(private_args));
1814 std::vector<u8> user_args_data(sizeof(user_args));
1815
1816 std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
1817 std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
1818 std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
1819
1820 queue_data.emplace_back(std::move(common_args_data));
1821 queue_data.emplace_back(std::move(private_args_data));
1822 queue_data.emplace_back(std::move(user_args_data));
1823}
1824
1740void ILibraryAppletSelfAccessor::PushInShowCabinetData() { 1825void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
1741 const Applets::CommonArguments arguments{ 1826 const Applets::CommonArguments arguments{
1742 .arguments_version = Applets::CommonArgumentVersion::Version3, 1827 .arguments_version = Applets::CommonArgumentVersion::Version3,
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 8f8cb8a9e..905a71b9f 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -87,6 +87,7 @@ public:
87 87
88private: 88private:
89 void GetAppletResourceUserId(HLERequestContext& ctx); 89 void GetAppletResourceUserId(HLERequestContext& ctx);
90 void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
90 void AcquireForegroundRights(HLERequestContext& ctx); 91 void AcquireForegroundRights(HLERequestContext& ctx);
91}; 92};
92 93
@@ -345,6 +346,7 @@ private:
345 void PopInData(HLERequestContext& ctx); 346 void PopInData(HLERequestContext& ctx);
346 void PushOutData(HLERequestContext& ctx); 347 void PushOutData(HLERequestContext& ctx);
347 void GetLibraryAppletInfo(HLERequestContext& ctx); 348 void GetLibraryAppletInfo(HLERequestContext& ctx);
349 void GetMainAppletIdentityInfo(HLERequestContext& ctx);
348 void ExitProcessAndReturn(HLERequestContext& ctx); 350 void ExitProcessAndReturn(HLERequestContext& ctx);
349 void GetCallerAppletIdentityInfo(HLERequestContext& ctx); 351 void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
350 void GetDesirableKeyboardLayout(HLERequestContext& ctx); 352 void GetDesirableKeyboardLayout(HLERequestContext& ctx);
@@ -355,6 +357,7 @@ private:
355 void PushInShowCabinetData(); 357 void PushInShowCabinetData();
356 void PushInShowMiiEditData(); 358 void PushInShowMiiEditData();
357 void PushInShowSoftwareKeyboard(); 359 void PushInShowSoftwareKeyboard();
360 void PushInShowController();
358 361
359 std::deque<std::vector<u8>> queue_data; 362 std::deque<std::vector<u8>> queue_data;
360}; 363};
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index b379dadeb..9d1960cb7 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -122,7 +122,8 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
122 Service::NFP::RegisterInfoPrivate register_info{}; 122 Service::NFP::RegisterInfoPrivate register_info{};
123 std::memcpy(register_info.amiibo_name.data(), amiibo_name.data(), 123 std::memcpy(register_info.amiibo_name.data(), amiibo_name.data(),
124 std::min(amiibo_name.size(), register_info.amiibo_name.size() - 1)); 124 std::min(amiibo_name.size(), register_info.amiibo_name.size() - 1));
125 125 register_info.mii_store_data.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All);
126 register_info.mii_store_data.SetNickname({u'y', u'u', u'z', u'u'});
126 nfp_device->SetRegisterInfoPrivate(register_info); 127 nfp_device->SetRegisterInfoPrivate(register_info);
127 break; 128 break;
128 } 129 }
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h
index f6c64f633..9f839f3d7 100644
--- a/src/core/hle/service/am/applets/applet_controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
@@ -56,7 +56,7 @@ enum class ControllerSupportResult : u32 {
56struct ControllerSupportArgPrivate { 56struct ControllerSupportArgPrivate {
57 u32 arg_private_size{}; 57 u32 arg_private_size{};
58 u32 arg_size{}; 58 u32 arg_size{};
59 bool flag_0{}; 59 bool is_home_menu{};
60 bool flag_1{}; 60 bool flag_1{};
61 ControllerSupportMode mode{}; 61 ControllerSupportMode mode{};
62 ControllerSupportCaller caller{}; 62 ControllerSupportCaller caller{};
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() {
330 LOG_DEBUG(Service_AM, "Extracting RomFS to {}", 330 LOG_DEBUG(Service_AM, "Extracting RomFS to {}",
331 Common::FS::PathToUTF8String(offline_cache_dir)); 331 Common::FS::PathToUTF8String(offline_cache_dir));
332 332
333 const auto extracted_romfs_dir = 333 const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs);
334 FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard);
335 334
336 const auto temp_dir = system.GetFilesystem()->CreateDirectory( 335 const auto temp_dir = system.GetFilesystem()->CreateDirectory(
337 Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite); 336 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 {
69 MyPage = 0x1A, 69 MyPage = 0x1A,
70}; 70};
71 71
72enum class AppletProgramId : u64 {
73 QLaunch = 0x0100000000001000ull,
74 Auth = 0x0100000000001001ull,
75 Cabinet = 0x0100000000001002ull,
76 Controller = 0x0100000000001003ull,
77 DataErase = 0x0100000000001004ull,
78 Error = 0x0100000000001005ull,
79 NetConnect = 0x0100000000001006ull,
80 ProfileSelect = 0x0100000000001007ull,
81 SoftwareKeyboard = 0x0100000000001008ull,
82 MiiEdit = 0x0100000000001009ull,
83 Web = 0x010000000000100Aull,
84 Shop = 0x010000000000100Bull,
85 OverlayDisplay = 0x010000000000100Cull,
86 PhotoViewer = 0x010000000000100Dull,
87 Settings = 0x010000000000100Eull,
88 OfflineWeb = 0x010000000000100Full,
89 LoginShare = 0x0100000000001010ull,
90 WebAuth = 0x0100000000001011ull,
91 Starter = 0x0100000000001012ull,
92 MyPage = 0x0100000000001013ull,
93 MaxProgramId = 0x0100000000001FFFull,
94};
95
72enum class LibraryAppletMode : u32 { 96enum class LibraryAppletMode : u32 {
73 AllForeground = 0, 97 AllForeground = 0,
74 Background = 1, 98 Background = 1,
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 8069f75b7..c65e32489 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -127,7 +127,7 @@ public:
127 127
128private: 128private:
129 void GetCore(HLERequestContext& ctx) { 129 void GetCore(HLERequestContext& ctx) {
130 LOG_DEBUG(Service_BTM, "called"); 130 LOG_WARNING(Service_BTM, "called");
131 131
132 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 132 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
133 rb.Push(ResultSuccess); 133 rb.Push(ResultSuccess);
@@ -263,13 +263,13 @@ public:
263 explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} { 263 explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} {
264 // clang-format off 264 // clang-format off
265 static const FunctionInfo functions[] = { 265 static const FunctionInfo functions[] = {
266 {0, nullptr, "StartGamepadPairing"}, 266 {0, &IBtmSystemCore::StartGamepadPairing, "StartGamepadPairing"},
267 {1, nullptr, "CancelGamepadPairing"}, 267 {1, &IBtmSystemCore::CancelGamepadPairing, "CancelGamepadPairing"},
268 {2, nullptr, "ClearGamepadPairingDatabase"}, 268 {2, nullptr, "ClearGamepadPairingDatabase"},
269 {3, nullptr, "GetPairedGamepadCount"}, 269 {3, nullptr, "GetPairedGamepadCount"},
270 {4, nullptr, "EnableRadio"}, 270 {4, nullptr, "EnableRadio"},
271 {5, nullptr, "DisableRadio"}, 271 {5, nullptr, "DisableRadio"},
272 {6, nullptr, "GetRadioOnOff"}, 272 {6, &IBtmSystemCore::IsRadioEnabled, "IsRadioEnabled"},
273 {7, nullptr, "AcquireRadioEvent"}, 273 {7, nullptr, "AcquireRadioEvent"},
274 {8, nullptr, "AcquireGamepadPairingEvent"}, 274 {8, nullptr, "AcquireGamepadPairingEvent"},
275 {9, nullptr, "IsGamepadPairingStarted"}, 275 {9, nullptr, "IsGamepadPairingStarted"},
@@ -280,18 +280,58 @@ public:
280 {14, nullptr, "AcquireAudioDeviceConnectionEvent"}, 280 {14, nullptr, "AcquireAudioDeviceConnectionEvent"},
281 {15, nullptr, "ConnectAudioDevice"}, 281 {15, nullptr, "ConnectAudioDevice"},
282 {16, nullptr, "IsConnectingAudioDevice"}, 282 {16, nullptr, "IsConnectingAudioDevice"},
283 {17, nullptr, "GetConnectedAudioDevices"}, 283 {17, &IBtmSystemCore::GetConnectedAudioDevices, "GetConnectedAudioDevices"},
284 {18, nullptr, "DisconnectAudioDevice"}, 284 {18, nullptr, "DisconnectAudioDevice"},
285 {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"}, 285 {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"},
286 {20, nullptr, "GetPairedAudioDevices"}, 286 {20, nullptr, "GetPairedAudioDevices"},
287 {21, nullptr, "RemoveAudioDevicePairing"}, 287 {21, nullptr, "RemoveAudioDevicePairing"},
288 {22, nullptr, "RequestAudioDeviceConnectionRejection"}, 288 {22, &IBtmSystemCore::RequestAudioDeviceConnectionRejection, "RequestAudioDeviceConnectionRejection"},
289 {23, nullptr, "CancelAudioDeviceConnectionRejection"} 289 {23, &IBtmSystemCore::CancelAudioDeviceConnectionRejection, "CancelAudioDeviceConnectionRejection"}
290 }; 290 };
291 // clang-format on 291 // clang-format on
292 292
293 RegisterHandlers(functions); 293 RegisterHandlers(functions);
294 } 294 }
295
296private:
297 void IsRadioEnabled(HLERequestContext& ctx) {
298 LOG_DEBUG(Service_BTM, "(STUBBED) called"); // Spams a lot when controller applet is running
299
300 IPC::ResponseBuilder rb{ctx, 3};
301 rb.Push(ResultSuccess);
302 rb.Push(true);
303 }
304
305 void StartGamepadPairing(HLERequestContext& ctx) {
306 LOG_WARNING(Service_BTM, "(STUBBED) called");
307 IPC::ResponseBuilder rb{ctx, 2};
308 rb.Push(ResultSuccess);
309 }
310
311 void CancelGamepadPairing(HLERequestContext& ctx) {
312 LOG_WARNING(Service_BTM, "(STUBBED) called");
313 IPC::ResponseBuilder rb{ctx, 2};
314 rb.Push(ResultSuccess);
315 }
316
317 void CancelAudioDeviceConnectionRejection(HLERequestContext& ctx) {
318 LOG_WARNING(Service_BTM, "(STUBBED) called");
319 IPC::ResponseBuilder rb{ctx, 2};
320 rb.Push(ResultSuccess);
321 }
322
323 void GetConnectedAudioDevices(HLERequestContext& ctx) {
324 LOG_WARNING(Service_BTM, "(STUBBED) called");
325 IPC::ResponseBuilder rb{ctx, 3};
326 rb.Push(ResultSuccess);
327 rb.Push<u32>(0);
328 }
329
330 void RequestAudioDeviceConnectionRejection(HLERequestContext& ctx) {
331 LOG_WARNING(Service_BTM, "(STUBBED) called");
332 IPC::ResponseBuilder rb{ctx, 2};
333 rb.Push(ResultSuccess);
334 }
295}; 335};
296 336
297class BTM_SYS final : public ServiceFramework<BTM_SYS> { 337class BTM_SYS final : public ServiceFramework<BTM_SYS> {
@@ -308,7 +348,7 @@ public:
308 348
309private: 349private:
310 void GetCore(HLERequestContext& ctx) { 350 void GetCore(HLERequestContext& ctx) {
311 LOG_DEBUG(Service_BTM, "called"); 351 LOG_WARNING(Service_BTM, "called");
312 352
313 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 353 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
314 rb.Push(ResultSuccess); 354 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 9d05f9801..0507b14e7 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -32,7 +32,7 @@ public:
32 {10200, nullptr, "SendFriendRequestForApplication"}, 32 {10200, nullptr, "SendFriendRequestForApplication"},
33 {10211, nullptr, "AddFacedFriendRequestForApplication"}, 33 {10211, nullptr, "AddFacedFriendRequestForApplication"},
34 {10400, &IFriendService::GetBlockedUserListIds, "GetBlockedUserListIds"}, 34 {10400, &IFriendService::GetBlockedUserListIds, "GetBlockedUserListIds"},
35 {10420, nullptr, "IsBlockedUserListCacheAvailable"}, 35 {10420, &IFriendService::CheckBlockedUserListAvailability, "CheckBlockedUserListAvailability"},
36 {10421, nullptr, "EnsureBlockedUserListAvailable"}, 36 {10421, nullptr, "EnsureBlockedUserListAvailable"},
37 {10500, nullptr, "GetProfileList"}, 37 {10500, nullptr, "GetProfileList"},
38 {10600, nullptr, "DeclareOpenOnlinePlaySession"}, 38 {10600, nullptr, "DeclareOpenOnlinePlaySession"},
@@ -206,6 +206,17 @@ private:
206 rb.Push(true); 206 rb.Push(true);
207 } 207 }
208 208
209 void CheckBlockedUserListAvailability(HLERequestContext& ctx) {
210 IPC::RequestParser rp{ctx};
211 const auto uuid{rp.PopRaw<Common::UUID>()};
212
213 LOG_WARNING(Service_Friend, "(STUBBED) called, uuid=0x{}", uuid.RawString());
214
215 IPC::ResponseBuilder rb{ctx, 3};
216 rb.Push(ResultSuccess);
217 rb.Push(true);
218 }
219
209 KernelHelpers::ServiceContext service_context; 220 KernelHelpers::ServiceContext service_context;
210 221
211 Kernel::KEvent* completion_event; 222 Kernel::KEvent* completion_event;
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.cpp b/src/core/hle/service/hid/controllers/console_six_axis.cpp
new file mode 100644
index 000000000..b2bf1d78d
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/console_six_axis.cpp
@@ -0,0 +1,42 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core.h"
5#include "core/core_timing.h"
6#include "core/hid/emulated_console.h"
7#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/console_six_axis.h"
9#include "core/memory.h"
10
11namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
13
14ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
15 : ControllerBase{hid_core_} {
16 console = hid_core.GetEmulatedConsole();
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
18 "ConsoleSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
21}
22
23ConsoleSixAxis::~ConsoleSixAxis() = default;
24
25void ConsoleSixAxis::OnInit() {}
26
27void ConsoleSixAxis::OnRelease() {}
28
29void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 if (!IsControllerActivated()) {
31 return;
32 }
33
34 const auto motion_status = console->GetMotion();
35
36 shared_memory->sampling_number++;
37 shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
38 shared_memory->verticalization_error = motion_status.verticalization_error;
39 shared_memory->gyro_bias = motion_status.gyro_bias;
40}
41
42} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_six_axis.h b/src/core/hle/service/hid/controllers/console_six_axis.h
new file mode 100644
index 000000000..5b7c6a29a
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/console_six_axis.h
@@ -0,0 +1,43 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/vector_math.h"
7#include "core/hle/service/hid/controllers/controller_base.h"
8
9namespace Core::HID {
10class EmulatedConsole;
11} // namespace Core::HID
12
13namespace Service::HID {
14class ConsoleSixAxis final : public ControllerBase {
15public:
16 explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
17 ~ConsoleSixAxis() override;
18
19 // Called when the controller is initialized
20 void OnInit() override;
21
22 // When the controller is released
23 void OnRelease() override;
24
25 // When the controller is requesting an update for the shared memory
26 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
27
28private:
29 // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
30 struct ConsoleSharedMemory {
31 u64 sampling_number{};
32 bool is_seven_six_axis_sensor_at_rest{};
33 INSERT_PADDING_BYTES(3); // padding
34 f32 verticalization_error{};
35 Common::Vec3f gyro_bias{};
36 INSERT_PADDING_BYTES(4); // padding
37 };
38 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
39
40 ConsoleSharedMemory* shared_memory = nullptr;
41 Core::HID::EmulatedConsole* console = nullptr;
42};
43} // namespace Service::HID
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 {
8ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {} 8ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {}
9ControllerBase::~ControllerBase() = default; 9ControllerBase::~ControllerBase() = default;
10 10
11void ControllerBase::ActivateController() { 11Result ControllerBase::Activate() {
12 if (is_activated) { 12 if (is_activated) {
13 return; 13 return ResultSuccess;
14 } 14 }
15 is_activated = true; 15 is_activated = true;
16 OnInit(); 16 OnInit();
17 return ResultSuccess;
18}
19
20Result ControllerBase::Activate(u64 aruid) {
21 return Activate();
17} 22}
18 23
19void ControllerBase::DeactivateController() { 24void 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 @@
4#pragma once 4#pragma once
5 5
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/hle/result.h"
7 8
8namespace Core::Timing { 9namespace Core::Timing {
9class CoreTiming; 10class CoreTiming;
@@ -31,7 +32,8 @@ public:
31 // When the controller is requesting a motion update for the shared memory 32 // When the controller is requesting a motion update for the shared memory
32 virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {} 33 virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {}
33 34
34 void ActivateController(); 35 Result Activate();
36 Result Activate(u64 aruid);
35 37
36 void DeactivateController(); 38 void DeactivateController();
37 39
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 8ec9f4a95..9de19ebfc 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -13,7 +13,7 @@
13namespace Service::HID { 13namespace Service::HID {
14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; 14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
15 15
16Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 16DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
17 : ControllerBase{hid_core_} { 17 : ControllerBase{hid_core_} {
18 static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size, 18 static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
19 "DebugPadSharedMemory is bigger than the shared memory"); 19 "DebugPadSharedMemory is bigger than the shared memory");
@@ -22,13 +22,13 @@ Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_
22 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); 22 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
23} 23}
24 24
25Controller_DebugPad::~Controller_DebugPad() = default; 25DebugPad::~DebugPad() = default;
26 26
27void Controller_DebugPad::OnInit() {} 27void DebugPad::OnInit() {}
28 28
29void Controller_DebugPad::OnRelease() {} 29void DebugPad::OnRelease() {}
30 30
31void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 31void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
32 if (!IsControllerActivated()) { 32 if (!IsControllerActivated()) {
33 shared_memory->debug_pad_lifo.buffer_count = 0; 33 shared_memory->debug_pad_lifo.buffer_count = 0;
34 shared_memory->debug_pad_lifo.buffer_tail = 0; 34 shared_memory->debug_pad_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 68ff0ea79..5566dba77 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -15,10 +15,10 @@ struct AnalogStickState;
15} // namespace Core::HID 15} // namespace Core::HID
16 16
17namespace Service::HID { 17namespace Service::HID {
18class Controller_DebugPad final : public ControllerBase { 18class DebugPad final : public ControllerBase {
19public: 19public:
20 explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 20 explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
21 ~Controller_DebugPad() override; 21 ~DebugPad() override;
22 22
23 // Called when the controller is initialized 23 // Called when the controller is initialized
24 void OnInit() override; 24 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 63eecd42b..59b2ec73c 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -23,7 +23,7 @@ constexpr f32 Square(s32 num) {
23 return static_cast<f32>(num * num); 23 return static_cast<f32>(num * num);
24} 24}
25 25
26Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 26Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
27 : ControllerBase(hid_core_) { 27 : ControllerBase(hid_core_) {
28 static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size, 28 static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
29 "GestureSharedMemory is bigger than the shared memory"); 29 "GestureSharedMemory is bigger than the shared memory");
@@ -31,17 +31,17 @@ Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_sh
31 reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); 31 reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
32 console = hid_core.GetEmulatedConsole(); 32 console = hid_core.GetEmulatedConsole();
33} 33}
34Controller_Gesture::~Controller_Gesture() = default; 34Gesture::~Gesture() = default;
35 35
36void Controller_Gesture::OnInit() { 36void Gesture::OnInit() {
37 shared_memory->gesture_lifo.buffer_count = 0; 37 shared_memory->gesture_lifo.buffer_count = 0;
38 shared_memory->gesture_lifo.buffer_tail = 0; 38 shared_memory->gesture_lifo.buffer_tail = 0;
39 force_update = true; 39 force_update = true;
40} 40}
41 41
42void Controller_Gesture::OnRelease() {} 42void Gesture::OnRelease() {}
43 43
44void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 44void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
45 if (!IsControllerActivated()) { 45 if (!IsControllerActivated()) {
46 shared_memory->gesture_lifo.buffer_count = 0; 46 shared_memory->gesture_lifo.buffer_count = 0;
47 shared_memory->gesture_lifo.buffer_tail = 0; 47 shared_memory->gesture_lifo.buffer_tail = 0;
@@ -64,7 +64,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
64 UpdateGestureSharedMemory(gesture, time_difference); 64 UpdateGestureSharedMemory(gesture, time_difference);
65} 65}
66 66
67void Controller_Gesture::ReadTouchInput() { 67void Gesture::ReadTouchInput() {
68 if (!Settings::values.touchscreen.enabled) { 68 if (!Settings::values.touchscreen.enabled) {
69 fingers = {}; 69 fingers = {};
70 return; 70 return;
@@ -76,8 +76,7 @@ void Controller_Gesture::ReadTouchInput() {
76 } 76 }
77} 77}
78 78
79bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, 79bool Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) {
80 f32 time_difference) {
81 const auto& last_entry = GetLastGestureEntry(); 80 const auto& last_entry = GetLastGestureEntry();
82 if (force_update) { 81 if (force_update) {
83 force_update = false; 82 force_update = false;
@@ -100,8 +99,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
100 return false; 99 return false;
101} 100}
102 101
103void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, 102void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference) {
104 f32 time_difference) {
105 GestureType type = GestureType::Idle; 103 GestureType type = GestureType::Idle;
106 GestureAttribute attributes{}; 104 GestureAttribute attributes{};
107 105
@@ -138,8 +136,8 @@ void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture,
138 shared_memory->gesture_lifo.WriteNextEntry(next_state); 136 shared_memory->gesture_lifo.WriteNextEntry(next_state);
139} 137}
140 138
141void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type, 139void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
142 GestureAttribute& attributes) { 140 GestureAttribute& attributes) {
143 const auto& last_entry = GetLastGestureEntry(); 141 const auto& last_entry = GetLastGestureEntry();
144 142
145 gesture.detection_count++; 143 gesture.detection_count++;
@@ -152,8 +150,8 @@ void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& typ
152 } 150 }
153} 151}
154 152
155void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type, 153void Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
156 f32 time_difference) { 154 f32 time_difference) {
157 const auto& last_entry = GetLastGestureEntry(); 155 const auto& last_entry = GetLastGestureEntry();
158 156
159 // Promote to pan type if touch moved 157 // Promote to pan type if touch moved
@@ -186,9 +184,8 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Gestu
186 } 184 }
187} 185}
188 186
189void Controller_Gesture::EndGesture(GestureProperties& gesture, 187void Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
190 GestureProperties& last_gesture_props, GestureType& type, 188 GestureType& type, GestureAttribute& attributes, f32 time_difference) {
191 GestureAttribute& attributes, f32 time_difference) {
192 const auto& last_entry = GetLastGestureEntry(); 189 const auto& last_entry = GetLastGestureEntry();
193 190
194 if (last_gesture_props.active_points != 0) { 191 if (last_gesture_props.active_points != 0) {
@@ -222,9 +219,8 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture,
222 } 219 }
223} 220}
224 221
225void Controller_Gesture::SetTapEvent(GestureProperties& gesture, 222void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
226 GestureProperties& last_gesture_props, GestureType& type, 223 GestureType& type, GestureAttribute& attributes) {
227 GestureAttribute& attributes) {
228 type = GestureType::Tap; 224 type = GestureType::Tap;
229 gesture = last_gesture_props; 225 gesture = last_gesture_props;
230 force_update = true; 226 force_update = true;
@@ -236,9 +232,8 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
236 } 232 }
237} 233}
238 234
239void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, 235void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
240 GestureProperties& last_gesture_props, GestureType& type, 236 GestureType& type, f32 time_difference) {
241 f32 time_difference) {
242 const auto& last_entry = GetLastGestureEntry(); 237 const auto& last_entry = GetLastGestureEntry();
243 238
244 next_state.delta = gesture.mid_point - last_entry.pos; 239 next_state.delta = gesture.mid_point - last_entry.pos;
@@ -263,9 +258,8 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
263 } 258 }
264} 259}
265 260
266void Controller_Gesture::EndPanEvent(GestureProperties& gesture, 261void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
267 GestureProperties& last_gesture_props, GestureType& type, 262 GestureType& type, f32 time_difference) {
268 f32 time_difference) {
269 const auto& last_entry = GetLastGestureEntry(); 263 const auto& last_entry = GetLastGestureEntry();
270 next_state.vel_x = 264 next_state.vel_x =
271 static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference); 265 static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
@@ -287,8 +281,8 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
287 force_update = true; 281 force_update = true;
288} 282}
289 283
290void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, 284void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
291 GestureProperties& last_gesture_props, GestureType& type) { 285 GestureType& type) {
292 const auto& last_entry = GetLastGestureEntry(); 286 const auto& last_entry = GetLastGestureEntry();
293 287
294 type = GestureType::Swipe; 288 type = GestureType::Swipe;
@@ -311,11 +305,11 @@ void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
311 next_state.direction = GestureDirection::Up; 305 next_state.direction = GestureDirection::Up;
312} 306}
313 307
314const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { 308const Gesture::GestureState& Gesture::GetLastGestureEntry() const {
315 return shared_memory->gesture_lifo.ReadCurrentEntry().state; 309 return shared_memory->gesture_lifo.ReadCurrentEntry().state;
316} 310}
317 311
318Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { 312Gesture::GestureProperties Gesture::GetGestureProperties() {
319 GestureProperties gesture; 313 GestureProperties gesture;
320 std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers; 314 std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
321 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), 315 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 0d6099ea0..4c6f8ee07 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -12,10 +12,10 @@
12#include "core/hle/service/hid/ring_lifo.h" 12#include "core/hle/service/hid/ring_lifo.h"
13 13
14namespace Service::HID { 14namespace Service::HID {
15class Controller_Gesture final : public ControllerBase { 15class Gesture final : public ControllerBase {
16public: 16public:
17 explicit Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 17 explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
18 ~Controller_Gesture() override; 18 ~Gesture() override;
19 19
20 // Called when the controller is initialized 20 // Called when the controller is initialized
21 void OnInit() override; 21 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 117d87433..ddb1b0ba4 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -12,7 +12,7 @@
12namespace Service::HID { 12namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
14 14
15Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 15Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
16 : ControllerBase{hid_core_} { 16 : ControllerBase{hid_core_} {
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size, 17 static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
18 "KeyboardSharedMemory is bigger than the shared memory"); 18 "KeyboardSharedMemory is bigger than the shared memory");
@@ -21,13 +21,13 @@ Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_
21 emulated_devices = hid_core.GetEmulatedDevices(); 21 emulated_devices = hid_core.GetEmulatedDevices();
22} 22}
23 23
24Controller_Keyboard::~Controller_Keyboard() = default; 24Keyboard::~Keyboard() = default;
25 25
26void Controller_Keyboard::OnInit() {} 26void Keyboard::OnInit() {}
27 27
28void Controller_Keyboard::OnRelease() {} 28void Keyboard::OnRelease() {}
29 29
30void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 30void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
31 if (!IsControllerActivated()) { 31 if (!IsControllerActivated()) {
32 shared_memory->keyboard_lifo.buffer_count = 0; 32 shared_memory->keyboard_lifo.buffer_count = 0;
33 shared_memory->keyboard_lifo.buffer_tail = 0; 33 shared_memory->keyboard_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 7532f53c6..172ec1309 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -14,10 +14,10 @@ struct KeyboardKey;
14} // namespace Core::HID 14} // namespace Core::HID
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Keyboard final : public ControllerBase { 17class Keyboard final : public ControllerBase {
18public: 18public:
19 explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 19 explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Keyboard() override; 20 ~Keyboard() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
23 void OnInit() override; 23 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index 0afc66681..6e5a04e34 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -12,8 +12,7 @@
12namespace Service::HID { 12namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
14 14
15Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 15Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
16 : ControllerBase{hid_core_} {
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size, 16 static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
18 "MouseSharedMemory is bigger than the shared memory"); 17 "MouseSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at( 18 shared_memory = std::construct_at(
@@ -21,12 +20,12 @@ Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared
21 emulated_devices = hid_core.GetEmulatedDevices(); 20 emulated_devices = hid_core.GetEmulatedDevices();
22} 21}
23 22
24Controller_Mouse::~Controller_Mouse() = default; 23Mouse::~Mouse() = default;
25 24
26void Controller_Mouse::OnInit() {} 25void Mouse::OnInit() {}
27void Controller_Mouse::OnRelease() {} 26void Mouse::OnRelease() {}
28 27
29void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 28void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 if (!IsControllerActivated()) { 29 if (!IsControllerActivated()) {
31 shared_memory->mouse_lifo.buffer_count = 0; 30 shared_memory->mouse_lifo.buffer_count = 0;
32 shared_memory->mouse_lifo.buffer_tail = 0; 31 shared_memory->mouse_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 733d00577..a80f3823f 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -14,10 +14,10 @@ struct AnalogStickState;
14} // namespace Core::HID 14} // namespace Core::HID
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Mouse final : public ControllerBase { 17class Mouse final : public ControllerBase {
18public: 18public:
19 explicit Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 19 explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Mouse() override; 20 ~Mouse() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
23 void OnInit() override; 23 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index bc822f19e..08ee9de9c 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -18,6 +18,7 @@
18#include "core/hle/kernel/k_readable_event.h" 18#include "core/hle/kernel/k_readable_event.h"
19#include "core/hle/service/hid/controllers/npad.h" 19#include "core/hle/service/hid/controllers/npad.h"
20#include "core/hle/service/hid/errors.h" 20#include "core/hle/service/hid/errors.h"
21#include "core/hle/service/hid/hid_util.h"
21#include "core/hle/service/kernel_helpers.h" 22#include "core/hle/service/kernel_helpers.h"
22 23
23namespace Service::HID { 24namespace Service::HID {
@@ -29,60 +30,8 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
29 Core::HID::NpadIdType::Handheld, 30 Core::HID::NpadIdType::Handheld,
30}; 31};
31 32
32bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) { 33NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
33 switch (npad_id) { 34 KernelHelpers::ServiceContext& service_context_)
34 case Core::HID::NpadIdType::Player1:
35 case Core::HID::NpadIdType::Player2:
36 case Core::HID::NpadIdType::Player3:
37 case Core::HID::NpadIdType::Player4:
38 case Core::HID::NpadIdType::Player5:
39 case Core::HID::NpadIdType::Player6:
40 case Core::HID::NpadIdType::Player7:
41 case Core::HID::NpadIdType::Player8:
42 case Core::HID::NpadIdType::Other:
43 case Core::HID::NpadIdType::Handheld:
44 return true;
45 default:
46 LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
47 return false;
48 }
49}
50
51Result Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
52 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
53 const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
54 const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
55
56 if (!npad_type) {
57 return VibrationInvalidStyleIndex;
58 }
59 if (!npad_id) {
60 return VibrationInvalidNpadId;
61 }
62 if (!device_index) {
63 return VibrationDeviceIndexOutOfRange;
64 }
65
66 return ResultSuccess;
67}
68
69Result Controller_NPad::VerifyValidSixAxisSensorHandle(
70 const Core::HID::SixAxisSensorHandle& device_handle) {
71 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
72 const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
73
74 if (!npad_id) {
75 return InvalidNpadId;
76 }
77 if (!device_index) {
78 return NpadDeviceIndexOutOfRange;
79 }
80
81 return ResultSuccess;
82}
83
84Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
85 KernelHelpers::ServiceContext& service_context_)
86 : ControllerBase{hid_core_}, service_context{service_context_} { 35 : ControllerBase{hid_core_}, service_context{service_context_} {
87 static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size); 36 static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
88 for (std::size_t i = 0; i < controller_data.size(); ++i) { 37 for (std::size_t i = 0; i < controller_data.size(); ++i) {
@@ -103,7 +52,7 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_m
103 } 52 }
104} 53}
105 54
106Controller_NPad::~Controller_NPad() { 55NPad::~NPad() {
107 for (std::size_t i = 0; i < controller_data.size(); ++i) { 56 for (std::size_t i = 0; i < controller_data.size(); ++i) {
108 auto& controller = controller_data[i]; 57 auto& controller = controller_data[i];
109 controller.device->DeleteCallback(controller.callback_key); 58 controller.device->DeleteCallback(controller.callback_key);
@@ -111,8 +60,7 @@ Controller_NPad::~Controller_NPad() {
111 OnRelease(); 60 OnRelease();
112} 61}
113 62
114void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, 63void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) {
115 std::size_t controller_idx) {
116 if (type == Core::HID::ControllerTriggerType::All) { 64 if (type == Core::HID::ControllerTriggerType::All) {
117 ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); 65 ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
118 ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); 66 ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
@@ -150,7 +98,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
150 } 98 }
151} 99}
152 100
153void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { 101void NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
154 auto& controller = GetControllerFromNpadIdType(npad_id); 102 auto& controller = GetControllerFromNpadIdType(npad_id);
155 if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) { 103 if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) {
156 return; 104 return;
@@ -344,12 +292,13 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
344 controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices, 292 controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices,
345 Common::Input::PollingMode::Active); 293 Common::Input::PollingMode::Active);
346 } 294 }
295
347 SignalStyleSetChangedEvent(npad_id); 296 SignalStyleSetChangedEvent(npad_id);
348 WriteEmptyEntry(controller.shared_memory); 297 WriteEmptyEntry(controller.shared_memory);
349 hid_core.SetLastActiveController(npad_id); 298 hid_core.SetLastActiveController(npad_id);
350} 299}
351 300
352void Controller_NPad::OnInit() { 301void NPad::OnInit() {
353 if (!IsControllerActivated()) { 302 if (!IsControllerActivated()) {
354 return; 303 return;
355 } 304 }
@@ -383,7 +332,7 @@ void Controller_NPad::OnInit() {
383 } 332 }
384} 333}
385 334
386void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) { 335void NPad::WriteEmptyEntry(NpadInternalState* npad) {
387 NPadGenericState dummy_pad_state{}; 336 NPadGenericState dummy_pad_state{};
388 NpadGcTriggerState dummy_gc_state{}; 337 NpadGcTriggerState dummy_gc_state{};
389 dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1; 338 dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
@@ -404,7 +353,7 @@ void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
404 npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); 353 npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
405} 354}
406 355
407void Controller_NPad::OnRelease() { 356void NPad::OnRelease() {
408 is_controller_initialized = false; 357 is_controller_initialized = false;
409 for (std::size_t i = 0; i < controller_data.size(); ++i) { 358 for (std::size_t i = 0; i < controller_data.size(); ++i) {
410 auto& controller = controller_data[i]; 359 auto& controller = controller_data[i];
@@ -415,7 +364,7 @@ void Controller_NPad::OnRelease() {
415 } 364 }
416} 365}
417 366
418void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { 367void NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
419 std::scoped_lock lock{mutex}; 368 std::scoped_lock lock{mutex};
420 auto& controller = GetControllerFromNpadIdType(npad_id); 369 auto& controller = GetControllerFromNpadIdType(npad_id);
421 const auto controller_type = controller.device->GetNpadStyleIndex(); 370 const auto controller_type = controller.device->GetNpadStyleIndex();
@@ -457,12 +406,14 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
457 pad_entry.l_stick = stick_state.left; 406 pad_entry.l_stick = stick_state.left;
458 } 407 }
459 408
460 if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) { 409 if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft ||
410 controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
461 pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl); 411 pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
462 pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr); 412 pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
463 } 413 }
464 414
465 if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) { 415 if (controller_type == Core::HID::NpadStyleIndex::JoyconRight ||
416 controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
466 pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl); 417 pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
467 pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr); 418 pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
468 } 419 }
@@ -482,7 +433,7 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
482 } 433 }
483} 434}
484 435
485void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 436void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
486 if (!IsControllerActivated()) { 437 if (!IsControllerActivated()) {
487 return; 438 return;
488 } 439 }
@@ -612,134 +563,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
612 } 563 }
613} 564}
614 565
615void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) { 566void NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
616 if (!IsControllerActivated()) {
617 return;
618 }
619
620 for (std::size_t i = 0; i < controller_data.size(); ++i) {
621 auto& controller = controller_data[i];
622
623 const auto& controller_type = controller.device->GetNpadStyleIndex();
624
625 if (controller_type == Core::HID::NpadStyleIndex::None ||
626 !controller.device->IsConnected()) {
627 continue;
628 }
629
630 auto* npad = controller.shared_memory;
631 const auto& motion_state = controller.device->GetMotions();
632 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
633 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
634 auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
635 auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
636 auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
637 auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
638
639 // Clear previous state
640 sixaxis_fullkey_state = {};
641 sixaxis_handheld_state = {};
642 sixaxis_dual_left_state = {};
643 sixaxis_dual_right_state = {};
644 sixaxis_left_lifo_state = {};
645 sixaxis_right_lifo_state = {};
646
647 if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
648 controller.sixaxis_at_rest = true;
649 for (std::size_t e = 0; e < motion_state.size(); ++e) {
650 controller.sixaxis_at_rest =
651 controller.sixaxis_at_rest && motion_state[e].is_at_rest;
652 }
653 }
654
655 const auto set_motion_state = [&](SixAxisSensorState& state,
656 const Core::HID::ControllerMotion& hid_state) {
657 using namespace std::literals::chrono_literals;
658 static constexpr SixAxisSensorState default_motion_state = {
659 .delta_time = std::chrono::nanoseconds(5ms).count(),
660 .accel = {0, 0, -1.0f},
661 .orientation =
662 {
663 Common::Vec3f{1.0f, 0, 0},
664 Common::Vec3f{0, 1.0f, 0},
665 Common::Vec3f{0, 0, 1.0f},
666 },
667 .attribute = {1},
668 };
669 if (!controller.sixaxis_sensor_enabled) {
670 state = default_motion_state;
671 return;
672 }
673 if (!Settings::values.motion_enabled.GetValue()) {
674 state = default_motion_state;
675 return;
676 }
677 state.attribute.is_connected.Assign(1);
678 state.delta_time = std::chrono::nanoseconds(5ms).count();
679 state.accel = hid_state.accel;
680 state.gyro = hid_state.gyro;
681 state.rotation = hid_state.rotation;
682 state.orientation = hid_state.orientation;
683 };
684
685 switch (controller_type) {
686 case Core::HID::NpadStyleIndex::None:
687 ASSERT(false);
688 break;
689 case Core::HID::NpadStyleIndex::ProController:
690 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
691 break;
692 case Core::HID::NpadStyleIndex::Handheld:
693 set_motion_state(sixaxis_handheld_state, motion_state[0]);
694 break;
695 case Core::HID::NpadStyleIndex::JoyconDual:
696 set_motion_state(sixaxis_dual_left_state, motion_state[0]);
697 set_motion_state(sixaxis_dual_right_state, motion_state[1]);
698 break;
699 case Core::HID::NpadStyleIndex::JoyconLeft:
700 set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
701 break;
702 case Core::HID::NpadStyleIndex::JoyconRight:
703 set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
704 break;
705 case Core::HID::NpadStyleIndex::Pokeball:
706 using namespace std::literals::chrono_literals;
707 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
708 sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
709 break;
710 default:
711 break;
712 }
713
714 sixaxis_fullkey_state.sampling_number =
715 npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
716 sixaxis_handheld_state.sampling_number =
717 npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
718 sixaxis_dual_left_state.sampling_number =
719 npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
720 sixaxis_dual_right_state.sampling_number =
721 npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
722 sixaxis_left_lifo_state.sampling_number =
723 npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
724 sixaxis_right_lifo_state.sampling_number =
725 npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
726
727 if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
728 // This buffer only is updated on handheld on HW
729 npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
730 } else {
731 // Handheld doesn't update this buffer on HW
732 npad->sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
733 }
734
735 npad->sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
736 npad->sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
737 npad->sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
738 npad->sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
739 }
740}
741
742void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
743 hid_core.SetSupportedStyleTag(style_set); 567 hid_core.SetSupportedStyleTag(style_set);
744 568
745 if (is_controller_initialized) { 569 if (is_controller_initialized) {
@@ -750,14 +574,14 @@ void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
750 is_controller_initialized = true; 574 is_controller_initialized = true;
751} 575}
752 576
753Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const { 577Core::HID::NpadStyleTag NPad::GetSupportedStyleSet() const {
754 if (!is_controller_initialized) { 578 if (!is_controller_initialized) {
755 return {Core::HID::NpadStyleSet::None}; 579 return {Core::HID::NpadStyleSet::None};
756 } 580 }
757 return hid_core.GetSupportedStyleTag(); 581 return hid_core.GetSupportedStyleTag();
758} 582}
759 583
760Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) { 584Result NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
761 constexpr std::size_t max_number_npad_ids = 0xa; 585 constexpr std::size_t max_number_npad_ids = 0xa;
762 const auto length = data.size(); 586 const auto length = data.size();
763 ASSERT(length > 0 && (length % sizeof(u32)) == 0); 587 ASSERT(length > 0 && (length % sizeof(u32)) == 0);
@@ -773,17 +597,17 @@ Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
773 return ResultSuccess; 597 return ResultSuccess;
774} 598}
775 599
776void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { 600void NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
777 const auto copy_amount = supported_npad_id_types.size() * sizeof(u32); 601 const auto copy_amount = supported_npad_id_types.size() * sizeof(u32);
778 ASSERT(max_length <= copy_amount); 602 ASSERT(max_length <= copy_amount);
779 std::memcpy(data, supported_npad_id_types.data(), copy_amount); 603 std::memcpy(data, supported_npad_id_types.data(), copy_amount);
780} 604}
781 605
782std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { 606std::size_t NPad::GetSupportedNpadIdTypesSize() const {
783 return supported_npad_id_types.size(); 607 return supported_npad_id_types.size();
784} 608}
785 609
786void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) { 610void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
787 if (joy_hold_type != NpadJoyHoldType::Horizontal && 611 if (joy_hold_type != NpadJoyHoldType::Horizontal &&
788 joy_hold_type != NpadJoyHoldType::Vertical) { 612 joy_hold_type != NpadJoyHoldType::Vertical) {
789 LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}", 613 LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}",
@@ -793,11 +617,11 @@ void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
793 hold_type = joy_hold_type; 617 hold_type = joy_hold_type;
794} 618}
795 619
796Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const { 620NPad::NpadJoyHoldType NPad::GetHoldType() const {
797 return hold_type; 621 return hold_type;
798} 622}
799 623
800void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) { 624void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
801 if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) { 625 if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) {
802 ASSERT_MSG(false, "Activation mode should be always None, Single or Dual"); 626 ASSERT_MSG(false, "Activation mode should be always None, Single or Dual");
803 return; 627 return;
@@ -806,21 +630,20 @@ void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode a
806 handheld_activation_mode = activation_mode; 630 handheld_activation_mode = activation_mode;
807} 631}
808 632
809Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const { 633NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
810 return handheld_activation_mode; 634 return handheld_activation_mode;
811} 635}
812 636
813void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) { 637void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
814 communication_mode = communication_mode_; 638 communication_mode = communication_mode_;
815} 639}
816 640
817Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const { 641NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
818 return communication_mode; 642 return communication_mode;
819} 643}
820 644
821bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, 645bool NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
822 NpadJoyDeviceType npad_device_type, 646 NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) {
823 NpadJoyAssignmentMode assignment_mode) {
824 if (!IsNpadIdValid(npad_id)) { 647 if (!IsNpadIdValid(npad_id)) {
825 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 648 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
826 return false; 649 return false;
@@ -889,9 +712,8 @@ bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID:
889 return true; 712 return true;
890} 713}
891 714
892bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, 715bool NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
893 std::size_t device_index, 716 const Core::HID::VibrationValue& vibration_value) {
894 const Core::HID::VibrationValue& vibration_value) {
895 auto& controller = GetControllerFromNpadIdType(npad_id); 717 auto& controller = GetControllerFromNpadIdType(npad_id);
896 if (!controller.device->IsConnected()) { 718 if (!controller.device->IsConnected()) {
897 return false; 719 return false;
@@ -935,10 +757,9 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
935 return controller.device->SetVibration(device_index, vibration); 757 return controller.device->SetVibration(device_index, vibration);
936} 758}
937 759
938void Controller_NPad::VibrateController( 760void NPad::VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle,
939 const Core::HID::VibrationDeviceHandle& vibration_device_handle, 761 const Core::HID::VibrationValue& vibration_value) {
940 const Core::HID::VibrationValue& vibration_value) { 762 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
941 if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
942 return; 763 return;
943 } 764 }
944 765
@@ -982,7 +803,7 @@ void Controller_NPad::VibrateController(
982 } 803 }
983} 804}
984 805
985void Controller_NPad::VibrateControllers( 806void NPad::VibrateControllers(
986 std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, 807 std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
987 std::span<const Core::HID::VibrationValue> vibration_values) { 808 std::span<const Core::HID::VibrationValue> vibration_values) {
988 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { 809 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
@@ -999,9 +820,9 @@ void Controller_NPad::VibrateControllers(
999 } 820 }
1000} 821}
1001 822
1002Core::HID::VibrationValue Controller_NPad::GetLastVibration( 823Core::HID::VibrationValue NPad::GetLastVibration(
1003 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { 824 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
1004 if (IsDeviceHandleValid(vibration_device_handle).IsError()) { 825 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
1005 return {}; 826 return {};
1006 } 827 }
1007 828
@@ -1010,9 +831,9 @@ Core::HID::VibrationValue Controller_NPad::GetLastVibration(
1010 return controller.vibration[device_index].latest_vibration_value; 831 return controller.vibration[device_index].latest_vibration_value;
1011} 832}
1012 833
1013void Controller_NPad::InitializeVibrationDevice( 834void NPad::InitializeVibrationDevice(
1014 const Core::HID::VibrationDeviceHandle& vibration_device_handle) { 835 const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
1015 if (IsDeviceHandleValid(vibration_device_handle).IsError()) { 836 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
1016 return; 837 return;
1017 } 838 }
1018 839
@@ -1021,8 +842,8 @@ void Controller_NPad::InitializeVibrationDevice(
1021 InitializeVibrationDeviceAtIndex(npad_index, device_index); 842 InitializeVibrationDeviceAtIndex(npad_index, device_index);
1022} 843}
1023 844
1024void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id, 845void NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
1025 std::size_t device_index) { 846 std::size_t device_index) {
1026 auto& controller = GetControllerFromNpadIdType(npad_id); 847 auto& controller = GetControllerFromNpadIdType(npad_id);
1027 if (!Settings::values.vibration_enabled.GetValue()) { 848 if (!Settings::values.vibration_enabled.GetValue()) {
1028 controller.vibration[device_index].device_mounted = false; 849 controller.vibration[device_index].device_mounted = false;
@@ -1033,13 +854,13 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npa
1033 controller.device->IsVibrationEnabled(device_index); 854 controller.device->IsVibrationEnabled(device_index);
1034} 855}
1035 856
1036void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { 857void NPad::SetPermitVibrationSession(bool permit_vibration_session) {
1037 permit_vibration_session_enabled = permit_vibration_session; 858 permit_vibration_session_enabled = permit_vibration_session;
1038} 859}
1039 860
1040bool Controller_NPad::IsVibrationDeviceMounted( 861bool NPad::IsVibrationDeviceMounted(
1041 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { 862 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
1042 if (IsDeviceHandleValid(vibration_device_handle).IsError()) { 863 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
1043 return false; 864 return false;
1044 } 865 }
1045 866
@@ -1048,7 +869,7 @@ bool Controller_NPad::IsVibrationDeviceMounted(
1048 return controller.vibration[device_index].device_mounted; 869 return controller.vibration[device_index].device_mounted;
1049} 870}
1050 871
1051Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) { 872Kernel::KReadableEvent& NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
1052 if (!IsNpadIdValid(npad_id)) { 873 if (!IsNpadIdValid(npad_id)) {
1053 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 874 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1054 // Fallback to player 1 875 // Fallback to player 1
@@ -1060,18 +881,17 @@ Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::Npad
1060 return controller.styleset_changed_event->GetReadableEvent(); 881 return controller.styleset_changed_event->GetReadableEvent();
1061} 882}
1062 883
1063void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const { 884void NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
1064 const auto& controller = GetControllerFromNpadIdType(npad_id); 885 const auto& controller = GetControllerFromNpadIdType(npad_id);
1065 controller.styleset_changed_event->Signal(); 886 controller.styleset_changed_event->Signal();
1066} 887}
1067 888
1068void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, 889void NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id) {
1069 Core::HID::NpadIdType npad_id) {
1070 UpdateControllerAt(controller, npad_id, true); 890 UpdateControllerAt(controller, npad_id, true);
1071} 891}
1072 892
1073void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, 893void NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, Core::HID::NpadIdType npad_id,
1074 Core::HID::NpadIdType npad_id, bool connected) { 894 bool connected) {
1075 auto& controller = GetControllerFromNpadIdType(npad_id); 895 auto& controller = GetControllerFromNpadIdType(npad_id);
1076 if (!connected) { 896 if (!connected) {
1077 DisconnectNpad(npad_id); 897 DisconnectNpad(npad_id);
@@ -1082,7 +902,7 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
1082 InitNewlyAddedController(npad_id); 902 InitNewlyAddedController(npad_id);
1083} 903}
1084 904
1085Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { 905Result NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1086 if (!IsNpadIdValid(npad_id)) { 906 if (!IsNpadIdValid(npad_id)) {
1087 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 907 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1088 return InvalidNpadId; 908 return InvalidNpadId;
@@ -1108,9 +928,9 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1108 shared_memory->sixaxis_dual_right_properties.raw = 0; 928 shared_memory->sixaxis_dual_right_properties.raw = 0;
1109 shared_memory->sixaxis_left_properties.raw = 0; 929 shared_memory->sixaxis_left_properties.raw = 0;
1110 shared_memory->sixaxis_right_properties.raw = 0; 930 shared_memory->sixaxis_right_properties.raw = 0;
1111 shared_memory->battery_level_dual = 0; 931 shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty;
1112 shared_memory->battery_level_left = 0; 932 shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty;
1113 shared_memory->battery_level_right = 0; 933 shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty;
1114 shared_memory->fullkey_color = { 934 shared_memory->fullkey_color = {
1115 .attribute = ColorAttribute::NoController, 935 .attribute = ColorAttribute::NoController,
1116 .fullkey = {}, 936 .fullkey = {},
@@ -1131,54 +951,9 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1131 return ResultSuccess; 951 return ResultSuccess;
1132} 952}
1133 953
1134Result Controller_NPad::SetGyroscopeZeroDriftMode( 954Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1135 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1136 Core::HID::GyroscopeZeroDriftMode drift_mode) {
1137 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1138 if (is_valid.IsError()) {
1139 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1140 return is_valid;
1141 }
1142
1143 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1144 auto& controller = GetControllerFromHandle(sixaxis_handle);
1145 sixaxis.gyroscope_zero_drift_mode = drift_mode;
1146 controller.device->SetGyroscopeZeroDriftMode(drift_mode);
1147
1148 return ResultSuccess;
1149}
1150
1151Result Controller_NPad::GetGyroscopeZeroDriftMode(
1152 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1153 Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
1154 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1155 if (is_valid.IsError()) {
1156 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1157 return is_valid;
1158 }
1159
1160 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1161 drift_mode = sixaxis.gyroscope_zero_drift_mode;
1162
1163 return ResultSuccess;
1164}
1165
1166Result Controller_NPad::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1167 bool& is_at_rest) const {
1168 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1169 if (is_valid.IsError()) {
1170 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1171 return is_valid;
1172 }
1173
1174 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1175 is_at_rest = controller.sixaxis_at_rest;
1176 return ResultSuccess;
1177}
1178
1179Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1180 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const { 955 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
1181 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 956 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
1182 if (is_valid.IsError()) { 957 if (is_valid.IsError()) {
1183 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); 958 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1184 return is_valid; 959 return is_valid;
@@ -1189,65 +964,9 @@ Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1189 return ResultSuccess; 964 return ResultSuccess;
1190} 965}
1191 966
1192Result Controller_NPad::EnableSixAxisSensorUnalteredPassthrough( 967Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1193 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
1194 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1195 if (is_valid.IsError()) {
1196 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1197 return is_valid;
1198 }
1199
1200 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1201 sixaxis.unaltered_passtrough = is_enabled;
1202 return ResultSuccess;
1203}
1204
1205Result Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
1206 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
1207 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1208 if (is_valid.IsError()) {
1209 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1210 return is_valid;
1211 }
1212
1213 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1214 is_enabled = sixaxis.unaltered_passtrough;
1215 return ResultSuccess;
1216}
1217
1218Result Controller_NPad::LoadSixAxisSensorCalibrationParameter(
1219 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1220 Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
1221 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1222 if (is_valid.IsError()) {
1223 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1224 return is_valid;
1225 }
1226
1227 // TODO: Request this data to the controller. On error return 0xd8ca
1228 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1229 calibration = sixaxis.calibration;
1230 return ResultSuccess;
1231}
1232
1233Result Controller_NPad::GetSixAxisSensorIcInformation(
1234 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1235 Core::HID::SixAxisSensorIcInformation& ic_information) const {
1236 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1237 if (is_valid.IsError()) {
1238 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1239 return is_valid;
1240 }
1241
1242 // TODO: Request this data to the controller. On error return 0xd8ca
1243 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1244 ic_information = sixaxis.ic_information;
1245 return ResultSuccess;
1246}
1247
1248Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1249 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 968 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1250 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 969 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
1251 if (is_valid.IsError()) { 970 if (is_valid.IsError()) {
1252 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); 971 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1253 return is_valid; 972 return is_valid;
@@ -1259,83 +978,32 @@ Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1259 return ResultSuccess; 978 return ResultSuccess;
1260} 979}
1261 980
1262Result Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 981NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
1263 bool sixaxis_status) { 982 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
1264 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1265 if (is_valid.IsError()) {
1266 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1267 return is_valid;
1268 }
1269
1270 auto& controller = GetControllerFromHandle(sixaxis_handle);
1271 controller.sixaxis_sensor_enabled = sixaxis_status;
1272 return ResultSuccess;
1273} 983}
1274 984
1275Result Controller_NPad::IsSixAxisSensorFusionEnabled( 985NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
1276 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const { 986 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
1277 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1278 if (is_valid.IsError()) {
1279 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1280 return is_valid;
1281 }
1282
1283 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1284 is_fusion_enabled = sixaxis.is_fusion_enabled;
1285
1286 return ResultSuccess;
1287} 987}
1288Result Controller_NPad::SetSixAxisFusionEnabled(
1289 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
1290 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1291 if (is_valid.IsError()) {
1292 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1293 return is_valid;
1294 }
1295 988
1296 auto& sixaxis = GetSixaxisState(sixaxis_handle); 989NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
1297 sixaxis.is_fusion_enabled = is_fusion_enabled; 990 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
1298
1299 return ResultSuccess;
1300} 991}
1301 992
1302Result Controller_NPad::SetSixAxisFusionParameters( 993NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
1303 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 994 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
1304 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
1305 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1306 if (is_valid.IsError()) {
1307 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1308 return is_valid;
1309 }
1310
1311 const auto param1 = sixaxis_fusion_parameters.parameter1;
1312 if (param1 < 0.0f || param1 > 1.0f) {
1313 return InvalidSixAxisFusionRange;
1314 }
1315
1316 auto& sixaxis = GetSixaxisState(sixaxis_handle);
1317 sixaxis.fusion = sixaxis_fusion_parameters;
1318
1319 return ResultSuccess;
1320} 995}
1321 996
1322Result Controller_NPad::GetSixAxisFusionParameters( 997NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
1323 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 998 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
1324 Core::HID::SixAxisSensorFusionParameters& parameters) const { 999}
1325 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1326 if (is_valid.IsError()) {
1327 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
1328 return is_valid;
1329 }
1330
1331 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
1332 parameters = sixaxis.fusion;
1333 1000
1334 return ResultSuccess; 1001NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
1002 return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
1335} 1003}
1336 1004
1337Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, 1005Result NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1338 Core::HID::NpadIdType npad_id_2) { 1006 Core::HID::NpadIdType npad_id_2) {
1339 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1007 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1340 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1008 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1341 npad_id_2); 1009 npad_id_2);
@@ -1397,18 +1065,17 @@ Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1397 return ResultSuccess; 1065 return ResultSuccess;
1398} 1066}
1399 1067
1400void Controller_NPad::StartLRAssignmentMode() { 1068void NPad::StartLRAssignmentMode() {
1401 // Nothing internally is used for lr assignment mode. Since we have the ability to set the 1069 // Nothing internally is used for lr assignment mode. Since we have the ability to set the
1402 // controller types from boot, it doesn't really matter about showing a selection screen 1070 // controller types from boot, it doesn't really matter about showing a selection screen
1403 is_in_lr_assignment_mode = true; 1071 is_in_lr_assignment_mode = true;
1404} 1072}
1405 1073
1406void Controller_NPad::StopLRAssignmentMode() { 1074void NPad::StopLRAssignmentMode() {
1407 is_in_lr_assignment_mode = false; 1075 is_in_lr_assignment_mode = false;
1408} 1076}
1409 1077
1410Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, 1078Result NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) {
1411 Core::HID::NpadIdType npad_id_2) {
1412 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1079 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1413 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1080 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1414 npad_id_2); 1081 npad_id_2);
@@ -1439,8 +1106,7 @@ Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1439 return ResultSuccess; 1106 return ResultSuccess;
1440} 1107}
1441 1108
1442Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id, 1109Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
1443 Core::HID::LedPattern& pattern) const {
1444 if (!IsNpadIdValid(npad_id)) { 1110 if (!IsNpadIdValid(npad_id)) {
1445 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1111 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1446 return InvalidNpadId; 1112 return InvalidNpadId;
@@ -1450,8 +1116,8 @@ Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
1450 return ResultSuccess; 1116 return ResultSuccess;
1451} 1117}
1452 1118
1453Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, 1119Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
1454 bool& is_valid) const { 1120 bool& is_valid) const {
1455 if (!IsNpadIdValid(npad_id)) { 1121 if (!IsNpadIdValid(npad_id)) {
1456 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1122 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1457 return InvalidNpadId; 1123 return InvalidNpadId;
@@ -1461,8 +1127,8 @@ Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::
1461 return ResultSuccess; 1127 return ResultSuccess;
1462} 1128}
1463 1129
1464Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled( 1130Result NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
1465 bool is_protection_enabled, Core::HID::NpadIdType npad_id) { 1131 Core::HID::NpadIdType npad_id) {
1466 if (!IsNpadIdValid(npad_id)) { 1132 if (!IsNpadIdValid(npad_id)) {
1467 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1133 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1468 return InvalidNpadId; 1134 return InvalidNpadId;
@@ -1472,11 +1138,11 @@ Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
1472 return ResultSuccess; 1138 return ResultSuccess;
1473} 1139}
1474 1140
1475void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) { 1141void NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
1476 analog_stick_use_center_clamp = use_center_clamp; 1142 analog_stick_use_center_clamp = use_center_clamp;
1477} 1143}
1478 1144
1479void Controller_NPad::ClearAllConnectedControllers() { 1145void NPad::ClearAllConnectedControllers() {
1480 for (auto& controller : controller_data) { 1146 for (auto& controller : controller_data) {
1481 if (controller.device->IsConnected() && 1147 if (controller.device->IsConnected() &&
1482 controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) { 1148 controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
@@ -1486,13 +1152,13 @@ void Controller_NPad::ClearAllConnectedControllers() {
1486 } 1152 }
1487} 1153}
1488 1154
1489void Controller_NPad::DisconnectAllConnectedControllers() { 1155void NPad::DisconnectAllConnectedControllers() {
1490 for (auto& controller : controller_data) { 1156 for (auto& controller : controller_data) {
1491 controller.device->Disconnect(); 1157 controller.device->Disconnect();
1492 } 1158 }
1493} 1159}
1494 1160
1495void Controller_NPad::ConnectAllDisconnectedControllers() { 1161void NPad::ConnectAllDisconnectedControllers() {
1496 for (auto& controller : controller_data) { 1162 for (auto& controller : controller_data) {
1497 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None && 1163 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
1498 !controller.device->IsConnected()) { 1164 !controller.device->IsConnected()) {
@@ -1501,18 +1167,18 @@ void Controller_NPad::ConnectAllDisconnectedControllers() {
1501 } 1167 }
1502} 1168}
1503 1169
1504void Controller_NPad::ClearAllControllers() { 1170void NPad::ClearAllControllers() {
1505 for (auto& controller : controller_data) { 1171 for (auto& controller : controller_data) {
1506 controller.device->Disconnect(); 1172 controller.device->Disconnect();
1507 controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None); 1173 controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
1508 } 1174 }
1509} 1175}
1510 1176
1511Core::HID::NpadButton Controller_NPad::GetAndResetPressState() { 1177Core::HID::NpadButton NPad::GetAndResetPressState() {
1512 return static_cast<Core::HID::NpadButton>(press_state.exchange(0)); 1178 return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
1513} 1179}
1514 1180
1515void Controller_NPad::ApplyNpadSystemCommonPolicy() { 1181void NPad::ApplyNpadSystemCommonPolicy() {
1516 Core::HID::NpadStyleTag styletag{}; 1182 Core::HID::NpadStyleTag styletag{};
1517 styletag.fullkey.Assign(1); 1183 styletag.fullkey.Assign(1);
1518 styletag.handheld.Assign(1); 1184 styletag.handheld.Assign(1);
@@ -1537,7 +1203,7 @@ void Controller_NPad::ApplyNpadSystemCommonPolicy() {
1537 supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld; 1203 supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld;
1538} 1204}
1539 1205
1540bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const { 1206bool NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
1541 if (controller == Core::HID::NpadStyleIndex::Handheld) { 1207 if (controller == Core::HID::NpadStyleIndex::Handheld) {
1542 const bool support_handheld = 1208 const bool support_handheld =
1543 std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 1209 std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
@@ -1588,51 +1254,50 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
1588 return false; 1254 return false;
1589} 1255}
1590 1256
1591Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1257NPad::NpadControllerData& NPad::GetControllerFromHandle(
1592 const Core::HID::SixAxisSensorHandle& device_handle) { 1258 const Core::HID::VibrationDeviceHandle& device_handle) {
1593 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1259 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1594 return GetControllerFromNpadIdType(npad_id); 1260 return GetControllerFromNpadIdType(npad_id);
1595} 1261}
1596 1262
1597const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1263const NPad::NpadControllerData& NPad::GetControllerFromHandle(
1598 const Core::HID::SixAxisSensorHandle& device_handle) const { 1264 const Core::HID::VibrationDeviceHandle& device_handle) const {
1599 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1265 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1600 return GetControllerFromNpadIdType(npad_id); 1266 return GetControllerFromNpadIdType(npad_id);
1601} 1267}
1602 1268
1603Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1269NPad::NpadControllerData& NPad::GetControllerFromHandle(
1604 const Core::HID::VibrationDeviceHandle& device_handle) { 1270 const Core::HID::SixAxisSensorHandle& device_handle) {
1605 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1271 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1606 return GetControllerFromNpadIdType(npad_id); 1272 return GetControllerFromNpadIdType(npad_id);
1607} 1273}
1608 1274
1609const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle( 1275const NPad::NpadControllerData& NPad::GetControllerFromHandle(
1610 const Core::HID::VibrationDeviceHandle& device_handle) const { 1276 const Core::HID::SixAxisSensorHandle& device_handle) const {
1611 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1277 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1612 return GetControllerFromNpadIdType(npad_id); 1278 return GetControllerFromNpadIdType(npad_id);
1613} 1279}
1614 1280
1615Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType( 1281NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
1616 Core::HID::NpadIdType npad_id) {
1617 if (!IsNpadIdValid(npad_id)) { 1282 if (!IsNpadIdValid(npad_id)) {
1618 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1283 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1619 npad_id = Core::HID::NpadIdType::Player1; 1284 npad_id = Core::HID::NpadIdType::Player1;
1620 } 1285 }
1621 const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id); 1286 const auto npad_index = NpadIdTypeToIndex(npad_id);
1622 return controller_data[npad_index]; 1287 return controller_data[npad_index];
1623} 1288}
1624 1289
1625const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType( 1290const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(
1626 Core::HID::NpadIdType npad_id) const { 1291 Core::HID::NpadIdType npad_id) const {
1627 if (!IsNpadIdValid(npad_id)) { 1292 if (!IsNpadIdValid(npad_id)) {
1628 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1293 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1629 npad_id = Core::HID::NpadIdType::Player1; 1294 npad_id = Core::HID::NpadIdType::Player1;
1630 } 1295 }
1631 const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id); 1296 const auto npad_index = NpadIdTypeToIndex(npad_id);
1632 return controller_data[npad_index]; 1297 return controller_data[npad_index];
1633} 1298}
1634 1299
1635Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties( 1300Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
1636 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 1301 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1637 auto& controller = GetControllerFromHandle(sixaxis_handle); 1302 auto& controller = GetControllerFromHandle(sixaxis_handle);
1638 switch (sixaxis_handle.npad_type) { 1303 switch (sixaxis_handle.npad_type) {
@@ -1655,7 +1320,7 @@ Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
1655 } 1320 }
1656} 1321}
1657 1322
1658const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties( 1323const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
1659 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { 1324 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
1660 const auto& controller = GetControllerFromHandle(sixaxis_handle); 1325 const auto& controller = GetControllerFromHandle(sixaxis_handle);
1661 switch (sixaxis_handle.npad_type) { 1326 switch (sixaxis_handle.npad_type) {
@@ -1678,50 +1343,13 @@ const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
1678 } 1343 }
1679} 1344}
1680 1345
1681Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState( 1346NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
1682 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 1347 const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
1683 auto& controller = GetControllerFromHandle(sixaxis_handle);
1684 switch (sixaxis_handle.npad_type) {
1685 case Core::HID::NpadStyleIndex::ProController:
1686 case Core::HID::NpadStyleIndex::Pokeball:
1687 return controller.sixaxis_fullkey;
1688 case Core::HID::NpadStyleIndex::Handheld:
1689 return controller.sixaxis_handheld;
1690 case Core::HID::NpadStyleIndex::JoyconDual:
1691 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1692 return controller.sixaxis_dual_left;
1693 }
1694 return controller.sixaxis_dual_right;
1695 case Core::HID::NpadStyleIndex::JoyconLeft:
1696 return controller.sixaxis_left;
1697 case Core::HID::NpadStyleIndex::JoyconRight:
1698 return controller.sixaxis_right;
1699 default:
1700 return controller.sixaxis_unknown;
1701 }
1702}
1703 1348
1704const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState( 1349 return {
1705 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const { 1350 .ui_variant = 0,
1706 const auto& controller = GetControllerFromHandle(sixaxis_handle); 1351 .footer = shared_memory->applet_footer_type,
1707 switch (sixaxis_handle.npad_type) { 1352 };
1708 case Core::HID::NpadStyleIndex::ProController:
1709 case Core::HID::NpadStyleIndex::Pokeball:
1710 return controller.sixaxis_fullkey;
1711 case Core::HID::NpadStyleIndex::Handheld:
1712 return controller.sixaxis_handheld;
1713 case Core::HID::NpadStyleIndex::JoyconDual:
1714 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
1715 return controller.sixaxis_dual_left;
1716 }
1717 return controller.sixaxis_dual_right;
1718 case Core::HID::NpadStyleIndex::JoyconLeft:
1719 return controller.sixaxis_left;
1720 case Core::HID::NpadStyleIndex::JoyconRight:
1721 return controller.sixaxis_right;
1722 default:
1723 return controller.sixaxis_unknown;
1724 }
1725} 1353}
1726 1354
1727} // namespace Service::HID 1355} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 949e58a4c..9167c93f0 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -10,7 +10,6 @@
10 10
11#include "common/bit_field.h" 11#include "common/bit_field.h"
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/vector_math.h"
14 13
15#include "core/hid/hid_types.h" 14#include "core/hid/hid_types.h"
16#include "core/hle/service/hid/controllers/controller_base.h" 15#include "core/hle/service/hid/controllers/controller_base.h"
@@ -34,11 +33,11 @@ union Result;
34 33
35namespace Service::HID { 34namespace Service::HID {
36 35
37class Controller_NPad final : public ControllerBase { 36class NPad final : public ControllerBase {
38public: 37public:
39 explicit Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 38 explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
40 KernelHelpers::ServiceContext& service_context_); 39 KernelHelpers::ServiceContext& service_context_);
41 ~Controller_NPad() override; 40 ~NPad() override;
42 41
43 // Called when the controller is initialized 42 // Called when the controller is initialized
44 void OnInit() override; 43 void OnInit() override;
@@ -49,9 +48,6 @@ public:
49 // When the controller is requesting an update for the shared memory 48 // When the controller is requesting an update for the shared memory
50 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override; 49 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
51 50
52 // When the controller is requesting a motion update for the shared memory
53 void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;
54
55 // This is nn::hid::NpadJoyHoldType 51 // This is nn::hid::NpadJoyHoldType
56 enum class NpadJoyHoldType : u64 { 52 enum class NpadJoyHoldType : u64 {
57 Vertical = 0, 53 Vertical = 0,
@@ -78,6 +74,46 @@ public:
78 MaxActivationMode = 3, 74 MaxActivationMode = 3,
79 }; 75 };
80 76
77 // This is nn::hid::system::AppletFooterUiAttributesSet
78 struct AppletFooterUiAttributes {
79 INSERT_PADDING_BYTES(0x4);
80 };
81
82 // This is nn::hid::system::AppletFooterUiType
83 enum class AppletFooterUiType : u8 {
84 None = 0,
85 HandheldNone = 1,
86 HandheldJoyConLeftOnly = 2,
87 HandheldJoyConRightOnly = 3,
88 HandheldJoyConLeftJoyConRight = 4,
89 JoyDual = 5,
90 JoyDualLeftOnly = 6,
91 JoyDualRightOnly = 7,
92 JoyLeftHorizontal = 8,
93 JoyLeftVertical = 9,
94 JoyRightHorizontal = 10,
95 JoyRightVertical = 11,
96 SwitchProController = 12,
97 CompatibleProController = 13,
98 CompatibleJoyCon = 14,
99 LarkHvc1 = 15,
100 LarkHvc2 = 16,
101 LarkNesLeft = 17,
102 LarkNesRight = 18,
103 Lucia = 19,
104 Verification = 20,
105 Lagon = 21,
106 };
107
108 using AppletFooterUiVariant = u8;
109
110 // This is "nn::hid::system::AppletDetailedUiType".
111 struct AppletDetailedUiType {
112 AppletFooterUiVariant ui_variant;
113 INSERT_PADDING_BYTES(0x2);
114 AppletFooterUiType footer;
115 };
116 static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
81 // This is nn::hid::NpadCommunicationMode 117 // This is nn::hid::NpadCommunicationMode
82 enum class NpadCommunicationMode : u64 { 118 enum class NpadCommunicationMode : u64 {
83 Mode_5ms = 0, 119 Mode_5ms = 0,
@@ -86,6 +122,15 @@ public:
86 Default = 3, 122 Default = 3,
87 }; 123 };
88 124
125 enum class NpadRevision : u32 {
126 Revision0 = 0,
127 Revision1 = 1,
128 Revision2 = 2,
129 Revision3 = 3,
130 };
131
132 using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
133
89 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); 134 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
90 Core::HID::NpadStyleTag GetSupportedStyleSet() const; 135 Core::HID::NpadStyleTag GetSupportedStyleSet() const;
91 136
@@ -138,37 +183,18 @@ public:
138 183
139 Result DisconnectNpad(Core::HID::NpadIdType npad_id); 184 Result DisconnectNpad(Core::HID::NpadIdType npad_id);
140 185
141 Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
142 Core::HID::GyroscopeZeroDriftMode drift_mode);
143 Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
144 Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
145 Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
146 bool& is_at_rest) const;
147 Result IsFirmwareUpdateAvailableForSixAxisSensor( 186 Result IsFirmwareUpdateAvailableForSixAxisSensor(
148 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const; 187 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const;
149 Result EnableSixAxisSensorUnalteredPassthrough(
150 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
151 Result IsSixAxisSensorUnalteredPassthroughEnabled(
152 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
153 Result LoadSixAxisSensorCalibrationParameter(
154 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
155 Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
156 Result GetSixAxisSensorIcInformation(
157 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
158 Core::HID::SixAxisSensorIcInformation& ic_information) const;
159 Result ResetIsSixAxisSensorDeviceNewlyAssigned( 188 Result ResetIsSixAxisSensorDeviceNewlyAssigned(
160 const Core::HID::SixAxisSensorHandle& sixaxis_handle); 189 const Core::HID::SixAxisSensorHandle& sixaxis_handle);
161 Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 190
162 bool sixaxis_status); 191 SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
163 Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 192 SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
164 bool& is_fusion_enabled) const; 193 SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
165 Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 194 SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
166 bool is_fusion_enabled); 195 SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
167 Result SetSixAxisFusionParameters( 196 SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
168 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 197
169 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
170 Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
171 Core::HID::SixAxisSensorFusionParameters& parameters) const;
172 Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; 198 Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
173 Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, 199 Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
174 bool& is_enabled) const; 200 bool& is_enabled) const;
@@ -192,10 +218,7 @@ public:
192 218
193 void ApplyNpadSystemCommonPolicy(); 219 void ApplyNpadSystemCommonPolicy();
194 220
195 static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); 221 AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
196 static Result IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
197 static Result VerifyValidSixAxisSensorHandle(
198 const Core::HID::SixAxisSensorHandle& device_handle);
199 222
200private: 223private:
201 static constexpr std::size_t NPAD_COUNT = 10; 224 static constexpr std::size_t NPAD_COUNT = 10;
@@ -254,29 +277,6 @@ private:
254 }; 277 };
255 static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size"); 278 static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
256 279
257 // This is nn::hid::SixAxisSensorAttribute
258 struct SixAxisSensorAttribute {
259 union {
260 u32 raw{};
261 BitField<0, 1, u32> is_connected;
262 BitField<1, 1, u32> is_interpolated;
263 };
264 };
265 static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
266
267 // This is nn::hid::SixAxisSensorState
268 struct SixAxisSensorState {
269 s64 delta_time{};
270 s64 sampling_number{};
271 Common::Vec3f accel{};
272 Common::Vec3f gyro{};
273 Common::Vec3f rotation{};
274 std::array<Common::Vec3f, 3> orientation{};
275 SixAxisSensorAttribute attribute{};
276 INSERT_PADDING_BYTES(4); // Reserved
277 };
278 static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
279
280 // This is nn::hid::server::NpadGcTriggerState 280 // This is nn::hid::server::NpadGcTriggerState
281 struct NpadGcTriggerState { 281 struct NpadGcTriggerState {
282 s64 sampling_number{}; 282 s64 sampling_number{};
@@ -353,37 +353,6 @@ private:
353 static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18, 353 static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
354 "NfcXcdDeviceHandleStateImpl is an invalid size"); 354 "NfcXcdDeviceHandleStateImpl is an invalid size");
355 355
356 // This is nn::hid::system::AppletFooterUiAttributesSet
357 struct AppletFooterUiAttributes {
358 INSERT_PADDING_BYTES(0x4);
359 };
360
361 // This is nn::hid::system::AppletFooterUiType
362 enum class AppletFooterUiType : u8 {
363 None = 0,
364 HandheldNone = 1,
365 HandheldJoyConLeftOnly = 2,
366 HandheldJoyConRightOnly = 3,
367 HandheldJoyConLeftJoyConRight = 4,
368 JoyDual = 5,
369 JoyDualLeftOnly = 6,
370 JoyDualRightOnly = 7,
371 JoyLeftHorizontal = 8,
372 JoyLeftVertical = 9,
373 JoyRightHorizontal = 10,
374 JoyRightVertical = 11,
375 SwitchProController = 12,
376 CompatibleProController = 13,
377 CompatibleJoyCon = 14,
378 LarkHvc1 = 15,
379 LarkHvc2 = 16,
380 LarkNesLeft = 17,
381 LarkNesRight = 18,
382 Lucia = 19,
383 Verification = 20,
384 Lagon = 21,
385 };
386
387 // This is nn::hid::NpadLarkType 356 // This is nn::hid::NpadLarkType
388 enum class NpadLarkType : u32 { 357 enum class NpadLarkType : u32 {
389 Invalid, 358 Invalid,
@@ -427,12 +396,12 @@ private:
427 Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{}; 396 Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
428 Lifo<NPadGenericState, hid_entry_count> palma_lifo{}; 397 Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
429 Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{}; 398 Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
430 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{}; 399 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
431 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{}; 400 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
432 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{}; 401 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
433 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{}; 402 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
434 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{}; 403 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
435 Lifo<SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{}; 404 Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
436 DeviceType device_type{}; 405 DeviceType device_type{};
437 INSERT_PADDING_BYTES(0x4); // Reserved 406 INSERT_PADDING_BYTES(0x4); // Reserved
438 NPadSystemProperties system_properties{}; 407 NPadSystemProperties system_properties{};
@@ -466,16 +435,6 @@ private:
466 std::chrono::steady_clock::time_point last_vibration_timepoint{}; 435 std::chrono::steady_clock::time_point last_vibration_timepoint{};
467 }; 436 };
468 437
469 struct SixaxisParameters {
470 bool is_fusion_enabled{true};
471 bool unaltered_passtrough{false};
472 Core::HID::SixAxisSensorFusionParameters fusion{};
473 Core::HID::SixAxisSensorCalibrationParameter calibration{};
474 Core::HID::SixAxisSensorIcInformation ic_information{};
475 Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
476 Core::HID::GyroscopeZeroDriftMode::Standard};
477 };
478
479 struct NpadControllerData { 438 struct NpadControllerData {
480 Kernel::KEvent* styleset_changed_event{}; 439 Kernel::KEvent* styleset_changed_event{};
481 NpadInternalState* shared_memory = nullptr; 440 NpadInternalState* shared_memory = nullptr;
@@ -489,27 +448,10 @@ private:
489 bool is_dual_left_connected{true}; 448 bool is_dual_left_connected{true};
490 bool is_dual_right_connected{true}; 449 bool is_dual_right_connected{true};
491 450
492 // Motion parameters
493 bool sixaxis_at_rest{true};
494 bool sixaxis_sensor_enabled{true};
495 SixaxisParameters sixaxis_fullkey{};
496 SixaxisParameters sixaxis_handheld{};
497 SixaxisParameters sixaxis_dual_left{};
498 SixaxisParameters sixaxis_dual_right{};
499 SixaxisParameters sixaxis_left{};
500 SixaxisParameters sixaxis_right{};
501 SixaxisParameters sixaxis_unknown{};
502
503 // Current pad state 451 // Current pad state
504 NPadGenericState npad_pad_state{}; 452 NPadGenericState npad_pad_state{};
505 NPadGenericState npad_libnx_state{}; 453 NPadGenericState npad_libnx_state{};
506 NpadGcTriggerState npad_trigger_state{}; 454 NpadGcTriggerState npad_trigger_state{};
507 SixAxisSensorState sixaxis_fullkey_state{};
508 SixAxisSensorState sixaxis_handheld_state{};
509 SixAxisSensorState sixaxis_dual_left_state{};
510 SixAxisSensorState sixaxis_dual_right_state{};
511 SixAxisSensorState sixaxis_left_lifo_state{};
512 SixAxisSensorState sixaxis_right_lifo_state{};
513 int callback_key{}; 455 int callback_key{};
514 }; 456 };
515 457
@@ -520,13 +462,13 @@ private:
520 void WriteEmptyEntry(NpadInternalState* npad); 462 void WriteEmptyEntry(NpadInternalState* npad);
521 463
522 NpadControllerData& GetControllerFromHandle( 464 NpadControllerData& GetControllerFromHandle(
523 const Core::HID::SixAxisSensorHandle& device_handle);
524 const NpadControllerData& GetControllerFromHandle(
525 const Core::HID::SixAxisSensorHandle& device_handle) const;
526 NpadControllerData& GetControllerFromHandle(
527 const Core::HID::VibrationDeviceHandle& device_handle); 465 const Core::HID::VibrationDeviceHandle& device_handle);
528 const NpadControllerData& GetControllerFromHandle( 466 const NpadControllerData& GetControllerFromHandle(
529 const Core::HID::VibrationDeviceHandle& device_handle) const; 467 const Core::HID::VibrationDeviceHandle& device_handle) const;
468 NpadControllerData& GetControllerFromHandle(
469 const Core::HID::SixAxisSensorHandle& device_handle);
470 const NpadControllerData& GetControllerFromHandle(
471 const Core::HID::SixAxisSensorHandle& device_handle) const;
530 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); 472 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
531 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; 473 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
532 474
@@ -534,9 +476,6 @@ private:
534 const Core::HID::SixAxisSensorHandle& device_handle); 476 const Core::HID::SixAxisSensorHandle& device_handle);
535 const Core::HID::SixAxisSensorProperties& GetSixaxisProperties( 477 const Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
536 const Core::HID::SixAxisSensorHandle& device_handle) const; 478 const Core::HID::SixAxisSensorHandle& device_handle) const;
537 SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
538 const SixaxisParameters& GetSixaxisState(
539 const Core::HID::SixAxisSensorHandle& device_handle) const;
540 479
541 std::atomic<u64> press_state{}; 480 std::atomic<u64> press_state{};
542 481
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp
index 73a2a2b91..588ff9d62 100644
--- a/src/core/hle/service/hid/controllers/palma.cpp
+++ b/src/core/hle/service/hid/controllers/palma.cpp
@@ -12,43 +12,43 @@
12 12
13namespace Service::HID { 13namespace Service::HID {
14 14
15Controller_Palma::Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 15Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
16 KernelHelpers::ServiceContext& service_context_) 16 KernelHelpers::ServiceContext& service_context_)
17 : ControllerBase{hid_core_}, service_context{service_context_} { 17 : ControllerBase{hid_core_}, service_context{service_context_} {
18 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); 18 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
19 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); 19 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
20} 20}
21 21
22Controller_Palma::~Controller_Palma() { 22Palma::~Palma() {
23 service_context.CloseEvent(operation_complete_event); 23 service_context.CloseEvent(operation_complete_event);
24}; 24};
25 25
26void Controller_Palma::OnInit() {} 26void Palma::OnInit() {}
27 27
28void Controller_Palma::OnRelease() {} 28void Palma::OnRelease() {}
29 29
30void Controller_Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 30void Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
31 if (!IsControllerActivated()) { 31 if (!IsControllerActivated()) {
32 return; 32 return;
33 } 33 }
34} 34}
35 35
36Result Controller_Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id, 36Result Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id,
37 PalmaConnectionHandle& handle) { 37 PalmaConnectionHandle& handle) {
38 active_handle.npad_id = npad_id; 38 active_handle.npad_id = npad_id;
39 handle = active_handle; 39 handle = active_handle;
40 return ResultSuccess; 40 return ResultSuccess;
41} 41}
42 42
43Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) { 43Result Palma::InitializePalma(const PalmaConnectionHandle& handle) {
44 if (handle.npad_id != active_handle.npad_id) { 44 if (handle.npad_id != active_handle.npad_id) {
45 return InvalidPalmaHandle; 45 return InvalidPalmaHandle;
46 } 46 }
47 ActivateController(); 47 Activate();
48 return ResultSuccess; 48 return ResultSuccess;
49} 49}
50 50
51Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent( 51Kernel::KReadableEvent& Palma::AcquirePalmaOperationCompleteEvent(
52 const PalmaConnectionHandle& handle) const { 52 const PalmaConnectionHandle& handle) const {
53 if (handle.npad_id != active_handle.npad_id) { 53 if (handle.npad_id != active_handle.npad_id) {
54 LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id); 54 LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id);
@@ -56,9 +56,9 @@ Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent(
56 return operation_complete_event->GetReadableEvent(); 56 return operation_complete_event->GetReadableEvent();
57} 57}
58 58
59Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle, 59Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle,
60 PalmaOperationType& operation_type, 60 PalmaOperationType& operation_type,
61 PalmaOperationData& data) const { 61 PalmaOperationData& data) const {
62 if (handle.npad_id != active_handle.npad_id) { 62 if (handle.npad_id != active_handle.npad_id) {
63 return InvalidPalmaHandle; 63 return InvalidPalmaHandle;
64 } 64 }
@@ -67,8 +67,7 @@ Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& hand
67 return ResultSuccess; 67 return ResultSuccess;
68} 68}
69 69
70Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, 70Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity) {
71 u64 palma_activity) {
72 if (handle.npad_id != active_handle.npad_id) { 71 if (handle.npad_id != active_handle.npad_id) {
73 return InvalidPalmaHandle; 72 return InvalidPalmaHandle;
74 } 73 }
@@ -79,8 +78,7 @@ Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle,
79 return ResultSuccess; 78 return ResultSuccess;
80} 79}
81 80
82Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, 81Result Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_) {
83 PalmaFrModeType fr_mode_) {
84 if (handle.npad_id != active_handle.npad_id) { 82 if (handle.npad_id != active_handle.npad_id) {
85 return InvalidPalmaHandle; 83 return InvalidPalmaHandle;
86 } 84 }
@@ -88,7 +86,7 @@ Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle,
88 return ResultSuccess; 86 return ResultSuccess;
89} 87}
90 88
91Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { 89Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
92 if (handle.npad_id != active_handle.npad_id) { 90 if (handle.npad_id != active_handle.npad_id) {
93 return InvalidPalmaHandle; 91 return InvalidPalmaHandle;
94 } 92 }
@@ -99,25 +97,25 @@ Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
99 return ResultSuccess; 97 return ResultSuccess;
100} 98}
101 99
102Result Controller_Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) { 100Result Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) {
103 if (handle.npad_id != active_handle.npad_id) { 101 if (handle.npad_id != active_handle.npad_id) {
104 return InvalidPalmaHandle; 102 return InvalidPalmaHandle;
105 } 103 }
106 return ResultSuccess; 104 return ResultSuccess;
107} 105}
108 106
109Result Controller_Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) { 107Result Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) {
110 if (handle.npad_id != active_handle.npad_id) { 108 if (handle.npad_id != active_handle.npad_id) {
111 return InvalidPalmaHandle; 109 return InvalidPalmaHandle;
112 } 110 }
113 return ResultSuccess; 111 return ResultSuccess;
114} 112}
115 113
116void Controller_Palma::ReadPalmaApplicationSection() {} 114void Palma::ReadPalmaApplicationSection() {}
117 115
118void Controller_Palma::WritePalmaApplicationSection() {} 116void Palma::WritePalmaApplicationSection() {}
119 117
120Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { 118Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) {
121 if (handle.npad_id != active_handle.npad_id) { 119 if (handle.npad_id != active_handle.npad_id) {
122 return InvalidPalmaHandle; 120 return InvalidPalmaHandle;
123 } 121 }
@@ -128,7 +126,7 @@ Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle
128 return ResultSuccess; 126 return ResultSuccess;
129} 127}
130 128
131Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { 129Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) {
132 if (handle.npad_id != active_handle.npad_id) { 130 if (handle.npad_id != active_handle.npad_id) {
133 return InvalidPalmaHandle; 131 return InvalidPalmaHandle;
134 } 132 }
@@ -139,10 +137,9 @@ Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle&
139 return ResultSuccess; 137 return ResultSuccess;
140} 138}
141 139
142void Controller_Palma::WritePalmaActivityEntry() {} 140void Palma::WritePalmaActivityEntry() {}
143 141
144Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, 142Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown) {
145 u64 unknown) {
146 if (handle.npad_id != active_handle.npad_id) { 143 if (handle.npad_id != active_handle.npad_id) {
147 return InvalidPalmaHandle; 144 return InvalidPalmaHandle;
148 } 145 }
@@ -153,8 +150,8 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl
153 return ResultSuccess; 150 return ResultSuccess;
154} 151}
155 152
156Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave, 153Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
157 Common::ProcessAddress t_mem, u64 size) { 154 Common::ProcessAddress t_mem, u64 size) {
158 if (handle.npad_id != active_handle.npad_id) { 155 if (handle.npad_id != active_handle.npad_id) {
159 return InvalidPalmaHandle; 156 return InvalidPalmaHandle;
160 } 157 }
@@ -165,8 +162,8 @@ Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle
165 return ResultSuccess; 162 return ResultSuccess;
166} 163}
167 164
168Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle, 165Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle,
169 s32 database_id_version_) { 166 s32 database_id_version_) {
170 if (handle.npad_id != active_handle.npad_id) { 167 if (handle.npad_id != active_handle.npad_id) {
171 return InvalidPalmaHandle; 168 return InvalidPalmaHandle;
172 } 169 }
@@ -178,8 +175,7 @@ Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnec
178 return ResultSuccess; 175 return ResultSuccess;
179} 176}
180 177
181Result Controller_Palma::GetPalmaDataBaseIdentificationVersion( 178Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle) {
182 const PalmaConnectionHandle& handle) {
183 if (handle.npad_id != active_handle.npad_id) { 179 if (handle.npad_id != active_handle.npad_id) {
184 return InvalidPalmaHandle; 180 return InvalidPalmaHandle;
185 } 181 }
@@ -191,26 +187,26 @@ Result Controller_Palma::GetPalmaDataBaseIdentificationVersion(
191 return ResultSuccess; 187 return ResultSuccess;
192} 188}
193 189
194void Controller_Palma::SuspendPalmaFeature() {} 190void Palma::SuspendPalmaFeature() {}
195 191
196Result Controller_Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const { 192Result Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const {
197 if (handle.npad_id != active_handle.npad_id) { 193 if (handle.npad_id != active_handle.npad_id) {
198 return InvalidPalmaHandle; 194 return InvalidPalmaHandle;
199 } 195 }
200 return operation.result; 196 return operation.result;
201} 197}
202void Controller_Palma::ReadPalmaPlayLog() {} 198void Palma::ReadPalmaPlayLog() {}
203 199
204void Controller_Palma::ResetPalmaPlayLog() {} 200void Palma::ResetPalmaPlayLog() {}
205 201
206void Controller_Palma::SetIsPalmaAllConnectable(bool is_all_connectable) { 202void Palma::SetIsPalmaAllConnectable(bool is_all_connectable) {
207 // If true controllers are able to be paired 203 // If true controllers are able to be paired
208 is_connectable = is_all_connectable; 204 is_connectable = is_all_connectable;
209} 205}
210 206
211void Controller_Palma::SetIsPalmaPairedConnectable() {} 207void Palma::SetIsPalmaPairedConnectable() {}
212 208
213Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) { 209Result Palma::PairPalma(const PalmaConnectionHandle& handle) {
214 if (handle.npad_id != active_handle.npad_id) { 210 if (handle.npad_id != active_handle.npad_id) {
215 return InvalidPalmaHandle; 211 return InvalidPalmaHandle;
216 } 212 }
@@ -218,14 +214,14 @@ Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) {
218 return ResultSuccess; 214 return ResultSuccess;
219} 215}
220 216
221void Controller_Palma::SetPalmaBoostMode(bool boost_mode) {} 217void Palma::SetPalmaBoostMode(bool boost_mode) {}
222 218
223void Controller_Palma::CancelWritePalmaWaveEntry() {} 219void Palma::CancelWritePalmaWaveEntry() {}
224 220
225void Controller_Palma::EnablePalmaBoostMode() {} 221void Palma::EnablePalmaBoostMode() {}
226 222
227void Controller_Palma::GetPalmaBluetoothAddress() {} 223void Palma::GetPalmaBluetoothAddress() {}
228 224
229void Controller_Palma::SetDisallowedPalmaConnection() {} 225void Palma::SetDisallowedPalmaConnection() {}
230 226
231} // namespace Service::HID 227} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/palma.h b/src/core/hle/service/hid/controllers/palma.h
index a0491a819..a6047f36a 100644
--- a/src/core/hle/service/hid/controllers/palma.h
+++ b/src/core/hle/service/hid/controllers/palma.h
@@ -23,7 +23,7 @@ class EmulatedController;
23} // namespace Core::HID 23} // namespace Core::HID
24 24
25namespace Service::HID { 25namespace Service::HID {
26class Controller_Palma final : public ControllerBase { 26class Palma final : public ControllerBase {
27public: 27public:
28 using PalmaOperationData = std::array<u8, 0x140>; 28 using PalmaOperationData = std::array<u8, 0x140>;
29 29
@@ -97,9 +97,9 @@ public:
97 static_assert(sizeof(PalmaConnectionHandle) == 0x8, 97 static_assert(sizeof(PalmaConnectionHandle) == 0x8,
98 "PalmaConnectionHandle has incorrect size."); 98 "PalmaConnectionHandle has incorrect size.");
99 99
100 explicit Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_, 100 explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
101 KernelHelpers::ServiceContext& service_context_); 101 KernelHelpers::ServiceContext& service_context_);
102 ~Controller_Palma() override; 102 ~Palma() override;
103 103
104 // Called when the controller is initialized 104 // Called when the controller is initialized
105 void OnInit() override; 105 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/seven_six_axis.cpp
index bcb272eaf..495568484 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/seven_six_axis.cpp
@@ -1,32 +1,29 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include <cstring>
5#include "common/common_types.h"
4#include "core/core.h" 6#include "core/core.h"
5#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/frontend/emu_window.h"
6#include "core/hid/emulated_console.h" 9#include "core/hid/emulated_console.h"
10#include "core/hid/emulated_devices.h"
7#include "core/hid/hid_core.h" 11#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/console_sixaxis.h" 12#include "core/hle/service/hid/controllers/seven_six_axis.h"
9#include "core/memory.h" 13#include "core/memory.h"
10 14
11namespace Service::HID { 15namespace Service::HID {
12constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; 16SevenSixAxis::SevenSixAxis(Core::System& system_)
13
14Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_)
15 : ControllerBase{system_.HIDCore()}, system{system_} { 17 : ControllerBase{system_.HIDCore()}, system{system_} {
16 console = hid_core.GetEmulatedConsole(); 18 console = hid_core.GetEmulatedConsole();
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
18 "ConsoleSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
21} 19}
22 20
23Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; 21SevenSixAxis::~SevenSixAxis() = default;
24
25void Controller_ConsoleSixAxis::OnInit() {}
26 22
27void Controller_ConsoleSixAxis::OnRelease() {} 23void SevenSixAxis::OnInit() {}
24void SevenSixAxis::OnRelease() {}
28 25
29void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 26void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 if (!IsControllerActivated() || transfer_memory == 0) { 27 if (!IsControllerActivated() || transfer_memory == 0) {
31 seven_sixaxis_lifo.buffer_count = 0; 28 seven_sixaxis_lifo.buffer_count = 0;
32 seven_sixaxis_lifo.buffer_tail = 0; 29 seven_sixaxis_lifo.buffer_tail = 0;
@@ -53,22 +50,17 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
53 -motion_status.quaternion.xyz.z, 50 -motion_status.quaternion.xyz.z,
54 }; 51 };
55 52
56 shared_memory->sampling_number++;
57 shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
58 shared_memory->verticalization_error = motion_status.verticalization_error;
59 shared_memory->gyro_bias = motion_status.gyro_bias;
60
61 // Update seven six axis transfer memory
62 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); 53 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
63 system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, 54 system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
64 sizeof(seven_sixaxis_lifo)); 55 sizeof(seven_sixaxis_lifo));
65} 56}
66 57
67void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { 58void SevenSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
68 transfer_memory = t_mem; 59 transfer_memory = t_mem;
69} 60}
70 61
71void Controller_ConsoleSixAxis::ResetTimestamp() { 62void SevenSixAxis::ResetTimestamp() {
72 last_saved_timestamp = last_global_timestamp; 63 last_saved_timestamp = last_global_timestamp;
73} 64}
65
74} // namespace Service::HID 66} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/seven_six_axis.h
index 7015d924c..40e3f5d12 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/seven_six_axis.h
@@ -1,10 +1,9 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include <array> 6#include "common/common_types.h"
7
8#include "common/quaternion.h" 7#include "common/quaternion.h"
9#include "common/typed_address.h" 8#include "common/typed_address.h"
10#include "core/hle/service/hid/controllers/controller_base.h" 9#include "core/hle/service/hid/controllers/controller_base.h"
@@ -19,10 +18,10 @@ class EmulatedConsole;
19} // namespace Core::HID 18} // namespace Core::HID
20 19
21namespace Service::HID { 20namespace Service::HID {
22class Controller_ConsoleSixAxis final : public ControllerBase { 21class SevenSixAxis final : public ControllerBase {
23public: 22public:
24 explicit Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_); 23 explicit SevenSixAxis(Core::System& system_);
25 ~Controller_ConsoleSixAxis() override; 24 ~SevenSixAxis() override;
26 25
27 // Called when the controller is initialized 26 // Called when the controller is initialized
28 void OnInit() override; 27 void OnInit() override;
@@ -51,28 +50,16 @@ private:
51 }; 50 };
52 static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size"); 51 static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
53 52
54 // This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
55 struct ConsoleSharedMemory {
56 u64 sampling_number{};
57 bool is_seven_six_axis_sensor_at_rest{};
58 INSERT_PADDING_BYTES(3); // padding
59 f32 verticalization_error{};
60 Common::Vec3f gyro_bias{};
61 INSERT_PADDING_BYTES(4); // padding
62 };
63 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
64
65 Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{}; 53 Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
66 static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); 54 static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
67 55
56 u64 last_saved_timestamp{};
57 u64 last_global_timestamp{};
58
68 SevenSixAxisState next_seven_sixaxis_state{}; 59 SevenSixAxisState next_seven_sixaxis_state{};
69 Common::ProcessAddress transfer_memory{}; 60 Common::ProcessAddress transfer_memory{};
70 ConsoleSharedMemory* shared_memory = nullptr;
71 Core::HID::EmulatedConsole* console = nullptr; 61 Core::HID::EmulatedConsole* console = nullptr;
72 62
73 u64 last_saved_timestamp{};
74 u64 last_global_timestamp{};
75
76 Core::System& system; 63 Core::System& system;
77}; 64};
78} // namespace Service::HID 65} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/six_axis.cpp b/src/core/hle/service/hid/controllers/six_axis.cpp
new file mode 100644
index 000000000..3d24a5c04
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/six_axis.cpp
@@ -0,0 +1,413 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "common/common_types.h"
5#include "core/core_timing.h"
6#include "core/hid/emulated_controller.h"
7#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/controllers/npad.h"
9#include "core/hle/service/hid/controllers/six_axis.h"
10#include "core/hle/service/hid/errors.h"
11#include "core/hle/service/hid/hid_util.h"
12
13namespace Service::HID {
14
15SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_)
16 : ControllerBase{hid_core_}, npad{npad_} {
17 for (std::size_t i = 0; i < controller_data.size(); ++i) {
18 auto& controller = controller_data[i];
19 controller.device = hid_core.GetEmulatedControllerByIndex(i);
20 }
21}
22
23SixAxis::~SixAxis() = default;
24
25void SixAxis::OnInit() {}
26void SixAxis::OnRelease() {}
27
28void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
29 if (!IsControllerActivated()) {
30 return;
31 }
32
33 for (std::size_t i = 0; i < controller_data.size(); ++i) {
34 auto& controller = controller_data[i];
35
36 const auto npad_id = IndexToNpadIdType(i);
37 const auto& controller_type = controller.device->GetNpadStyleIndex();
38
39 if (controller_type == Core::HID::NpadStyleIndex::None ||
40 !controller.device->IsConnected()) {
41 continue;
42 }
43
44 const auto& motion_state = controller.device->GetMotions();
45 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
46 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
47 auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
48 auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
49 auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
50 auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
51
52 auto& sixaxis_fullkey_lifo = npad->GetSixAxisFullkeyLifo(npad_id);
53 auto& sixaxis_handheld_lifo = npad->GetSixAxisHandheldLifo(npad_id);
54 auto& sixaxis_dual_left_lifo = npad->GetSixAxisDualLeftLifo(npad_id);
55 auto& sixaxis_dual_right_lifo = npad->GetSixAxisDualRightLifo(npad_id);
56 auto& sixaxis_left_lifo = npad->GetSixAxisLeftLifo(npad_id);
57 auto& sixaxis_right_lifo = npad->GetSixAxisRightLifo(npad_id);
58
59 // Clear previous state
60 sixaxis_fullkey_state = {};
61 sixaxis_handheld_state = {};
62 sixaxis_dual_left_state = {};
63 sixaxis_dual_right_state = {};
64 sixaxis_left_lifo_state = {};
65 sixaxis_right_lifo_state = {};
66
67 if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
68 controller.sixaxis_at_rest = true;
69 for (std::size_t e = 0; e < motion_state.size(); ++e) {
70 controller.sixaxis_at_rest =
71 controller.sixaxis_at_rest && motion_state[e].is_at_rest;
72 }
73 }
74
75 const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state,
76 const Core::HID::ControllerMotion& hid_state) {
77 using namespace std::literals::chrono_literals;
78 static constexpr Core::HID::SixAxisSensorState default_motion_state = {
79 .delta_time = std::chrono::nanoseconds(5ms).count(),
80 .accel = {0, 0, -1.0f},
81 .orientation =
82 {
83 Common::Vec3f{1.0f, 0, 0},
84 Common::Vec3f{0, 1.0f, 0},
85 Common::Vec3f{0, 0, 1.0f},
86 },
87 .attribute = {1},
88 };
89 if (!controller.sixaxis_sensor_enabled) {
90 state = default_motion_state;
91 return;
92 }
93 if (!Settings::values.motion_enabled.GetValue()) {
94 state = default_motion_state;
95 return;
96 }
97 state.attribute.is_connected.Assign(1);
98 state.delta_time = std::chrono::nanoseconds(5ms).count();
99 state.accel = hid_state.accel;
100 state.gyro = hid_state.gyro;
101 state.rotation = hid_state.rotation;
102 state.orientation = hid_state.orientation;
103 };
104
105 switch (controller_type) {
106 case Core::HID::NpadStyleIndex::None:
107 ASSERT(false);
108 break;
109 case Core::HID::NpadStyleIndex::ProController:
110 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
111 break;
112 case Core::HID::NpadStyleIndex::Handheld:
113 set_motion_state(sixaxis_handheld_state, motion_state[0]);
114 break;
115 case Core::HID::NpadStyleIndex::JoyconDual:
116 set_motion_state(sixaxis_dual_left_state, motion_state[0]);
117 set_motion_state(sixaxis_dual_right_state, motion_state[1]);
118 break;
119 case Core::HID::NpadStyleIndex::JoyconLeft:
120 set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
121 break;
122 case Core::HID::NpadStyleIndex::JoyconRight:
123 set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
124 break;
125 case Core::HID::NpadStyleIndex::Pokeball:
126 using namespace std::literals::chrono_literals;
127 set_motion_state(sixaxis_fullkey_state, motion_state[0]);
128 sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
129 break;
130 default:
131 break;
132 }
133
134 sixaxis_fullkey_state.sampling_number =
135 sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
136 sixaxis_handheld_state.sampling_number =
137 sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
138 sixaxis_dual_left_state.sampling_number =
139 sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
140 sixaxis_dual_right_state.sampling_number =
141 sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
142 sixaxis_left_lifo_state.sampling_number =
143 sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
144 sixaxis_right_lifo_state.sampling_number =
145 sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
146
147 if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
148 // This buffer only is updated on handheld on HW
149 sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
150 } else {
151 // Handheld doesn't update this buffer on HW
152 sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
153 }
154
155 sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
156 sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
157 sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
158 sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
159 }
160}
161
162Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
163 Core::HID::GyroscopeZeroDriftMode drift_mode) {
164 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
165 if (is_valid.IsError()) {
166 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
167 return is_valid;
168 }
169
170 auto& sixaxis = GetSixaxisState(sixaxis_handle);
171 auto& controller = GetControllerFromHandle(sixaxis_handle);
172 sixaxis.gyroscope_zero_drift_mode = drift_mode;
173 controller.device->SetGyroscopeZeroDriftMode(drift_mode);
174
175 return ResultSuccess;
176}
177
178Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
179 Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
180 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
181 if (is_valid.IsError()) {
182 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
183 return is_valid;
184 }
185
186 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
187 drift_mode = sixaxis.gyroscope_zero_drift_mode;
188
189 return ResultSuccess;
190}
191
192Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
193 bool& is_at_rest) const {
194 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
195 if (is_valid.IsError()) {
196 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
197 return is_valid;
198 }
199
200 const auto& controller = GetControllerFromHandle(sixaxis_handle);
201 is_at_rest = controller.sixaxis_at_rest;
202 return ResultSuccess;
203}
204
205Result SixAxis::LoadSixAxisSensorCalibrationParameter(
206 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
207 Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
208 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
209 if (is_valid.IsError()) {
210 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
211 return is_valid;
212 }
213
214 // TODO: Request this data to the controller. On error return 0xd8ca
215 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
216 calibration = sixaxis.calibration;
217 return ResultSuccess;
218}
219
220Result SixAxis::GetSixAxisSensorIcInformation(
221 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
222 Core::HID::SixAxisSensorIcInformation& ic_information) const {
223 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
224 if (is_valid.IsError()) {
225 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
226 return is_valid;
227 }
228
229 // TODO: Request this data to the controller. On error return 0xd8ca
230 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
231 ic_information = sixaxis.ic_information;
232 return ResultSuccess;
233}
234
235Result SixAxis::EnableSixAxisSensorUnalteredPassthrough(
236 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
237 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
238 if (is_valid.IsError()) {
239 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
240 return is_valid;
241 }
242
243 auto& sixaxis = GetSixaxisState(sixaxis_handle);
244 sixaxis.unaltered_passtrough = is_enabled;
245 return ResultSuccess;
246}
247
248Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled(
249 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
250 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
251 if (is_valid.IsError()) {
252 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
253 return is_valid;
254 }
255
256 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
257 is_enabled = sixaxis.unaltered_passtrough;
258 return ResultSuccess;
259}
260
261Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
262 bool sixaxis_status) {
263 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
264 if (is_valid.IsError()) {
265 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
266 return is_valid;
267 }
268
269 auto& controller = GetControllerFromHandle(sixaxis_handle);
270 controller.sixaxis_sensor_enabled = sixaxis_status;
271 return ResultSuccess;
272}
273
274Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
275 bool& is_fusion_enabled) const {
276 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
277 if (is_valid.IsError()) {
278 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
279 return is_valid;
280 }
281
282 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
283 is_fusion_enabled = sixaxis.is_fusion_enabled;
284
285 return ResultSuccess;
286}
287Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
288 bool is_fusion_enabled) {
289 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
290 if (is_valid.IsError()) {
291 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
292 return is_valid;
293 }
294
295 auto& sixaxis = GetSixaxisState(sixaxis_handle);
296 sixaxis.is_fusion_enabled = is_fusion_enabled;
297
298 return ResultSuccess;
299}
300
301Result SixAxis::SetSixAxisFusionParameters(
302 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
303 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
304 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
305 if (is_valid.IsError()) {
306 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
307 return is_valid;
308 }
309
310 const auto param1 = sixaxis_fusion_parameters.parameter1;
311 if (param1 < 0.0f || param1 > 1.0f) {
312 return InvalidSixAxisFusionRange;
313 }
314
315 auto& sixaxis = GetSixaxisState(sixaxis_handle);
316 sixaxis.fusion = sixaxis_fusion_parameters;
317
318 return ResultSuccess;
319}
320
321Result SixAxis::GetSixAxisFusionParameters(
322 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
323 Core::HID::SixAxisSensorFusionParameters& parameters) const {
324 const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
325 if (is_valid.IsError()) {
326 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
327 return is_valid;
328 }
329
330 const auto& sixaxis = GetSixaxisState(sixaxis_handle);
331 parameters = sixaxis.fusion;
332
333 return ResultSuccess;
334}
335
336SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
337 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
338 auto& controller = GetControllerFromHandle(sixaxis_handle);
339 switch (sixaxis_handle.npad_type) {
340 case Core::HID::NpadStyleIndex::ProController:
341 case Core::HID::NpadStyleIndex::Pokeball:
342 return controller.sixaxis_fullkey;
343 case Core::HID::NpadStyleIndex::Handheld:
344 return controller.sixaxis_handheld;
345 case Core::HID::NpadStyleIndex::JoyconDual:
346 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
347 return controller.sixaxis_dual_left;
348 }
349 return controller.sixaxis_dual_right;
350 case Core::HID::NpadStyleIndex::JoyconLeft:
351 return controller.sixaxis_left;
352 case Core::HID::NpadStyleIndex::JoyconRight:
353 return controller.sixaxis_right;
354 default:
355 return controller.sixaxis_unknown;
356 }
357}
358
359const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
360 const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
361 const auto& controller = GetControllerFromHandle(sixaxis_handle);
362 switch (sixaxis_handle.npad_type) {
363 case Core::HID::NpadStyleIndex::ProController:
364 case Core::HID::NpadStyleIndex::Pokeball:
365 return controller.sixaxis_fullkey;
366 case Core::HID::NpadStyleIndex::Handheld:
367 return controller.sixaxis_handheld;
368 case Core::HID::NpadStyleIndex::JoyconDual:
369 if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
370 return controller.sixaxis_dual_left;
371 }
372 return controller.sixaxis_dual_right;
373 case Core::HID::NpadStyleIndex::JoyconLeft:
374 return controller.sixaxis_left;
375 case Core::HID::NpadStyleIndex::JoyconRight:
376 return controller.sixaxis_right;
377 default:
378 return controller.sixaxis_unknown;
379 }
380}
381
382SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
383 const Core::HID::SixAxisSensorHandle& device_handle) {
384 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
385 return GetControllerFromNpadIdType(npad_id);
386}
387
388const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
389 const Core::HID::SixAxisSensorHandle& device_handle) const {
390 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
391 return GetControllerFromNpadIdType(npad_id);
392}
393
394SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
395 if (!IsNpadIdValid(npad_id)) {
396 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
397 npad_id = Core::HID::NpadIdType::Player1;
398 }
399 const auto npad_index = NpadIdTypeToIndex(npad_id);
400 return controller_data[npad_index];
401}
402
403const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(
404 Core::HID::NpadIdType npad_id) const {
405 if (!IsNpadIdValid(npad_id)) {
406 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
407 npad_id = Core::HID::NpadIdType::Player1;
408 }
409 const auto npad_index = NpadIdTypeToIndex(npad_id);
410 return controller_data[npad_index];
411}
412
413} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/six_axis.h b/src/core/hle/service/hid/controllers/six_axis.h
new file mode 100644
index 000000000..4c4f5dc7b
--- /dev/null
+++ b/src/core/hle/service/hid/controllers/six_axis.h
@@ -0,0 +1,111 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/common_types.h"
7#include "core/hid/hid_types.h"
8#include "core/hle/service/hid/controllers/controller_base.h"
9#include "core/hle/service/hid/ring_lifo.h"
10
11namespace Core::HID {
12class EmulatedController;
13} // namespace Core::HID
14
15namespace Service::HID {
16class NPad;
17
18class SixAxis final : public ControllerBase {
19public:
20 explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_);
21 ~SixAxis() override;
22
23 // Called when the controller is initialized
24 void OnInit() override;
25
26 // When the controller is released
27 void OnRelease() override;
28
29 // When the controller is requesting an update for the shared memory
30 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
31
32 Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
33 Core::HID::GyroscopeZeroDriftMode drift_mode);
34 Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
35 Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
36 Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
37 bool& is_at_rest) const;
38 Result EnableSixAxisSensorUnalteredPassthrough(
39 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
40 Result IsSixAxisSensorUnalteredPassthroughEnabled(
41 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
42 Result LoadSixAxisSensorCalibrationParameter(
43 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
44 Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
45 Result GetSixAxisSensorIcInformation(
46 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
47 Core::HID::SixAxisSensorIcInformation& ic_information) const;
48 Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
49 bool sixaxis_status);
50 Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
51 bool& is_fusion_enabled) const;
52 Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
53 bool is_fusion_enabled);
54 Result SetSixAxisFusionParameters(
55 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
56 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
57 Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
58 Core::HID::SixAxisSensorFusionParameters& parameters) const;
59
60private:
61 static constexpr std::size_t NPAD_COUNT = 10;
62
63 struct SixaxisParameters {
64 bool is_fusion_enabled{true};
65 bool unaltered_passtrough{false};
66 Core::HID::SixAxisSensorFusionParameters fusion{};
67 Core::HID::SixAxisSensorCalibrationParameter calibration{};
68 Core::HID::SixAxisSensorIcInformation ic_information{};
69 Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
70 Core::HID::GyroscopeZeroDriftMode::Standard};
71 };
72
73 struct NpadControllerData {
74 Core::HID::EmulatedController* device = nullptr;
75
76 // Motion parameters
77 bool sixaxis_at_rest{true};
78 bool sixaxis_sensor_enabled{true};
79 SixaxisParameters sixaxis_fullkey{};
80 SixaxisParameters sixaxis_handheld{};
81 SixaxisParameters sixaxis_dual_left{};
82 SixaxisParameters sixaxis_dual_right{};
83 SixaxisParameters sixaxis_left{};
84 SixaxisParameters sixaxis_right{};
85 SixaxisParameters sixaxis_unknown{};
86
87 // Current pad state
88 Core::HID::SixAxisSensorState sixaxis_fullkey_state{};
89 Core::HID::SixAxisSensorState sixaxis_handheld_state{};
90 Core::HID::SixAxisSensorState sixaxis_dual_left_state{};
91 Core::HID::SixAxisSensorState sixaxis_dual_right_state{};
92 Core::HID::SixAxisSensorState sixaxis_left_lifo_state{};
93 Core::HID::SixAxisSensorState sixaxis_right_lifo_state{};
94 int callback_key{};
95 };
96
97 SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
98 const SixaxisParameters& GetSixaxisState(
99 const Core::HID::SixAxisSensorHandle& device_handle) const;
100
101 NpadControllerData& GetControllerFromHandle(
102 const Core::HID::SixAxisSensorHandle& device_handle);
103 const NpadControllerData& GetControllerFromHandle(
104 const Core::HID::SixAxisSensorHandle& device_handle) const;
105 NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
106 const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
107
108 std::shared_ptr<NPad> npad;
109 std::array<NpadControllerData, NPAD_COUNT> controller_data{};
110};
111} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 3ef91df4b..3bcf0ee9f 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -15,8 +15,7 @@
15namespace Service::HID { 15namespace Service::HID {
16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; 16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
17 17
18Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_, 18TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
19 u8* raw_shared_memory_)
20 : ControllerBase{hid_core_} { 19 : ControllerBase{hid_core_} {
21 static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size, 20 static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
22 "TouchSharedMemory is bigger than the shared memory"); 21 "TouchSharedMemory is bigger than the shared memory");
@@ -25,13 +24,13 @@ Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
25 console = hid_core.GetEmulatedConsole(); 24 console = hid_core.GetEmulatedConsole();
26} 25}
27 26
28Controller_Touchscreen::~Controller_Touchscreen() = default; 27TouchScreen::~TouchScreen() = default;
29 28
30void Controller_Touchscreen::OnInit() {} 29void TouchScreen::OnInit() {}
31 30
32void Controller_Touchscreen::OnRelease() {} 31void TouchScreen::OnRelease() {}
33 32
34void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 33void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
35 shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count(); 34 shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
36 35
37 if (!IsControllerActivated()) { 36 if (!IsControllerActivated()) {
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index dd00921fd..cd342ce91 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -14,10 +14,10 @@ class EmulatedConsole;
14} // namespace Core::HID 14} // namespace Core::HID
15 15
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Touchscreen final : public ControllerBase { 17class TouchScreen final : public ControllerBase {
18public: 18public:
19 explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 19 explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Touchscreen() override; 20 ~TouchScreen() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
23 void OnInit() override; 23 void OnInit() override;
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index 62119e2c5..0aaed1fa7 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -10,20 +10,19 @@
10namespace Service::HID { 10namespace Service::HID {
11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; 11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
12 12
13Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) 13XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
14 : ControllerBase{hid_core_} {
15 static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size, 14 static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
16 "XpadSharedMemory is bigger than the shared memory"); 15 "XpadSharedMemory is bigger than the shared memory");
17 shared_memory = std::construct_at( 16 shared_memory = std::construct_at(
18 reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); 17 reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
19} 18}
20Controller_XPad::~Controller_XPad() = default; 19XPad::~XPad() = default;
21 20
22void Controller_XPad::OnInit() {} 21void XPad::OnInit() {}
23 22
24void Controller_XPad::OnRelease() {} 23void XPad::OnRelease() {}
25 24
26void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { 25void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
27 if (!IsControllerActivated()) { 26 if (!IsControllerActivated()) {
28 shared_memory->basic_xpad_lifo.buffer_count = 0; 27 shared_memory->basic_xpad_lifo.buffer_count = 0;
29 shared_memory->basic_xpad_lifo.buffer_tail = 0; 28 shared_memory->basic_xpad_lifo.buffer_tail = 0;
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index d01dee5fc..9e63a317a 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -10,10 +10,10 @@
10#include "core/hle/service/hid/ring_lifo.h" 10#include "core/hle/service/hid/ring_lifo.h"
11 11
12namespace Service::HID { 12namespace Service::HID {
13class Controller_XPad final : public ControllerBase { 13class XPad final : public ControllerBase {
14public: 14public:
15 explicit Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); 15 explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
16 ~Controller_XPad() override; 16 ~XPad() override;
17 17
18 // Called when the controller is initialized 18 // Called when the controller is initialized
19 void OnInit() override; 19 void OnInit() override;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 929dd5f03..1b7381d8d 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1,2864 +1,39 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <array>
5#include "common/common_types.h"
6#include "common/logging/log.h"
7#include "common/settings.h"
8#include "core/core.h"
9#include "core/core_timing.h"
10#include "core/hid/hid_core.h"
11#include "core/hle/kernel/k_readable_event.h"
12#include "core/hle/kernel/k_shared_memory.h"
13#include "core/hle/kernel/k_transfer_memory.h"
14#include "core/hle/kernel/kernel.h"
15#include "core/hle/service/hid/errors.h"
16#include "core/hle/service/hid/hid.h" 4#include "core/hle/service/hid/hid.h"
5#include "core/hle/service/hid/hid_debug_server.h"
6#include "core/hle/service/hid/hid_firmware_settings.h"
7#include "core/hle/service/hid/hid_server.h"
8#include "core/hle/service/hid/hid_system_server.h"
17#include "core/hle/service/hid/hidbus.h" 9#include "core/hle/service/hid/hidbus.h"
18#include "core/hle/service/hid/irs.h" 10#include "core/hle/service/hid/irs.h"
11#include "core/hle/service/hid/resource_manager.h"
19#include "core/hle/service/hid/xcd.h" 12#include "core/hle/service/hid/xcd.h"
20#include "core/hle/service/ipc_helpers.h"
21#include "core/hle/service/server_manager.h" 13#include "core/hle/service/server_manager.h"
22#include "core/memory.h"
23
24#include "core/hle/service/hid/controllers/console_sixaxis.h"
25#include "core/hle/service/hid/controllers/controller_base.h"
26#include "core/hle/service/hid/controllers/debug_pad.h"
27#include "core/hle/service/hid/controllers/gesture.h"
28#include "core/hle/service/hid/controllers/keyboard.h"
29#include "core/hle/service/hid/controllers/mouse.h"
30#include "core/hle/service/hid/controllers/npad.h"
31#include "core/hle/service/hid/controllers/palma.h"
32#include "core/hle/service/hid/controllers/stubbed.h"
33#include "core/hle/service/hid/controllers/touchscreen.h"
34#include "core/hle/service/hid/controllers/xpad.h"
35 14
36namespace Service::HID { 15namespace Service::HID {
37 16
38// Updating period for each HID device.
39// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
40// Correct npad_update_ns is 4ms this is overclocked to lower input lag
41constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
42constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
43constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
44constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
45
46IAppletResource::IAppletResource(Core::System& system_,
47 KernelHelpers::ServiceContext& service_context_)
48 : ServiceFramework{system_, "IAppletResource"}, service_context{service_context_} {
49 static const FunctionInfo functions[] = {
50 {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
51 };
52 RegisterHandlers(functions);
53 u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
54 MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory);
55 MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory);
56 MakeController<Controller_Mouse>(HidController::Mouse, shared_memory);
57 MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory);
58 MakeController<Controller_XPad>(HidController::XPad, shared_memory);
59 MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory);
60 MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory);
61 MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory);
62 MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory);
63 MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory);
64 MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory);
65 MakeController<Controller_Gesture>(HidController::Gesture, shared_memory);
66 MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);
67 MakeController<Controller_Stubbed>(HidController::DebugMouse, shared_memory);
68 MakeControllerWithServiceContext<Controller_Palma>(HidController::Palma, shared_memory);
69
70 // Homebrew doesn't try to activate some controllers, so we activate them by default
71 GetController<Controller_NPad>(HidController::NPad).ActivateController();
72 GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController();
73
74 GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
75 GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
76 GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
77 GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
78 GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
79 GetController<Controller_Stubbed>(HidController::DebugMouse).SetCommonHeaderOffset(0x3DC00);
80
81 // Register update callbacks
82 npad_update_event = Core::Timing::CreateEvent(
83 "HID::UpdatePadCallback",
84 [this](std::uintptr_t user_data, s64 time,
85 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
86 const auto guard = LockService();
87 UpdateNpad(user_data, ns_late);
88 return std::nullopt;
89 });
90 default_update_event = Core::Timing::CreateEvent(
91 "HID::UpdateDefaultCallback",
92 [this](std::uintptr_t user_data, s64 time,
93 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
94 const auto guard = LockService();
95 UpdateControllers(user_data, ns_late);
96 return std::nullopt;
97 });
98 mouse_keyboard_update_event = Core::Timing::CreateEvent(
99 "HID::UpdateMouseKeyboardCallback",
100 [this](std::uintptr_t user_data, s64 time,
101 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
102 const auto guard = LockService();
103 UpdateMouseKeyboard(user_data, ns_late);
104 return std::nullopt;
105 });
106 motion_update_event = Core::Timing::CreateEvent(
107 "HID::UpdateMotionCallback",
108 [this](std::uintptr_t user_data, s64 time,
109 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
110 const auto guard = LockService();
111 UpdateMotion(user_data, ns_late);
112 return std::nullopt;
113 });
114
115 system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
116 system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
117 default_update_event);
118 system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
119 mouse_keyboard_update_event);
120 system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
121 motion_update_event);
122
123 system.HIDCore().ReloadInputDevices();
124}
125
126void IAppletResource::ActivateController(HidController controller) {
127 controllers[static_cast<size_t>(controller)]->ActivateController();
128}
129
130void IAppletResource::DeactivateController(HidController controller) {
131 controllers[static_cast<size_t>(controller)]->DeactivateController();
132}
133
134IAppletResource::~IAppletResource() {
135 system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
136 system.CoreTiming().UnscheduleEvent(default_update_event, 0);
137 system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
138 system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
139}
140
141void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
142 LOG_DEBUG(Service_HID, "called");
143
144 IPC::ResponseBuilder rb{ctx, 2, 1};
145 rb.Push(ResultSuccess);
146 rb.PushCopyObjects(&system.Kernel().GetHidSharedMem());
147}
148
149void IAppletResource::UpdateControllers(std::uintptr_t user_data,
150 std::chrono::nanoseconds ns_late) {
151 auto& core_timing = system.CoreTiming();
152
153 for (const auto& controller : controllers) {
154 // Keyboard has it's own update event
155 if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
156 continue;
157 }
158 // Mouse has it's own update event
159 if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
160 continue;
161 }
162 // Npad has it's own update event
163 if (controller == controllers[static_cast<size_t>(HidController::NPad)]) {
164 continue;
165 }
166 controller->OnUpdate(core_timing);
167 }
168}
169
170void IAppletResource::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
171 auto& core_timing = system.CoreTiming();
172
173 controllers[static_cast<size_t>(HidController::NPad)]->OnUpdate(core_timing);
174}
175
176void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
177 std::chrono::nanoseconds ns_late) {
178 auto& core_timing = system.CoreTiming();
179
180 controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing);
181 controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);
182}
183
184void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
185 auto& core_timing = system.CoreTiming();
186
187 controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);
188}
189
190class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
191public:
192 explicit IActiveVibrationDeviceList(Core::System& system_,
193 std::shared_ptr<IAppletResource> applet_resource_)
194 : ServiceFramework{system_, "IActiveVibrationDeviceList"},
195 applet_resource(applet_resource_) {
196 // clang-format off
197 static const FunctionInfo functions[] = {
198 {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"},
199 };
200 // clang-format on
201
202 RegisterHandlers(functions);
203 }
204
205private:
206 void InitializeVibrationDevice(HLERequestContext& ctx) {
207 IPC::RequestParser rp{ctx};
208 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
209
210 if (applet_resource != nullptr) {
211 applet_resource->GetController<Controller_NPad>(HidController::NPad)
212 .InitializeVibrationDevice(vibration_device_handle);
213 }
214
215 LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}",
216 vibration_device_handle.npad_type, vibration_device_handle.npad_id,
217 vibration_device_handle.device_index);
218
219 IPC::ResponseBuilder rb{ctx, 2};
220 rb.Push(ResultSuccess);
221 }
222
223 std::shared_ptr<IAppletResource> applet_resource;
224};
225
226std::shared_ptr<IAppletResource> Hid::GetAppletResource() {
227 if (applet_resource == nullptr) {
228 applet_resource = std::make_shared<IAppletResource>(system, service_context);
229 }
230
231 return applet_resource;
232}
233
234Hid::Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_)
235 : ServiceFramework{system_, "hid"}, applet_resource{applet_resource_}, service_context{
236 system_,
237 service_name} {
238 // clang-format off
239 static const FunctionInfo functions[] = {
240 {0, &Hid::CreateAppletResource, "CreateAppletResource"},
241 {1, &Hid::ActivateDebugPad, "ActivateDebugPad"},
242 {11, &Hid::ActivateTouchScreen, "ActivateTouchScreen"},
243 {21, &Hid::ActivateMouse, "ActivateMouse"},
244 {26, nullptr, "ActivateDebugMouse"},
245 {31, &Hid::ActivateKeyboard, "ActivateKeyboard"},
246 {32, &Hid::SendKeyboardLockKeyEvent, "SendKeyboardLockKeyEvent"},
247 {40, nullptr, "AcquireXpadIdEventHandle"},
248 {41, nullptr, "ReleaseXpadIdEventHandle"},
249 {51, &Hid::ActivateXpad, "ActivateXpad"},
250 {55, &Hid::GetXpadIDs, "GetXpadIds"},
251 {56, nullptr, "ActivateJoyXpad"},
252 {58, nullptr, "GetJoyXpadLifoHandle"},
253 {59, nullptr, "GetJoyXpadIds"},
254 {60, &Hid::ActivateSixAxisSensor, "ActivateSixAxisSensor"},
255 {61, &Hid::DeactivateSixAxisSensor, "DeactivateSixAxisSensor"},
256 {62, nullptr, "GetSixAxisSensorLifoHandle"},
257 {63, nullptr, "ActivateJoySixAxisSensor"},
258 {64, nullptr, "DeactivateJoySixAxisSensor"},
259 {65, nullptr, "GetJoySixAxisSensorLifoHandle"},
260 {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
261 {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
262 {68, &Hid::IsSixAxisSensorFusionEnabled, "IsSixAxisSensorFusionEnabled"},
263 {69, &Hid::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
264 {70, &Hid::SetSixAxisSensorFusionParameters, "SetSixAxisSensorFusionParameters"},
265 {71, &Hid::GetSixAxisSensorFusionParameters, "GetSixAxisSensorFusionParameters"},
266 {72, &Hid::ResetSixAxisSensorFusionParameters, "ResetSixAxisSensorFusionParameters"},
267 {73, nullptr, "SetAccelerometerParameters"},
268 {74, nullptr, "GetAccelerometerParameters"},
269 {75, nullptr, "ResetAccelerometerParameters"},
270 {76, nullptr, "SetAccelerometerPlayMode"},
271 {77, nullptr, "GetAccelerometerPlayMode"},
272 {78, nullptr, "ResetAccelerometerPlayMode"},
273 {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
274 {80, &Hid::GetGyroscopeZeroDriftMode, "GetGyroscopeZeroDriftMode"},
275 {81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
276 {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
277 {83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
278 {84, &Hid::EnableSixAxisSensorUnalteredPassthrough, "EnableSixAxisSensorUnalteredPassthrough"},
279 {85, &Hid::IsSixAxisSensorUnalteredPassthroughEnabled, "IsSixAxisSensorUnalteredPassthroughEnabled"},
280 {86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
281 {87, &Hid::LoadSixAxisSensorCalibrationParameter, "LoadSixAxisSensorCalibrationParameter"},
282 {88, &Hid::GetSixAxisSensorIcInformation, "GetSixAxisSensorIcInformation"},
283 {89, &Hid::ResetIsSixAxisSensorDeviceNewlyAssigned, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
284 {91, &Hid::ActivateGesture, "ActivateGesture"},
285 {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
286 {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
287 {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
288 {103, &Hid::ActivateNpad, "ActivateNpad"},
289 {104, &Hid::DeactivateNpad, "DeactivateNpad"},
290 {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
291 {107, &Hid::DisconnectNpad, "DisconnectNpad"},
292 {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
293 {109, &Hid::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
294 {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
295 {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
296 {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
297 {123, &Hid::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"},
298 {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
299 {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
300 {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"},
301 {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"},
302 {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
303 {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
304 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
305 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
306 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
307 {133, &Hid::SetNpadJoyAssignmentModeSingleWithDestination, "SetNpadJoyAssignmentModeSingleWithDestination"},
308 {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
309 {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"},
310 {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"},
311 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
312 {201, &Hid::SendVibrationValue, "SendVibrationValue"},
313 {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
314 {203, &Hid::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
315 {204, &Hid::PermitVibration, "PermitVibration"},
316 {205, &Hid::IsVibrationPermitted, "IsVibrationPermitted"},
317 {206, &Hid::SendVibrationValues, "SendVibrationValues"},
318 {207, &Hid::SendVibrationGcErmCommand, "SendVibrationGcErmCommand"},
319 {208, &Hid::GetActualVibrationGcErmCommand, "GetActualVibrationGcErmCommand"},
320 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
321 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"},
322 {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
323 {212, nullptr, "SendVibrationValueInBool"},
324 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
325 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
326 {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"},
327 {303, &Hid::ActivateSevenSixAxisSensor, "ActivateSevenSixAxisSensor"},
328 {304, &Hid::StartSevenSixAxisSensor, "StartSevenSixAxisSensor"},
329 {305, &Hid::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"},
330 {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
331 {307, &Hid::FinalizeSevenSixAxisSensor, "FinalizeSevenSixAxisSensor"},
332 {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
333 {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
334 {310, &Hid::ResetSevenSixAxisSensorTimestamp, "ResetSevenSixAxisSensorTimestamp"},
335 {400, &Hid::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
336 {401, nullptr, "EnableUsbFullKeyController"},
337 {402, nullptr, "IsUsbFullKeyControllerConnected"},
338 {403, nullptr, "HasBattery"},
339 {404, nullptr, "HasLeftRightBattery"},
340 {405, nullptr, "GetNpadInterfaceType"},
341 {406, nullptr, "GetNpadLeftRightInterfaceType"},
342 {407, nullptr, "GetNpadOfHighestBatteryLevel"},
343 {408, nullptr, "GetNpadOfHighestBatteryLevelForJoyRight"},
344 {500, &Hid::GetPalmaConnectionHandle, "GetPalmaConnectionHandle"},
345 {501, &Hid::InitializePalma, "InitializePalma"},
346 {502, &Hid::AcquirePalmaOperationCompleteEvent, "AcquirePalmaOperationCompleteEvent"},
347 {503, &Hid::GetPalmaOperationInfo, "GetPalmaOperationInfo"},
348 {504, &Hid::PlayPalmaActivity, "PlayPalmaActivity"},
349 {505, &Hid::SetPalmaFrModeType, "SetPalmaFrModeType"},
350 {506, &Hid::ReadPalmaStep, "ReadPalmaStep"},
351 {507, &Hid::EnablePalmaStep, "EnablePalmaStep"},
352 {508, &Hid::ResetPalmaStep, "ResetPalmaStep"},
353 {509, &Hid::ReadPalmaApplicationSection, "ReadPalmaApplicationSection"},
354 {510, &Hid::WritePalmaApplicationSection, "WritePalmaApplicationSection"},
355 {511, &Hid::ReadPalmaUniqueCode, "ReadPalmaUniqueCode"},
356 {512, &Hid::SetPalmaUniqueCodeInvalid, "SetPalmaUniqueCodeInvalid"},
357 {513, &Hid::WritePalmaActivityEntry, "WritePalmaActivityEntry"},
358 {514, &Hid::WritePalmaRgbLedPatternEntry, "WritePalmaRgbLedPatternEntry"},
359 {515, &Hid::WritePalmaWaveEntry, "WritePalmaWaveEntry"},
360 {516, &Hid::SetPalmaDataBaseIdentificationVersion, "SetPalmaDataBaseIdentificationVersion"},
361 {517, &Hid::GetPalmaDataBaseIdentificationVersion, "GetPalmaDataBaseIdentificationVersion"},
362 {518, &Hid::SuspendPalmaFeature, "SuspendPalmaFeature"},
363 {519, &Hid::GetPalmaOperationResult, "GetPalmaOperationResult"},
364 {520, &Hid::ReadPalmaPlayLog, "ReadPalmaPlayLog"},
365 {521, &Hid::ResetPalmaPlayLog, "ResetPalmaPlayLog"},
366 {522, &Hid::SetIsPalmaAllConnectable, "SetIsPalmaAllConnectable"},
367 {523, &Hid::SetIsPalmaPairedConnectable, "SetIsPalmaPairedConnectable"},
368 {524, &Hid::PairPalma, "PairPalma"},
369 {525, &Hid::SetPalmaBoostMode, "SetPalmaBoostMode"},
370 {526, &Hid::CancelWritePalmaWaveEntry, "CancelWritePalmaWaveEntry"},
371 {527, &Hid::EnablePalmaBoostMode, "EnablePalmaBoostMode"},
372 {528, &Hid::GetPalmaBluetoothAddress, "GetPalmaBluetoothAddress"},
373 {529, &Hid::SetDisallowedPalmaConnection, "SetDisallowedPalmaConnection"},
374 {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"},
375 {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"},
376 {1002, &Hid::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"},
377 {1003, &Hid::IsFirmwareUpdateNeededForNotification, "IsFirmwareUpdateNeededForNotification"},
378 {2000, nullptr, "ActivateDigitizer"},
379 };
380 // clang-format on
381
382 RegisterHandlers(functions);
383}
384
385Hid::~Hid() = default;
386
387void Hid::CreateAppletResource(HLERequestContext& ctx) {
388 IPC::RequestParser rp{ctx};
389 const auto applet_resource_user_id{rp.Pop<u64>()};
390
391 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
392
393 if (applet_resource == nullptr) {
394 applet_resource = std::make_shared<IAppletResource>(system, service_context);
395 }
396
397 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
398 rb.Push(ResultSuccess);
399 rb.PushIpcInterface<IAppletResource>(applet_resource);
400}
401
402void Hid::ActivateDebugPad(HLERequestContext& ctx) {
403 IPC::RequestParser rp{ctx};
404 const auto applet_resource_user_id{rp.Pop<u64>()};
405
406 applet_resource->ActivateController(HidController::DebugPad);
407
408 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
409
410 IPC::ResponseBuilder rb{ctx, 2};
411 rb.Push(ResultSuccess);
412}
413
414void Hid::ActivateTouchScreen(HLERequestContext& ctx) {
415 IPC::RequestParser rp{ctx};
416 const auto applet_resource_user_id{rp.Pop<u64>()};
417
418 applet_resource->ActivateController(HidController::Touchscreen);
419
420 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
421
422 IPC::ResponseBuilder rb{ctx, 2};
423 rb.Push(ResultSuccess);
424}
425
426void Hid::ActivateMouse(HLERequestContext& ctx) {
427 IPC::RequestParser rp{ctx};
428 const auto applet_resource_user_id{rp.Pop<u64>()};
429
430 applet_resource->ActivateController(HidController::Mouse);
431
432 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
433
434 IPC::ResponseBuilder rb{ctx, 2};
435 rb.Push(ResultSuccess);
436}
437
438void Hid::ActivateKeyboard(HLERequestContext& ctx) {
439 IPC::RequestParser rp{ctx};
440 const auto applet_resource_user_id{rp.Pop<u64>()};
441
442 applet_resource->ActivateController(HidController::Keyboard);
443
444 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
445
446 IPC::ResponseBuilder rb{ctx, 2};
447 rb.Push(ResultSuccess);
448}
449
450void Hid::SendKeyboardLockKeyEvent(HLERequestContext& ctx) {
451 IPC::RequestParser rp{ctx};
452 const auto flags{rp.Pop<u32>()};
453
454 LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags);
455
456 IPC::ResponseBuilder rb{ctx, 2};
457 rb.Push(ResultSuccess);
458}
459
460void Hid::ActivateXpad(HLERequestContext& ctx) {
461 IPC::RequestParser rp{ctx};
462 struct Parameters {
463 u32 basic_xpad_id;
464 INSERT_PADDING_WORDS_NOINIT(1);
465 u64 applet_resource_user_id;
466 };
467 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
468
469 const auto parameters{rp.PopRaw<Parameters>()};
470
471 applet_resource->ActivateController(HidController::XPad);
472
473 LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}",
474 parameters.basic_xpad_id, parameters.applet_resource_user_id);
475
476 IPC::ResponseBuilder rb{ctx, 2};
477 rb.Push(ResultSuccess);
478}
479
480void Hid::GetXpadIDs(HLERequestContext& ctx) {
481 IPC::RequestParser rp{ctx};
482 const auto applet_resource_user_id{rp.Pop<u64>()};
483
484 LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id);
485
486 IPC::ResponseBuilder rb{ctx, 3};
487 rb.Push(ResultSuccess);
488 rb.Push(0);
489}
490
491void Hid::ActivateSixAxisSensor(HLERequestContext& ctx) {
492 IPC::RequestParser rp{ctx};
493 struct Parameters {
494 u32 basic_xpad_id;
495 INSERT_PADDING_WORDS_NOINIT(1);
496 u64 applet_resource_user_id;
497 };
498 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
499
500 const auto parameters{rp.PopRaw<Parameters>()};
501
502 // This function does nothing on 10.0.0+
503
504 LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
505 parameters.basic_xpad_id, parameters.applet_resource_user_id);
506
507 IPC::ResponseBuilder rb{ctx, 2};
508 rb.Push(ResultSuccess);
509}
510
511void Hid::DeactivateSixAxisSensor(HLERequestContext& ctx) {
512 IPC::RequestParser rp{ctx};
513 struct Parameters {
514 u32 basic_xpad_id;
515 INSERT_PADDING_WORDS_NOINIT(1);
516 u64 applet_resource_user_id;
517 };
518 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
519
520 const auto parameters{rp.PopRaw<Parameters>()};
521
522 // This function does nothing on 10.0.0+
523
524 LOG_WARNING(Service_HID, "(STUBBED) called, basic_xpad_id={}, applet_resource_user_id={}",
525 parameters.basic_xpad_id, parameters.applet_resource_user_id);
526
527 IPC::ResponseBuilder rb{ctx, 2};
528 rb.Push(ResultSuccess);
529}
530
531void Hid::StartSixAxisSensor(HLERequestContext& ctx) {
532 IPC::RequestParser rp{ctx};
533 struct Parameters {
534 Core::HID::SixAxisSensorHandle sixaxis_handle;
535 INSERT_PADDING_WORDS_NOINIT(1);
536 u64 applet_resource_user_id;
537 };
538 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
539
540 const auto parameters{rp.PopRaw<Parameters>()};
541
542 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
543 const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, true);
544
545 LOG_DEBUG(Service_HID,
546 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
547 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
548 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
549
550 IPC::ResponseBuilder rb{ctx, 2};
551 rb.Push(result);
552}
553
554void Hid::StopSixAxisSensor(HLERequestContext& ctx) {
555 IPC::RequestParser rp{ctx};
556 struct Parameters {
557 Core::HID::SixAxisSensorHandle sixaxis_handle;
558 INSERT_PADDING_WORDS_NOINIT(1);
559 u64 applet_resource_user_id;
560 };
561 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
562
563 const auto parameters{rp.PopRaw<Parameters>()};
564
565 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
566 const auto result = controller.SetSixAxisEnabled(parameters.sixaxis_handle, false);
567
568 LOG_DEBUG(Service_HID,
569 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
570 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
571 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
572
573 IPC::ResponseBuilder rb{ctx, 2};
574 rb.Push(result);
575}
576
577void Hid::IsSixAxisSensorFusionEnabled(HLERequestContext& ctx) {
578 IPC::RequestParser rp{ctx};
579 struct Parameters {
580 Core::HID::SixAxisSensorHandle sixaxis_handle;
581 INSERT_PADDING_WORDS_NOINIT(1);
582 u64 applet_resource_user_id;
583 };
584 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
585
586 const auto parameters{rp.PopRaw<Parameters>()};
587
588 bool is_enabled{};
589 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
590 const auto result =
591 controller.IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled);
592
593 LOG_DEBUG(Service_HID,
594 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
595 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
596 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
597
598 IPC::ResponseBuilder rb{ctx, 3};
599 rb.Push(result);
600 rb.Push(is_enabled);
601}
602
603void Hid::EnableSixAxisSensorFusion(HLERequestContext& ctx) {
604 IPC::RequestParser rp{ctx};
605 struct Parameters {
606 bool enable_sixaxis_sensor_fusion;
607 INSERT_PADDING_BYTES_NOINIT(3);
608 Core::HID::SixAxisSensorHandle sixaxis_handle;
609 u64 applet_resource_user_id;
610 };
611 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
612
613 const auto parameters{rp.PopRaw<Parameters>()};
614
615 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
616 const auto result = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle,
617 parameters.enable_sixaxis_sensor_fusion);
618
619 LOG_DEBUG(Service_HID,
620 "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
621 "device_index={}, applet_resource_user_id={}",
622 parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
623 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
624 parameters.applet_resource_user_id);
625
626 IPC::ResponseBuilder rb{ctx, 2};
627 rb.Push(result);
628}
629
630void Hid::SetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
631 IPC::RequestParser rp{ctx};
632 struct Parameters {
633 Core::HID::SixAxisSensorHandle sixaxis_handle;
634 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion;
635 INSERT_PADDING_WORDS_NOINIT(1);
636 u64 applet_resource_user_id;
637 };
638 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
639
640 const auto parameters{rp.PopRaw<Parameters>()};
641
642 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
643 const auto result =
644 controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
645
646 LOG_DEBUG(Service_HID,
647 "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
648 "parameter2={}, applet_resource_user_id={}",
649 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
650 parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1,
651 parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id);
652
653 IPC::ResponseBuilder rb{ctx, 2};
654 rb.Push(result);
655}
656
657void Hid::GetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
658 IPC::RequestParser rp{ctx};
659 struct Parameters {
660 Core::HID::SixAxisSensorHandle sixaxis_handle;
661 INSERT_PADDING_WORDS_NOINIT(1);
662 u64 applet_resource_user_id;
663 };
664 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
665
666 const auto parameters{rp.PopRaw<Parameters>()};
667
668 Core::HID::SixAxisSensorFusionParameters fusion_parameters{};
669 const auto& controller =
670 GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
671 const auto result =
672 controller.GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
673
674 LOG_DEBUG(Service_HID,
675 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
676 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
677 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
678
679 IPC::ResponseBuilder rb{ctx, 4};
680 rb.Push(result);
681 rb.PushRaw(fusion_parameters);
682}
683
684void Hid::ResetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
685 IPC::RequestParser rp{ctx};
686 struct Parameters {
687 Core::HID::SixAxisSensorHandle sixaxis_handle;
688 INSERT_PADDING_WORDS_NOINIT(1);
689 u64 applet_resource_user_id;
690 };
691 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
692
693 const auto parameters{rp.PopRaw<Parameters>()};
694
695 // Since these parameters are unknown just use what HW outputs
696 const Core::HID::SixAxisSensorFusionParameters fusion_parameters{
697 .parameter1 = 0.03f,
698 .parameter2 = 0.4f,
699 };
700 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
701 const auto result1 =
702 controller.SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
703 const auto result2 = controller.SetSixAxisFusionEnabled(parameters.sixaxis_handle, true);
704
705 LOG_DEBUG(Service_HID,
706 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
707 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
708 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
709
710 IPC::ResponseBuilder rb{ctx, 2};
711 if (result1.IsError()) {
712 rb.Push(result1);
713 return;
714 }
715 rb.Push(result2);
716}
717
718void Hid::SetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
719 IPC::RequestParser rp{ctx};
720 const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
721 const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()};
722 const auto applet_resource_user_id{rp.Pop<u64>()};
723
724 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
725 const auto result = controller.SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
726
727 LOG_DEBUG(Service_HID,
728 "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
729 "applet_resource_user_id={}",
730 sixaxis_handle.npad_type, sixaxis_handle.npad_id, sixaxis_handle.device_index,
731 drift_mode, applet_resource_user_id);
732
733 IPC::ResponseBuilder rb{ctx, 2};
734 rb.Push(result);
735}
736
737void Hid::GetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
738 IPC::RequestParser rp{ctx};
739 struct Parameters {
740 Core::HID::SixAxisSensorHandle sixaxis_handle;
741 INSERT_PADDING_WORDS_NOINIT(1);
742 u64 applet_resource_user_id;
743 };
744 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
745
746 const auto parameters{rp.PopRaw<Parameters>()};
747
748 auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
749 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
750 const auto result = controller.GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
751
752 LOG_DEBUG(Service_HID,
753 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
754 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
755 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
756
757 IPC::ResponseBuilder rb{ctx, 3};
758 rb.Push(result);
759 rb.PushEnum(drift_mode);
760}
761
762void Hid::ResetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
763 IPC::RequestParser rp{ctx};
764 struct Parameters {
765 Core::HID::SixAxisSensorHandle sixaxis_handle;
766 INSERT_PADDING_WORDS_NOINIT(1);
767 u64 applet_resource_user_id;
768 };
769 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
770
771 const auto parameters{rp.PopRaw<Parameters>()};
772
773 const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
774 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
775 const auto result = controller.SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
776
777 LOG_DEBUG(Service_HID,
778 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
779 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
780 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
781
782 IPC::ResponseBuilder rb{ctx, 2};
783 rb.Push(result);
784}
785
786void Hid::IsSixAxisSensorAtRest(HLERequestContext& ctx) {
787 IPC::RequestParser rp{ctx};
788 struct Parameters {
789 Core::HID::SixAxisSensorHandle sixaxis_handle;
790 INSERT_PADDING_WORDS_NOINIT(1);
791 u64 applet_resource_user_id;
792 };
793 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
794
795 const auto parameters{rp.PopRaw<Parameters>()};
796
797 bool is_at_rest{};
798 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
799 controller.IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
800
801 LOG_DEBUG(Service_HID,
802 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
803 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
804 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
805
806 IPC::ResponseBuilder rb{ctx, 3};
807 rb.Push(ResultSuccess);
808 rb.Push(is_at_rest);
809}
810
811void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx) {
812 IPC::RequestParser rp{ctx};
813 struct Parameters {
814 Core::HID::SixAxisSensorHandle sixaxis_handle;
815 INSERT_PADDING_WORDS_NOINIT(1);
816 u64 applet_resource_user_id;
817 };
818 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
819
820 const auto parameters{rp.PopRaw<Parameters>()};
821
822 bool is_firmware_available{};
823 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
824 controller.IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
825 is_firmware_available);
826
827 LOG_WARNING(
828 Service_HID,
829 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
830 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
831 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
832
833 IPC::ResponseBuilder rb{ctx, 3};
834 rb.Push(ResultSuccess);
835 rb.Push(is_firmware_available);
836}
837
838void Hid::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx) {
839 IPC::RequestParser rp{ctx};
840 struct Parameters {
841 bool enabled;
842 Core::HID::SixAxisSensorHandle sixaxis_handle;
843 u64 applet_resource_user_id;
844 };
845 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
846
847 const auto parameters{rp.PopRaw<Parameters>()};
848
849 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
850 const auto result = controller.EnableSixAxisSensorUnalteredPassthrough(
851 parameters.sixaxis_handle, parameters.enabled);
852
853 LOG_DEBUG(Service_HID,
854 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
855 "applet_resource_user_id={}",
856 parameters.enabled, parameters.sixaxis_handle.npad_type,
857 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
858 parameters.applet_resource_user_id);
859
860 IPC::ResponseBuilder rb{ctx, 2};
861 rb.Push(result);
862}
863
864void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx) {
865 IPC::RequestParser rp{ctx};
866 struct Parameters {
867 Core::HID::SixAxisSensorHandle sixaxis_handle;
868 INSERT_PADDING_WORDS_NOINIT(1);
869 u64 applet_resource_user_id;
870 };
871 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
872
873 const auto parameters{rp.PopRaw<Parameters>()};
874
875 bool is_unaltered_sisxaxis_enabled{};
876 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
877 const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled(
878 parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
879
880 LOG_DEBUG(
881 Service_HID,
882 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
883 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
884 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
885
886 IPC::ResponseBuilder rb{ctx, 3};
887 rb.Push(result);
888 rb.Push(is_unaltered_sisxaxis_enabled);
889}
890
891void Hid::LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx) {
892 IPC::RequestParser rp{ctx};
893 struct Parameters {
894 Core::HID::SixAxisSensorHandle sixaxis_handle;
895 INSERT_PADDING_WORDS_NOINIT(1);
896 u64 applet_resource_user_id;
897 };
898 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
899
900 const auto parameters{rp.PopRaw<Parameters>()};
901
902 Core::HID::SixAxisSensorCalibrationParameter calibration{};
903 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
904 const auto result =
905 controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
906
907 LOG_WARNING(
908 Service_HID,
909 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
910 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
911 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
912
913 if (result.IsSuccess()) {
914 ctx.WriteBuffer(calibration);
915 }
916
917 IPC::ResponseBuilder rb{ctx, 2};
918 rb.Push(result);
919}
920
921void Hid::GetSixAxisSensorIcInformation(HLERequestContext& ctx) {
922 IPC::RequestParser rp{ctx};
923 struct Parameters {
924 Core::HID::SixAxisSensorHandle sixaxis_handle;
925 INSERT_PADDING_WORDS_NOINIT(1);
926 u64 applet_resource_user_id;
927 };
928 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
929
930 const auto parameters{rp.PopRaw<Parameters>()};
931
932 Core::HID::SixAxisSensorIcInformation ic_information{};
933 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
934 const auto result =
935 controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
936
937 LOG_WARNING(
938 Service_HID,
939 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
940 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
941 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
942
943 if (result.IsSuccess()) {
944 ctx.WriteBuffer(ic_information);
945 }
946
947 IPC::ResponseBuilder rb{ctx, 2};
948 rb.Push(result);
949}
950
951void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) {
952 IPC::RequestParser rp{ctx};
953 struct Parameters {
954 Core::HID::SixAxisSensorHandle sixaxis_handle;
955 INSERT_PADDING_WORDS_NOINIT(1);
956 u64 applet_resource_user_id;
957 };
958 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
959
960 const auto parameters{rp.PopRaw<Parameters>()};
961
962 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
963 const auto result =
964 controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
965
966 LOG_WARNING(
967 Service_HID,
968 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
969 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
970 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
971
972 IPC::ResponseBuilder rb{ctx, 2};
973 rb.Push(result);
974}
975
976void Hid::ActivateGesture(HLERequestContext& ctx) {
977 IPC::RequestParser rp{ctx};
978 struct Parameters {
979 u32 unknown;
980 INSERT_PADDING_WORDS_NOINIT(1);
981 u64 applet_resource_user_id;
982 };
983 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
984
985 const auto parameters{rp.PopRaw<Parameters>()};
986
987 applet_resource->ActivateController(HidController::Gesture);
988
989 LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
990 parameters.unknown, parameters.applet_resource_user_id);
991
992 IPC::ResponseBuilder rb{ctx, 2};
993 rb.Push(ResultSuccess);
994}
995
996void Hid::SetSupportedNpadStyleSet(HLERequestContext& ctx) {
997 IPC::RequestParser rp{ctx};
998 struct Parameters {
999 Core::HID::NpadStyleSet supported_styleset;
1000 INSERT_PADDING_WORDS_NOINIT(1);
1001 u64 applet_resource_user_id;
1002 };
1003 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1004
1005 const auto parameters{rp.PopRaw<Parameters>()};
1006
1007 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1008 .SetSupportedStyleSet({parameters.supported_styleset});
1009
1010 LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
1011 parameters.supported_styleset, parameters.applet_resource_user_id);
1012
1013 IPC::ResponseBuilder rb{ctx, 2};
1014 rb.Push(ResultSuccess);
1015}
1016
1017void Hid::GetSupportedNpadStyleSet(HLERequestContext& ctx) {
1018 IPC::RequestParser rp{ctx};
1019 const auto applet_resource_user_id{rp.Pop<u64>()};
1020
1021 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1022
1023 IPC::ResponseBuilder rb{ctx, 3};
1024 rb.Push(ResultSuccess);
1025 rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
1026 .GetSupportedStyleSet()
1027 .raw);
1028}
1029
1030void Hid::SetSupportedNpadIdType(HLERequestContext& ctx) {
1031 IPC::RequestParser rp{ctx};
1032 const auto applet_resource_user_id{rp.Pop<u64>()};
1033
1034 const auto result = applet_resource->GetController<Controller_NPad>(HidController::NPad)
1035 .SetSupportedNpadIdTypes(ctx.ReadBuffer());
1036
1037 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1038
1039 IPC::ResponseBuilder rb{ctx, 2};
1040 rb.Push(result);
1041}
1042
1043void Hid::ActivateNpad(HLERequestContext& ctx) {
1044 IPC::RequestParser rp{ctx};
1045 const auto applet_resource_user_id{rp.Pop<u64>()};
1046
1047 applet_resource->ActivateController(HidController::NPad);
1048
1049 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1050
1051 IPC::ResponseBuilder rb{ctx, 2};
1052 rb.Push(ResultSuccess);
1053}
1054
1055void Hid::DeactivateNpad(HLERequestContext& ctx) {
1056 IPC::RequestParser rp{ctx};
1057 const auto applet_resource_user_id{rp.Pop<u64>()};
1058
1059 applet_resource->DeactivateController(HidController::NPad);
1060
1061 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1062
1063 IPC::ResponseBuilder rb{ctx, 2};
1064 rb.Push(ResultSuccess);
1065}
1066
1067void Hid::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) {
1068 IPC::RequestParser rp{ctx};
1069 struct Parameters {
1070 Core::HID::NpadIdType npad_id;
1071 INSERT_PADDING_WORDS_NOINIT(1);
1072 u64 applet_resource_user_id;
1073 u64 unknown;
1074 };
1075 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1076
1077 const auto parameters{rp.PopRaw<Parameters>()};
1078
1079 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
1080 parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown);
1081
1082 // Games expect this event to be signaled after calling this function
1083 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1084 .SignalStyleSetChangedEvent(parameters.npad_id);
1085
1086 IPC::ResponseBuilder rb{ctx, 2, 1};
1087 rb.Push(ResultSuccess);
1088 rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad)
1089 .GetStyleSetChangedEvent(parameters.npad_id));
1090}
1091
1092void Hid::DisconnectNpad(HLERequestContext& ctx) {
1093 IPC::RequestParser rp{ctx};
1094 struct Parameters {
1095 Core::HID::NpadIdType npad_id;
1096 INSERT_PADDING_WORDS_NOINIT(1);
1097 u64 applet_resource_user_id;
1098 };
1099 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1100
1101 const auto parameters{rp.PopRaw<Parameters>()};
1102
1103 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1104 controller.DisconnectNpad(parameters.npad_id);
1105
1106 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1107 parameters.applet_resource_user_id);
1108
1109 IPC::ResponseBuilder rb{ctx, 2};
1110 rb.Push(ResultSuccess);
1111}
1112
1113void Hid::GetPlayerLedPattern(HLERequestContext& ctx) {
1114 IPC::RequestParser rp{ctx};
1115 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
1116
1117 Core::HID::LedPattern pattern{0, 0, 0, 0};
1118 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1119 const auto result = controller.GetLedPattern(npad_id, pattern);
1120
1121 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
1122
1123 IPC::ResponseBuilder rb{ctx, 4};
1124 rb.Push(result);
1125 rb.Push(pattern.raw);
1126}
1127
1128void Hid::ActivateNpadWithRevision(HLERequestContext& ctx) {
1129 // Should have no effect with how our npad sets up the data
1130 IPC::RequestParser rp{ctx};
1131 struct Parameters {
1132 s32 revision;
1133 INSERT_PADDING_WORDS_NOINIT(1);
1134 u64 applet_resource_user_id;
1135 };
1136 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1137
1138 const auto parameters{rp.PopRaw<Parameters>()};
1139
1140 applet_resource->ActivateController(HidController::NPad);
1141
1142 LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
1143 parameters.applet_resource_user_id);
1144
1145 IPC::ResponseBuilder rb{ctx, 2};
1146 rb.Push(ResultSuccess);
1147}
1148
1149void Hid::SetNpadJoyHoldType(HLERequestContext& ctx) {
1150 IPC::RequestParser rp{ctx};
1151 const auto applet_resource_user_id{rp.Pop<u64>()};
1152 const auto hold_type{rp.PopEnum<Controller_NPad::NpadJoyHoldType>()};
1153
1154 applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type);
1155
1156 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}",
1157 applet_resource_user_id, hold_type);
1158
1159 IPC::ResponseBuilder rb{ctx, 2};
1160 rb.Push(ResultSuccess);
1161}
1162
1163void Hid::GetNpadJoyHoldType(HLERequestContext& ctx) {
1164 IPC::RequestParser rp{ctx};
1165 const auto applet_resource_user_id{rp.Pop<u64>()};
1166
1167 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1168
1169 IPC::ResponseBuilder rb{ctx, 4};
1170 rb.Push(ResultSuccess);
1171 rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad).GetHoldType());
1172}
1173
1174void Hid::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) {
1175 IPC::RequestParser rp{ctx};
1176 struct Parameters {
1177 Core::HID::NpadIdType npad_id;
1178 INSERT_PADDING_WORDS_NOINIT(1);
1179 u64 applet_resource_user_id;
1180 };
1181 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1182
1183 const auto parameters{rp.PopRaw<Parameters>()};
1184
1185 Core::HID::NpadIdType new_npad_id{};
1186 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1187 controller.SetNpadMode(new_npad_id, parameters.npad_id,
1188 Controller_NPad::NpadJoyDeviceType::Left,
1189 Controller_NPad::NpadJoyAssignmentMode::Single);
1190
1191 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1192 parameters.applet_resource_user_id);
1193
1194 IPC::ResponseBuilder rb{ctx, 2};
1195 rb.Push(ResultSuccess);
1196}
1197
1198void Hid::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
1199 IPC::RequestParser rp{ctx};
1200 struct Parameters {
1201 Core::HID::NpadIdType npad_id;
1202 INSERT_PADDING_WORDS_NOINIT(1);
1203 u64 applet_resource_user_id;
1204 Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
1205 };
1206 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1207
1208 const auto parameters{rp.PopRaw<Parameters>()};
1209
1210 Core::HID::NpadIdType new_npad_id{};
1211 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1212 controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1213 Controller_NPad::NpadJoyAssignmentMode::Single);
1214
1215 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1216 parameters.npad_id, parameters.applet_resource_user_id,
1217 parameters.npad_joy_device_type);
1218
1219 IPC::ResponseBuilder rb{ctx, 2};
1220 rb.Push(ResultSuccess);
1221}
1222
1223void Hid::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
1224 IPC::RequestParser rp{ctx};
1225 struct Parameters {
1226 Core::HID::NpadIdType npad_id;
1227 INSERT_PADDING_WORDS_NOINIT(1);
1228 u64 applet_resource_user_id;
1229 };
1230 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1231
1232 const auto parameters{rp.PopRaw<Parameters>()};
1233
1234 Core::HID::NpadIdType new_npad_id{};
1235 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1236 controller.SetNpadMode(new_npad_id, parameters.npad_id, {},
1237 Controller_NPad::NpadJoyAssignmentMode::Dual);
1238
1239 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1240 parameters.applet_resource_user_id);
1241
1242 IPC::ResponseBuilder rb{ctx, 2};
1243 rb.Push(ResultSuccess);
1244}
1245
1246void Hid::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) {
1247 IPC::RequestParser rp{ctx};
1248 const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
1249 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1250 const auto applet_resource_user_id{rp.Pop<u64>()};
1251
1252 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1253 const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
1254
1255 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1256 npad_id_1, npad_id_2, applet_resource_user_id);
1257
1258 IPC::ResponseBuilder rb{ctx, 2};
1259 rb.Push(result);
1260}
1261
1262void Hid::StartLrAssignmentMode(HLERequestContext& ctx) {
1263 IPC::RequestParser rp{ctx};
1264 const auto applet_resource_user_id{rp.Pop<u64>()};
1265
1266 applet_resource->GetController<Controller_NPad>(HidController::NPad).StartLRAssignmentMode();
1267
1268 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1269
1270 IPC::ResponseBuilder rb{ctx, 2};
1271 rb.Push(ResultSuccess);
1272}
1273
1274void Hid::StopLrAssignmentMode(HLERequestContext& ctx) {
1275 IPC::RequestParser rp{ctx};
1276 const auto applet_resource_user_id{rp.Pop<u64>()};
1277
1278 applet_resource->GetController<Controller_NPad>(HidController::NPad).StopLRAssignmentMode();
1279
1280 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1281
1282 IPC::ResponseBuilder rb{ctx, 2};
1283 rb.Push(ResultSuccess);
1284}
1285
1286void Hid::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
1287 IPC::RequestParser rp{ctx};
1288 const auto applet_resource_user_id{rp.Pop<u64>()};
1289 const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()};
1290
1291 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1292 .SetNpadHandheldActivationMode(activation_mode);
1293
1294 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}",
1295 applet_resource_user_id, activation_mode);
1296
1297 IPC::ResponseBuilder rb{ctx, 2};
1298 rb.Push(ResultSuccess);
1299}
1300
1301void Hid::GetNpadHandheldActivationMode(HLERequestContext& ctx) {
1302 IPC::RequestParser rp{ctx};
1303 const auto applet_resource_user_id{rp.Pop<u64>()};
1304
1305 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1306
1307 IPC::ResponseBuilder rb{ctx, 4};
1308 rb.Push(ResultSuccess);
1309 rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
1310 .GetNpadHandheldActivationMode());
1311}
1312
1313void Hid::SwapNpadAssignment(HLERequestContext& ctx) {
1314 IPC::RequestParser rp{ctx};
1315 const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
1316 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1317 const auto applet_resource_user_id{rp.Pop<u64>()};
1318
1319 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1320 const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2);
1321
1322 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1323 npad_id_1, npad_id_2, applet_resource_user_id);
1324
1325 IPC::ResponseBuilder rb{ctx, 2};
1326 rb.Push(result);
1327}
1328
1329void Hid::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx) {
1330 IPC::RequestParser rp{ctx};
1331 struct Parameters {
1332 Core::HID::NpadIdType npad_id;
1333 INSERT_PADDING_WORDS_NOINIT(1);
1334 u64 applet_resource_user_id;
1335 };
1336 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1337
1338 const auto parameters{rp.PopRaw<Parameters>()};
1339
1340 bool is_enabled = false;
1341 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1342 const auto result =
1343 controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
1344
1345 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
1346 parameters.npad_id, parameters.applet_resource_user_id);
1347
1348 IPC::ResponseBuilder rb{ctx, 3};
1349 rb.Push(result);
1350 rb.Push(is_enabled);
1351}
1352
1353void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
1354 IPC::RequestParser rp{ctx};
1355 struct Parameters {
1356 bool unintended_home_button_input_protection;
1357 INSERT_PADDING_BYTES_NOINIT(3);
1358 Core::HID::NpadIdType npad_id;
1359 u64 applet_resource_user_id;
1360 };
1361 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1362
1363 const auto parameters{rp.PopRaw<Parameters>()};
1364
1365 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1366 const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
1367 parameters.unintended_home_button_input_protection, parameters.npad_id);
1368
1369 LOG_WARNING(Service_HID,
1370 "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={},"
1371 "applet_resource_user_id={}",
1372 parameters.unintended_home_button_input_protection, parameters.npad_id,
1373 parameters.applet_resource_user_id);
1374
1375 IPC::ResponseBuilder rb{ctx, 2};
1376 rb.Push(result);
1377}
1378
1379void Hid::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx) {
1380 IPC::RequestParser rp{ctx};
1381 struct Parameters {
1382 Core::HID::NpadIdType npad_id;
1383 INSERT_PADDING_WORDS_NOINIT(1);
1384 u64 applet_resource_user_id;
1385 Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
1386 };
1387 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1388
1389 const auto parameters{rp.PopRaw<Parameters>()};
1390
1391 Core::HID::NpadIdType new_npad_id{};
1392 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1393 const auto is_reassigned =
1394 controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1395 Controller_NPad::NpadJoyAssignmentMode::Single);
1396
1397 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1398 parameters.npad_id, parameters.applet_resource_user_id,
1399 parameters.npad_joy_device_type);
1400
1401 IPC::ResponseBuilder rb{ctx, 4};
1402 rb.Push(ResultSuccess);
1403 rb.Push(is_reassigned);
1404 rb.PushEnum(new_npad_id);
1405}
1406
1407void Hid::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
1408 IPC::RequestParser rp{ctx};
1409 struct Parameters {
1410 bool analog_stick_use_center_clamp;
1411 INSERT_PADDING_BYTES_NOINIT(7);
1412 u64 applet_resource_user_id;
1413 };
1414 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1415
1416 const auto parameters{rp.PopRaw<Parameters>()};
1417
1418 GetAppletResource()
1419 ->GetController<Controller_NPad>(HidController::NPad)
1420 .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
1421
1422 LOG_WARNING(Service_HID,
1423 "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
1424 parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id);
1425
1426 IPC::ResponseBuilder rb{ctx, 2};
1427 rb.Push(ResultSuccess);
1428}
1429
1430void Hid::SetNpadCaptureButtonAssignment(HLERequestContext& ctx) {
1431 IPC::RequestParser rp{ctx};
1432 struct Parameters {
1433 Core::HID::NpadStyleSet npad_styleset;
1434 INSERT_PADDING_WORDS_NOINIT(1);
1435 u64 applet_resource_user_id;
1436 Core::HID::NpadButton button;
1437 };
1438 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1439
1440 const auto parameters{rp.PopRaw<Parameters>()};
1441
1442 LOG_WARNING(Service_HID,
1443 "(STUBBED) called, npad_styleset={}, applet_resource_user_id={}, button={}",
1444 parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button);
1445
1446 IPC::ResponseBuilder rb{ctx, 2};
1447 rb.Push(ResultSuccess);
1448}
1449
1450void Hid::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
1451 IPC::RequestParser rp{ctx};
1452 const auto applet_resource_user_id{rp.Pop<u64>()};
1453
1454 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1455 applet_resource_user_id);
1456
1457 IPC::ResponseBuilder rb{ctx, 2};
1458 rb.Push(ResultSuccess);
1459}
1460
1461void Hid::GetVibrationDeviceInfo(HLERequestContext& ctx) {
1462 IPC::RequestParser rp{ctx};
1463 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
1464 const auto& controller =
1465 GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1466
1467 Core::HID::VibrationDeviceInfo vibration_device_info;
1468 bool check_device_index = false;
1469
1470 switch (vibration_device_handle.npad_type) {
1471 case Core::HID::NpadStyleIndex::ProController:
1472 case Core::HID::NpadStyleIndex::Handheld:
1473 case Core::HID::NpadStyleIndex::JoyconDual:
1474 case Core::HID::NpadStyleIndex::JoyconLeft:
1475 case Core::HID::NpadStyleIndex::JoyconRight:
1476 vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
1477 check_device_index = true;
1478 break;
1479 case Core::HID::NpadStyleIndex::GameCube:
1480 vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
1481 break;
1482 case Core::HID::NpadStyleIndex::N64:
1483 vibration_device_info.type = Core::HID::VibrationDeviceType::N64;
1484 break;
1485 default:
1486 vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
1487 break;
1488 }
1489
1490 vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
1491 if (check_device_index) {
1492 switch (vibration_device_handle.device_index) {
1493 case Core::HID::DeviceIndex::Left:
1494 vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
1495 break;
1496 case Core::HID::DeviceIndex::Right:
1497 vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
1498 break;
1499 case Core::HID::DeviceIndex::None:
1500 default:
1501 ASSERT_MSG(false, "DeviceIndex should never be None!");
1502 break;
1503 }
1504 }
1505
1506 LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}",
1507 vibration_device_info.type, vibration_device_info.position);
1508
1509 const auto result = controller.IsDeviceHandleValid(vibration_device_handle);
1510 if (result.IsError()) {
1511 IPC::ResponseBuilder rb{ctx, 2};
1512 rb.Push(result);
1513 return;
1514 }
1515
1516 IPC::ResponseBuilder rb{ctx, 4};
1517 rb.Push(ResultSuccess);
1518 rb.PushRaw(vibration_device_info);
1519}
1520
1521void Hid::SendVibrationValue(HLERequestContext& ctx) {
1522 IPC::RequestParser rp{ctx};
1523 struct Parameters {
1524 Core::HID::VibrationDeviceHandle vibration_device_handle;
1525 Core::HID::VibrationValue vibration_value;
1526 INSERT_PADDING_WORDS_NOINIT(1);
1527 u64 applet_resource_user_id;
1528 };
1529 static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
1530
1531 const auto parameters{rp.PopRaw<Parameters>()};
1532
1533 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1534 .VibrateController(parameters.vibration_device_handle, parameters.vibration_value);
1535
1536 LOG_DEBUG(Service_HID,
1537 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1538 parameters.vibration_device_handle.npad_type,
1539 parameters.vibration_device_handle.npad_id,
1540 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1541
1542 IPC::ResponseBuilder rb{ctx, 2};
1543 rb.Push(ResultSuccess);
1544}
1545
1546void Hid::GetActualVibrationValue(HLERequestContext& ctx) {
1547 IPC::RequestParser rp{ctx};
1548 struct Parameters {
1549 Core::HID::VibrationDeviceHandle vibration_device_handle;
1550 INSERT_PADDING_WORDS_NOINIT(1);
1551 u64 applet_resource_user_id;
1552 };
1553 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1554
1555 const auto parameters{rp.PopRaw<Parameters>()};
1556
1557 LOG_DEBUG(Service_HID,
1558 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1559 parameters.vibration_device_handle.npad_type,
1560 parameters.vibration_device_handle.npad_id,
1561 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1562
1563 IPC::ResponseBuilder rb{ctx, 6};
1564 rb.Push(ResultSuccess);
1565 rb.PushRaw(applet_resource->GetController<Controller_NPad>(HidController::NPad)
1566 .GetLastVibration(parameters.vibration_device_handle));
1567}
1568
1569void Hid::CreateActiveVibrationDeviceList(HLERequestContext& ctx) {
1570 LOG_DEBUG(Service_HID, "called");
1571
1572 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1573 rb.Push(ResultSuccess);
1574 rb.PushIpcInterface<IActiveVibrationDeviceList>(system, applet_resource);
1575}
1576
1577void Hid::PermitVibration(HLERequestContext& ctx) {
1578 IPC::RequestParser rp{ctx};
1579 const auto can_vibrate{rp.Pop<bool>()};
1580
1581 // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
1582 // by converting it to a bool
1583 Settings::values.vibration_enabled.SetValue(can_vibrate);
1584
1585 LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
1586
1587 IPC::ResponseBuilder rb{ctx, 2};
1588 rb.Push(ResultSuccess);
1589}
1590
1591void Hid::IsVibrationPermitted(HLERequestContext& ctx) {
1592 LOG_DEBUG(Service_HID, "called");
1593
1594 // nnSDK checks if a float is greater than zero. We return the bool we stored earlier
1595 const auto is_enabled = Settings::values.vibration_enabled.GetValue();
1596
1597 IPC::ResponseBuilder rb{ctx, 3};
1598 rb.Push(ResultSuccess);
1599 rb.Push(is_enabled);
1600}
1601
1602void Hid::SendVibrationValues(HLERequestContext& ctx) {
1603 IPC::RequestParser rp{ctx};
1604 const auto applet_resource_user_id{rp.Pop<u64>()};
1605
1606 const auto handle_data = ctx.ReadBuffer(0);
1607 const auto handle_count = ctx.GetReadBufferNumElements<Core::HID::VibrationDeviceHandle>(0);
1608 const auto vibration_data = ctx.ReadBuffer(1);
1609 const auto vibration_count = ctx.GetReadBufferNumElements<Core::HID::VibrationValue>(1);
1610
1611 auto vibration_device_handles =
1612 std::span(reinterpret_cast<const Core::HID::VibrationDeviceHandle*>(handle_data.data()),
1613 handle_count);
1614 auto vibration_values = std::span(
1615 reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
1616
1617 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1618 .VibrateControllers(vibration_device_handles, vibration_values);
1619
1620 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1621
1622 IPC::ResponseBuilder rb{ctx, 2};
1623 rb.Push(ResultSuccess);
1624}
1625
1626void Hid::SendVibrationGcErmCommand(HLERequestContext& ctx) {
1627 IPC::RequestParser rp{ctx};
1628 struct Parameters {
1629 Core::HID::VibrationDeviceHandle vibration_device_handle;
1630 INSERT_PADDING_WORDS_NOINIT(1);
1631 u64 applet_resource_user_id;
1632 Core::HID::VibrationGcErmCommand gc_erm_command;
1633 };
1634 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1635
1636 const auto parameters{rp.PopRaw<Parameters>()};
1637
1638 /**
1639 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1640 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below,
1641 * in order to differentiate between Stop and StopHard commands.
1642 * This is done to reuse the controller vibration functions made for regular controllers.
1643 */
1644 const auto vibration_value = [parameters] {
1645 switch (parameters.gc_erm_command) {
1646 case Core::HID::VibrationGcErmCommand::Stop:
1647 return Core::HID::VibrationValue{
1648 .low_amplitude = 0.0f,
1649 .low_frequency = 160.0f,
1650 .high_amplitude = 0.0f,
1651 .high_frequency = 320.0f,
1652 };
1653 case Core::HID::VibrationGcErmCommand::Start:
1654 return Core::HID::VibrationValue{
1655 .low_amplitude = 1.0f,
1656 .low_frequency = 160.0f,
1657 .high_amplitude = 1.0f,
1658 .high_frequency = 320.0f,
1659 };
1660 case Core::HID::VibrationGcErmCommand::StopHard:
1661 return Core::HID::VibrationValue{
1662 .low_amplitude = 0.0f,
1663 .low_frequency = 0.0f,
1664 .high_amplitude = 0.0f,
1665 .high_frequency = 0.0f,
1666 };
1667 default:
1668 return Core::HID::DEFAULT_VIBRATION_VALUE;
1669 }
1670 }();
1671
1672 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1673 .VibrateController(parameters.vibration_device_handle, vibration_value);
1674
1675 LOG_DEBUG(Service_HID,
1676 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
1677 "gc_erm_command={}",
1678 parameters.vibration_device_handle.npad_type,
1679 parameters.vibration_device_handle.npad_id,
1680 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id,
1681 parameters.gc_erm_command);
1682
1683 IPC::ResponseBuilder rb{ctx, 2};
1684 rb.Push(ResultSuccess);
1685}
1686
1687void Hid::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
1688 IPC::RequestParser rp{ctx};
1689 struct Parameters {
1690 Core::HID::VibrationDeviceHandle vibration_device_handle;
1691 INSERT_PADDING_WORDS_NOINIT(1);
1692 u64 applet_resource_user_id;
1693 };
1694
1695 const auto parameters{rp.PopRaw<Parameters>()};
1696
1697 const auto last_vibration = applet_resource->GetController<Controller_NPad>(HidController::NPad)
1698 .GetLastVibration(parameters.vibration_device_handle);
1699
1700 const auto gc_erm_command = [last_vibration] {
1701 if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
1702 return Core::HID::VibrationGcErmCommand::Start;
1703 }
1704
1705 /**
1706 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1707 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function
1708 * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
1709 * This is done to reuse the controller vibration functions made for regular controllers.
1710 */
1711 if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
1712 return Core::HID::VibrationGcErmCommand::StopHard;
1713 }
1714
1715 return Core::HID::VibrationGcErmCommand::Stop;
1716 }();
1717
1718 LOG_DEBUG(Service_HID,
1719 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1720 parameters.vibration_device_handle.npad_type,
1721 parameters.vibration_device_handle.npad_id,
1722 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1723
1724 IPC::ResponseBuilder rb{ctx, 4};
1725 rb.Push(ResultSuccess);
1726 rb.PushEnum(gc_erm_command);
1727}
1728
1729void Hid::BeginPermitVibrationSession(HLERequestContext& ctx) {
1730 IPC::RequestParser rp{ctx};
1731 const auto applet_resource_user_id{rp.Pop<u64>()};
1732
1733 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1734 .SetPermitVibrationSession(true);
1735
1736 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1737
1738 IPC::ResponseBuilder rb{ctx, 2};
1739 rb.Push(ResultSuccess);
1740}
1741
1742void Hid::EndPermitVibrationSession(HLERequestContext& ctx) {
1743 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1744 .SetPermitVibrationSession(false);
1745
1746 LOG_DEBUG(Service_HID, "called");
1747
1748 IPC::ResponseBuilder rb{ctx, 2};
1749 rb.Push(ResultSuccess);
1750}
1751
1752void Hid::IsVibrationDeviceMounted(HLERequestContext& ctx) {
1753 IPC::RequestParser rp{ctx};
1754 struct Parameters {
1755 Core::HID::VibrationDeviceHandle vibration_device_handle;
1756 INSERT_PADDING_WORDS_NOINIT(1);
1757 u64 applet_resource_user_id;
1758 };
1759 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1760
1761 const auto parameters{rp.PopRaw<Parameters>()};
1762
1763 LOG_DEBUG(Service_HID,
1764 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1765 parameters.vibration_device_handle.npad_type,
1766 parameters.vibration_device_handle.npad_id,
1767 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1768
1769 IPC::ResponseBuilder rb{ctx, 3};
1770 rb.Push(ResultSuccess);
1771 rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
1772 .IsVibrationDeviceMounted(parameters.vibration_device_handle));
1773}
1774
1775void Hid::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
1776 IPC::RequestParser rp{ctx};
1777 const auto applet_resource_user_id{rp.Pop<u64>()};
1778
1779 applet_resource->ActivateController(HidController::ConsoleSixAxisSensor);
1780
1781 LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1782
1783 IPC::ResponseBuilder rb{ctx, 2};
1784 rb.Push(ResultSuccess);
1785}
1786
1787void Hid::StartConsoleSixAxisSensor(HLERequestContext& ctx) {
1788 IPC::RequestParser rp{ctx};
1789 struct Parameters {
1790 Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
1791 INSERT_PADDING_WORDS_NOINIT(1);
1792 u64 applet_resource_user_id;
1793 };
1794 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1795
1796 const auto parameters{rp.PopRaw<Parameters>()};
1797
1798 LOG_WARNING(Service_HID,
1799 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
1800 parameters.console_sixaxis_handle.unknown_1,
1801 parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
1802
1803 IPC::ResponseBuilder rb{ctx, 2};
1804 rb.Push(ResultSuccess);
1805}
1806
1807void Hid::StopConsoleSixAxisSensor(HLERequestContext& ctx) {
1808 IPC::RequestParser rp{ctx};
1809 struct Parameters {
1810 Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
1811 INSERT_PADDING_WORDS_NOINIT(1);
1812 u64 applet_resource_user_id;
1813 };
1814 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1815
1816 const auto parameters{rp.PopRaw<Parameters>()};
1817
1818 LOG_WARNING(Service_HID,
1819 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
1820 parameters.console_sixaxis_handle.unknown_1,
1821 parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
1822
1823 IPC::ResponseBuilder rb{ctx, 2};
1824 rb.Push(ResultSuccess);
1825}
1826
1827void Hid::ActivateSevenSixAxisSensor(HLERequestContext& ctx) {
1828 IPC::RequestParser rp{ctx};
1829 const auto applet_resource_user_id{rp.Pop<u64>()};
1830
1831 applet_resource->ActivateController(HidController::ConsoleSixAxisSensor);
1832
1833 LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1834
1835 IPC::ResponseBuilder rb{ctx, 2};
1836 rb.Push(ResultSuccess);
1837}
1838
1839void Hid::StartSevenSixAxisSensor(HLERequestContext& ctx) {
1840 IPC::RequestParser rp{ctx};
1841 const auto applet_resource_user_id{rp.Pop<u64>()};
1842
1843 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1844 applet_resource_user_id);
1845
1846 IPC::ResponseBuilder rb{ctx, 2};
1847 rb.Push(ResultSuccess);
1848}
1849
1850void Hid::StopSevenSixAxisSensor(HLERequestContext& ctx) {
1851 IPC::RequestParser rp{ctx};
1852 const auto applet_resource_user_id{rp.Pop<u64>()};
1853
1854 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1855 applet_resource_user_id);
1856
1857 IPC::ResponseBuilder rb{ctx, 2};
1858 rb.Push(ResultSuccess);
1859}
1860
1861void Hid::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
1862 IPC::RequestParser rp{ctx};
1863 const auto applet_resource_user_id{rp.Pop<u64>()};
1864 const auto t_mem_1_size{rp.Pop<u64>()};
1865 const auto t_mem_2_size{rp.Pop<u64>()};
1866 const auto t_mem_1_handle{ctx.GetCopyHandle(0)};
1867 const auto t_mem_2_handle{ctx.GetCopyHandle(1)};
1868
1869 ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
1870 ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
1871
1872 auto t_mem_1 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
1873 t_mem_1_handle);
1874
1875 if (t_mem_1.IsNull()) {
1876 LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
1877 IPC::ResponseBuilder rb{ctx, 2};
1878 rb.Push(ResultUnknown);
1879 return;
1880 }
1881
1882 auto t_mem_2 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
1883 t_mem_2_handle);
1884
1885 if (t_mem_2.IsNull()) {
1886 LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
1887 IPC::ResponseBuilder rb{ctx, 2};
1888 rb.Push(ResultUnknown);
1889 return;
1890 }
1891
1892 ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size");
1893 ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
1894
1895 // Activate console six axis controller
1896 applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
1897 .ActivateController();
1898
1899 applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
1900 .SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
1901
1902 LOG_WARNING(Service_HID,
1903 "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
1904 "applet_resource_user_id={}",
1905 t_mem_1_handle, t_mem_2_handle, applet_resource_user_id);
1906
1907 IPC::ResponseBuilder rb{ctx, 2};
1908 rb.Push(ResultSuccess);
1909}
1910
1911void Hid::FinalizeSevenSixAxisSensor(HLERequestContext& ctx) {
1912 IPC::RequestParser rp{ctx};
1913 const auto applet_resource_user_id{rp.Pop<u64>()};
1914
1915 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1916 applet_resource_user_id);
1917
1918 IPC::ResponseBuilder rb{ctx, 2};
1919 rb.Push(ResultSuccess);
1920}
1921
1922void Hid::ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx) {
1923 IPC::RequestParser rp{ctx};
1924 const auto applet_resource_user_id{rp.Pop<u64>()};
1925
1926 applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
1927 .ResetTimestamp();
1928
1929 LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1930
1931 IPC::ResponseBuilder rb{ctx, 2};
1932 rb.Push(ResultSuccess);
1933}
1934
1935void Hid::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
1936 IPC::RequestParser rp{ctx};
1937
1938 LOG_WARNING(Service_HID, "(STUBBED) called");
1939
1940 IPC::ResponseBuilder rb{ctx, 3};
1941 rb.Push(ResultSuccess);
1942 rb.Push(false);
1943}
1944
1945void Hid::GetPalmaConnectionHandle(HLERequestContext& ctx) {
1946 IPC::RequestParser rp{ctx};
1947 struct Parameters {
1948 Core::HID::NpadIdType npad_id;
1949 INSERT_PADDING_WORDS_NOINIT(1);
1950 u64 applet_resource_user_id;
1951 };
1952 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1953
1954 const auto parameters{rp.PopRaw<Parameters>()};
1955
1956 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
1957 parameters.npad_id, parameters.applet_resource_user_id);
1958
1959 Controller_Palma::PalmaConnectionHandle handle;
1960 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
1961 const auto result = controller.GetPalmaConnectionHandle(parameters.npad_id, handle);
1962
1963 IPC::ResponseBuilder rb{ctx, 4};
1964 rb.Push(result);
1965 rb.PushRaw(handle);
1966}
1967
1968void Hid::InitializePalma(HLERequestContext& ctx) {
1969 IPC::RequestParser rp{ctx};
1970 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
1971
1972 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
1973
1974 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
1975 const auto result = controller.InitializePalma(connection_handle);
1976
1977 IPC::ResponseBuilder rb{ctx, 2};
1978 rb.Push(result);
1979}
1980
1981void Hid::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) {
1982 IPC::RequestParser rp{ctx};
1983 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
1984
1985 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
1986
1987 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
1988
1989 IPC::ResponseBuilder rb{ctx, 2, 1};
1990 rb.Push(ResultSuccess);
1991 rb.PushCopyObjects(controller.AcquirePalmaOperationCompleteEvent(connection_handle));
1992}
1993
1994void Hid::GetPalmaOperationInfo(HLERequestContext& ctx) {
1995 IPC::RequestParser rp{ctx};
1996 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
1997
1998 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
1999
2000 Controller_Palma::PalmaOperationType operation_type;
2001 Controller_Palma::PalmaOperationData data;
2002 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
2003 const auto result = controller.GetPalmaOperationInfo(connection_handle, operation_type, data);
2004
2005 if (result.IsError()) {
2006 IPC::ResponseBuilder rb{ctx, 2};
2007 rb.Push(result);
2008 }
2009
2010 ctx.WriteBuffer(data);
2011 IPC::ResponseBuilder rb{ctx, 4};
2012 rb.Push(result);
2013 rb.Push(static_cast<u64>(operation_type));
2014}
2015
2016void Hid::PlayPalmaActivity(HLERequestContext& ctx) {
2017 IPC::RequestParser rp{ctx};
2018 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2019 const auto palma_activity{rp.Pop<u64>()};
2020
2021 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, palma_activity={}",
2022 connection_handle.npad_id, palma_activity);
2023
2024 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
2025 const auto result = controller.PlayPalmaActivity(connection_handle, palma_activity);
2026
2027 IPC::ResponseBuilder rb{ctx, 2};
2028 rb.Push(result);
2029}
2030
2031void Hid::SetPalmaFrModeType(HLERequestContext& ctx) {
2032 IPC::RequestParser rp{ctx};
2033 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2034 const auto fr_mode{rp.PopEnum<Controller_Palma::PalmaFrModeType>()};
2035
2036 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, fr_mode={}",
2037 connection_handle.npad_id, fr_mode);
2038
2039 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
2040 const auto result = controller.SetPalmaFrModeType(connection_handle, fr_mode);
2041
2042 IPC::ResponseBuilder rb{ctx, 2};
2043 rb.Push(result);
2044}
2045
2046void Hid::ReadPalmaStep(HLERequestContext& ctx) {
2047 IPC::RequestParser rp{ctx};
2048 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2049
2050 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2051
2052 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
2053 const auto result = controller.ReadPalmaStep(connection_handle);
2054
2055 IPC::ResponseBuilder rb{ctx, 2};
2056 rb.Push(result);
2057}
2058
2059void Hid::EnablePalmaStep(HLERequestContext& ctx) {
2060 IPC::RequestParser rp{ctx};
2061 struct Parameters {
2062 bool is_enabled;
2063 INSERT_PADDING_WORDS_NOINIT(1);
2064 Controller_Palma::PalmaConnectionHandle connection_handle;
2065 };
2066 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2067
2068 const auto parameters{rp.PopRaw<Parameters>()};
2069
2070 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, is_enabled={}",
2071 parameters.connection_handle.npad_id, parameters.is_enabled);
2072
2073 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
2074 const auto result =
2075 controller.EnablePalmaStep(parameters.connection_handle, parameters.is_enabled);
2076
2077 IPC::ResponseBuilder rb{ctx, 2};
2078 rb.Push(result);
2079}
2080
2081void Hid::ResetPalmaStep(HLERequestContext& ctx) {
2082 IPC::RequestParser rp{ctx};
2083 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2084
2085 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2086
2087 auto& controller = GetAppletResource()->GetController<Controller_Palma>(HidController::Palma);
2088 const auto result = controller.ResetPalmaStep(connection_handle);
2089
2090 IPC::ResponseBuilder rb{ctx, 2};
2091 rb.Push(result);
2092}
2093
2094void Hid::ReadPalmaApplicationSection(HLERequestContext& ctx) {
2095 LOG_WARNING(Service_HID, "(STUBBED) called");
2096
2097 IPC::ResponseBuilder rb{ctx, 2};
2098 rb.Push(ResultSuccess);
2099}
2100
2101void Hid::WritePalmaApplicationSection(HLERequestContext& ctx) {
2102 LOG_WARNING(Service_HID, "(STUBBED) called");
2103
2104 IPC::ResponseBuilder rb{ctx, 2};
2105 rb.Push(ResultSuccess);
2106}
2107
2108void Hid::ReadPalmaUniqueCode(HLERequestContext& ctx) {
2109 IPC::RequestParser rp{ctx};
2110 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2111
2112 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2113
2114 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2115 .ReadPalmaUniqueCode(connection_handle);
2116
2117 IPC::ResponseBuilder rb{ctx, 2};
2118 rb.Push(ResultSuccess);
2119}
2120
2121void Hid::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) {
2122 IPC::RequestParser rp{ctx};
2123 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2124
2125 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2126
2127 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2128 .SetPalmaUniqueCodeInvalid(connection_handle);
2129
2130 IPC::ResponseBuilder rb{ctx, 2};
2131 rb.Push(ResultSuccess);
2132}
2133
2134void Hid::WritePalmaActivityEntry(HLERequestContext& ctx) {
2135 LOG_CRITICAL(Service_HID, "(STUBBED) called");
2136
2137 IPC::ResponseBuilder rb{ctx, 2};
2138 rb.Push(ResultSuccess);
2139}
2140
2141void Hid::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
2142 IPC::RequestParser rp{ctx};
2143 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2144 const auto unknown{rp.Pop<u64>()};
2145
2146 [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
2147
2148 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
2149 connection_handle.npad_id, unknown);
2150
2151 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2152 .WritePalmaRgbLedPatternEntry(connection_handle, unknown);
2153
2154 IPC::ResponseBuilder rb{ctx, 2};
2155 rb.Push(ResultSuccess);
2156}
2157
2158void Hid::WritePalmaWaveEntry(HLERequestContext& ctx) {
2159 IPC::RequestParser rp{ctx};
2160 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2161 const auto wave_set{rp.PopEnum<Controller_Palma::PalmaWaveSet>()};
2162 const auto unknown{rp.Pop<u64>()};
2163 const auto t_mem_size{rp.Pop<u64>()};
2164 const auto t_mem_handle{ctx.GetCopyHandle(0)};
2165 const auto size{rp.Pop<u64>()};
2166
2167 ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes");
2168
2169 auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
2170 t_mem_handle);
2171
2172 if (t_mem.IsNull()) {
2173 LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
2174 IPC::ResponseBuilder rb{ctx, 2};
2175 rb.Push(ResultUnknown);
2176 return;
2177 }
2178
2179 ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size");
2180
2181 LOG_WARNING(Service_HID,
2182 "(STUBBED) called, connection_handle={}, wave_set={}, unknown={}, "
2183 "t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
2184 connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
2185
2186 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2187 .WritePalmaWaveEntry(connection_handle, wave_set, t_mem->GetSourceAddress(), t_mem_size);
2188
2189 IPC::ResponseBuilder rb{ctx, 2};
2190 rb.Push(ResultSuccess);
2191}
2192
2193void Hid::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2194 IPC::RequestParser rp{ctx};
2195 struct Parameters {
2196 s32 database_id_version;
2197 INSERT_PADDING_WORDS_NOINIT(1);
2198 Controller_Palma::PalmaConnectionHandle connection_handle;
2199 };
2200 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2201
2202 const auto parameters{rp.PopRaw<Parameters>()};
2203
2204 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, database_id_version={}",
2205 parameters.connection_handle.npad_id, parameters.database_id_version);
2206
2207 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2208 .SetPalmaDataBaseIdentificationVersion(parameters.connection_handle,
2209 parameters.database_id_version);
2210
2211 IPC::ResponseBuilder rb{ctx, 2};
2212 rb.Push(ResultSuccess);
2213}
2214
2215void Hid::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2216 IPC::RequestParser rp{ctx};
2217 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2218
2219 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2220
2221 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2222 .GetPalmaDataBaseIdentificationVersion(connection_handle);
2223
2224 IPC::ResponseBuilder rb{ctx, 2};
2225 rb.Push(ResultSuccess);
2226}
2227
2228void Hid::SuspendPalmaFeature(HLERequestContext& ctx) {
2229 LOG_WARNING(Service_HID, "(STUBBED) called");
2230
2231 IPC::ResponseBuilder rb{ctx, 2};
2232 rb.Push(ResultSuccess);
2233}
2234
2235void Hid::GetPalmaOperationResult(HLERequestContext& ctx) {
2236 IPC::RequestParser rp{ctx};
2237 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2238
2239 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2240
2241 const auto result = applet_resource->GetController<Controller_Palma>(HidController::Palma)
2242 .GetPalmaOperationResult(connection_handle);
2243
2244 IPC::ResponseBuilder rb{ctx, 2};
2245 rb.Push(result);
2246}
2247
2248void Hid::ReadPalmaPlayLog(HLERequestContext& ctx) {
2249 LOG_WARNING(Service_HID, "(STUBBED) called");
2250
2251 IPC::ResponseBuilder rb{ctx, 2};
2252 rb.Push(ResultSuccess);
2253}
2254
2255void Hid::ResetPalmaPlayLog(HLERequestContext& ctx) {
2256 LOG_WARNING(Service_HID, "(STUBBED) called");
2257
2258 IPC::ResponseBuilder rb{ctx, 2};
2259 rb.Push(ResultSuccess);
2260}
2261
2262void Hid::SetIsPalmaAllConnectable(HLERequestContext& ctx) {
2263 IPC::RequestParser rp{ctx};
2264 struct Parameters {
2265 bool is_palma_all_connectable;
2266 INSERT_PADDING_BYTES_NOINIT(7);
2267 u64 applet_resource_user_id;
2268 };
2269 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2270
2271 const auto parameters{rp.PopRaw<Parameters>()};
2272
2273 LOG_WARNING(Service_HID,
2274 "(STUBBED) called, is_palma_all_connectable={},applet_resource_user_id={}",
2275 parameters.is_palma_all_connectable, parameters.applet_resource_user_id);
2276
2277 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2278 .SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
2279
2280 IPC::ResponseBuilder rb{ctx, 2};
2281 rb.Push(ResultSuccess);
2282}
2283
2284void Hid::SetIsPalmaPairedConnectable(HLERequestContext& ctx) {
2285 LOG_WARNING(Service_HID, "(STUBBED) called");
2286
2287 IPC::ResponseBuilder rb{ctx, 2};
2288 rb.Push(ResultSuccess);
2289}
2290
2291void Hid::PairPalma(HLERequestContext& ctx) {
2292 IPC::RequestParser rp{ctx};
2293 const auto connection_handle{rp.PopRaw<Controller_Palma::PalmaConnectionHandle>()};
2294
2295 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2296
2297 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2298 .PairPalma(connection_handle);
2299
2300 IPC::ResponseBuilder rb{ctx, 2};
2301 rb.Push(ResultSuccess);
2302}
2303
2304void Hid::SetPalmaBoostMode(HLERequestContext& ctx) {
2305 IPC::RequestParser rp{ctx};
2306 const auto palma_boost_mode{rp.Pop<bool>()};
2307
2308 LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode);
2309
2310 applet_resource->GetController<Controller_Palma>(HidController::Palma)
2311 .SetPalmaBoostMode(palma_boost_mode);
2312
2313 IPC::ResponseBuilder rb{ctx, 2};
2314 rb.Push(ResultSuccess);
2315}
2316
2317void Hid::CancelWritePalmaWaveEntry(HLERequestContext& ctx) {
2318 LOG_WARNING(Service_HID, "(STUBBED) called");
2319
2320 IPC::ResponseBuilder rb{ctx, 2};
2321 rb.Push(ResultSuccess);
2322}
2323
2324void Hid::EnablePalmaBoostMode(HLERequestContext& ctx) {
2325 LOG_WARNING(Service_HID, "(STUBBED) called");
2326
2327 IPC::ResponseBuilder rb{ctx, 2};
2328 rb.Push(ResultSuccess);
2329}
2330
2331void Hid::GetPalmaBluetoothAddress(HLERequestContext& ctx) {
2332 LOG_WARNING(Service_HID, "(STUBBED) called");
2333
2334 IPC::ResponseBuilder rb{ctx, 2};
2335 rb.Push(ResultSuccess);
2336}
2337
2338void Hid::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
2339 LOG_WARNING(Service_HID, "(STUBBED) called");
2340
2341 IPC::ResponseBuilder rb{ctx, 2};
2342 rb.Push(ResultSuccess);
2343}
2344
2345void Hid::SetNpadCommunicationMode(HLERequestContext& ctx) {
2346 IPC::RequestParser rp{ctx};
2347 const auto applet_resource_user_id{rp.Pop<u64>()};
2348 const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()};
2349
2350 applet_resource->GetController<Controller_NPad>(HidController::NPad)
2351 .SetNpadCommunicationMode(communication_mode);
2352
2353 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}",
2354 applet_resource_user_id, communication_mode);
2355
2356 IPC::ResponseBuilder rb{ctx, 2};
2357 rb.Push(ResultSuccess);
2358}
2359
2360void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) {
2361 IPC::RequestParser rp{ctx};
2362
2363 LOG_WARNING(Service_HID, "(STUBBED) called");
2364
2365 IPC::ResponseBuilder rb{ctx, 4};
2366 rb.Push(ResultSuccess);
2367 rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad)
2368 .GetNpadCommunicationMode());
2369}
2370
2371void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
2372 IPC::RequestParser rp{ctx};
2373 const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()};
2374 const auto applet_resource_user_id{rp.Pop<u64>()};
2375
2376 LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
2377 touchscreen_mode.mode, applet_resource_user_id);
2378
2379 IPC::ResponseBuilder rb{ctx, 2};
2380 rb.Push(ResultSuccess);
2381}
2382
2383void Hid::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) {
2384 IPC::RequestParser rp{ctx};
2385 struct Parameters {
2386 s32 unknown;
2387 INSERT_PADDING_WORDS_NOINIT(1);
2388 u64 applet_resource_user_id;
2389 };
2390 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2391
2392 const auto parameters{rp.PopRaw<Parameters>()};
2393
2394 LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
2395 parameters.unknown, parameters.applet_resource_user_id);
2396
2397 IPC::ResponseBuilder rb{ctx, 3};
2398 rb.Push(ResultSuccess);
2399 rb.Push(false);
2400}
2401
2402class HidDbg final : public ServiceFramework<HidDbg> {
2403public:
2404 explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} {
2405 // clang-format off
2406 static const FunctionInfo functions[] = {
2407 {0, nullptr, "DeactivateDebugPad"},
2408 {1, nullptr, "SetDebugPadAutoPilotState"},
2409 {2, nullptr, "UnsetDebugPadAutoPilotState"},
2410 {10, nullptr, "DeactivateTouchScreen"},
2411 {11, nullptr, "SetTouchScreenAutoPilotState"},
2412 {12, nullptr, "UnsetTouchScreenAutoPilotState"},
2413 {13, nullptr, "GetTouchScreenConfiguration"},
2414 {14, nullptr, "ProcessTouchScreenAutoTune"},
2415 {15, nullptr, "ForceStopTouchScreenManagement"},
2416 {16, nullptr, "ForceRestartTouchScreenManagement"},
2417 {17, nullptr, "IsTouchScreenManaged"},
2418 {20, nullptr, "DeactivateMouse"},
2419 {21, nullptr, "SetMouseAutoPilotState"},
2420 {22, nullptr, "UnsetMouseAutoPilotState"},
2421 {25, nullptr, "SetDebugMouseAutoPilotState"},
2422 {26, nullptr, "UnsetDebugMouseAutoPilotState"},
2423 {30, nullptr, "DeactivateKeyboard"},
2424 {31, nullptr, "SetKeyboardAutoPilotState"},
2425 {32, nullptr, "UnsetKeyboardAutoPilotState"},
2426 {50, nullptr, "DeactivateXpad"},
2427 {51, nullptr, "SetXpadAutoPilotState"},
2428 {52, nullptr, "UnsetXpadAutoPilotState"},
2429 {53, nullptr, "DeactivateJoyXpad"},
2430 {60, nullptr, "ClearNpadSystemCommonPolicy"},
2431 {61, nullptr, "DeactivateNpad"},
2432 {62, nullptr, "ForceDisconnectNpad"},
2433 {91, nullptr, "DeactivateGesture"},
2434 {110, nullptr, "DeactivateHomeButton"},
2435 {111, nullptr, "SetHomeButtonAutoPilotState"},
2436 {112, nullptr, "UnsetHomeButtonAutoPilotState"},
2437 {120, nullptr, "DeactivateSleepButton"},
2438 {121, nullptr, "SetSleepButtonAutoPilotState"},
2439 {122, nullptr, "UnsetSleepButtonAutoPilotState"},
2440 {123, nullptr, "DeactivateInputDetector"},
2441 {130, nullptr, "DeactivateCaptureButton"},
2442 {131, nullptr, "SetCaptureButtonAutoPilotState"},
2443 {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
2444 {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
2445 {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
2446 {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
2447 {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
2448 {140, nullptr, "DeactivateConsoleSixAxisSensor"},
2449 {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
2450 {142, nullptr, "DeactivateSevenSixAxisSensor"},
2451 {143, nullptr, "GetConsoleSixAxisSensorCountStates"},
2452 {144, nullptr, "GetAccelerometerFsr"},
2453 {145, nullptr, "SetAccelerometerFsr"},
2454 {146, nullptr, "GetAccelerometerOdr"},
2455 {147, nullptr, "SetAccelerometerOdr"},
2456 {148, nullptr, "GetGyroscopeFsr"},
2457 {149, nullptr, "SetGyroscopeFsr"},
2458 {150, nullptr, "GetGyroscopeOdr"},
2459 {151, nullptr, "SetGyroscopeOdr"},
2460 {152, nullptr, "GetWhoAmI"},
2461 {201, nullptr, "ActivateFirmwareUpdate"},
2462 {202, nullptr, "DeactivateFirmwareUpdate"},
2463 {203, nullptr, "StartFirmwareUpdate"},
2464 {204, nullptr, "GetFirmwareUpdateStage"},
2465 {205, nullptr, "GetFirmwareVersion"},
2466 {206, nullptr, "GetDestinationFirmwareVersion"},
2467 {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
2468 {208, nullptr, "StartFirmwareUpdateForRevert"},
2469 {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
2470 {210, nullptr, "IsFirmwareUpdatingDevice"},
2471 {211, nullptr, "StartFirmwareUpdateIndividual"},
2472 {215, nullptr, "SetUsbFirmwareForceUpdateEnabled"},
2473 {216, nullptr, "SetAllKuinaDevicesToFirmwareUpdateMode"},
2474 {221, nullptr, "UpdateControllerColor"},
2475 {222, nullptr, "ConnectUsbPadsAsync"},
2476 {223, nullptr, "DisconnectUsbPadsAsync"},
2477 {224, nullptr, "UpdateDesignInfo"},
2478 {225, nullptr, "GetUniquePadDriverState"},
2479 {226, nullptr, "GetSixAxisSensorDriverStates"},
2480 {227, nullptr, "GetRxPacketHistory"},
2481 {228, nullptr, "AcquireOperationEventHandle"},
2482 {229, nullptr, "ReadSerialFlash"},
2483 {230, nullptr, "WriteSerialFlash"},
2484 {231, nullptr, "GetOperationResult"},
2485 {232, nullptr, "EnableShipmentMode"},
2486 {233, nullptr, "ClearPairingInfo"},
2487 {234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
2488 {235, nullptr, "EnableAnalogStickPower"},
2489 {236, nullptr, "RequestKuinaUartClockCal"},
2490 {237, nullptr, "GetKuinaUartClockCal"},
2491 {238, nullptr, "SetKuinaUartClockTrim"},
2492 {239, nullptr, "KuinaLoopbackTest"},
2493 {240, nullptr, "RequestBatteryVoltage"},
2494 {241, nullptr, "GetBatteryVoltage"},
2495 {242, nullptr, "GetUniquePadPowerInfo"},
2496 {243, nullptr, "RebootUniquePad"},
2497 {244, nullptr, "RequestKuinaFirmwareVersion"},
2498 {245, nullptr, "GetKuinaFirmwareVersion"},
2499 {246, nullptr, "GetVidPid"},
2500 {247, nullptr, "GetAnalogStickCalibrationValue"},
2501 {248, nullptr, "GetUniquePadIdsFull"},
2502 {249, nullptr, "ConnectUniquePad"},
2503 {250, nullptr, "IsVirtual"},
2504 {251, nullptr, "GetAnalogStickModuleParam"},
2505 {301, nullptr, "GetAbstractedPadHandles"},
2506 {302, nullptr, "GetAbstractedPadState"},
2507 {303, nullptr, "GetAbstractedPadsState"},
2508 {321, nullptr, "SetAutoPilotVirtualPadState"},
2509 {322, nullptr, "UnsetAutoPilotVirtualPadState"},
2510 {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
2511 {324, nullptr, "AttachHdlsWorkBuffer"},
2512 {325, nullptr, "ReleaseHdlsWorkBuffer"},
2513 {326, nullptr, "DumpHdlsNpadAssignmentState"},
2514 {327, nullptr, "DumpHdlsStates"},
2515 {328, nullptr, "ApplyHdlsNpadAssignmentState"},
2516 {329, nullptr, "ApplyHdlsStateList"},
2517 {330, nullptr, "AttachHdlsVirtualDevice"},
2518 {331, nullptr, "DetachHdlsVirtualDevice"},
2519 {332, nullptr, "SetHdlsState"},
2520 {350, nullptr, "AddRegisteredDevice"},
2521 {400, nullptr, "DisableExternalMcuOnNxDevice"},
2522 {401, nullptr, "DisableRailDeviceFiltering"},
2523 {402, nullptr, "EnableWiredPairing"},
2524 {403, nullptr, "EnableShipmentModeAutoClear"},
2525 {404, nullptr, "SetRailEnabled"},
2526 {500, nullptr, "SetFactoryInt"},
2527 {501, nullptr, "IsFactoryBootEnabled"},
2528 {550, nullptr, "SetAnalogStickModelDataTemporarily"},
2529 {551, nullptr, "GetAnalogStickModelData"},
2530 {552, nullptr, "ResetAnalogStickModelData"},
2531 {600, nullptr, "ConvertPadState"},
2532 {650, nullptr, "AddButtonPlayData"},
2533 {651, nullptr, "StartButtonPlayData"},
2534 {652, nullptr, "StopButtonPlayData"},
2535 {2000, nullptr, "DeactivateDigitizer"},
2536 {2001, nullptr, "SetDigitizerAutoPilotState"},
2537 {2002, nullptr, "UnsetDigitizerAutoPilotState"},
2538 {2002, nullptr, "ReloadFirmwareDebugSettings"},
2539 };
2540 // clang-format on
2541
2542 RegisterHandlers(functions);
2543 }
2544};
2545
2546class HidSys final : public ServiceFramework<HidSys> {
2547public:
2548 explicit HidSys(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_)
2549 : ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"},
2550 applet_resource{applet_resource_} {
2551 // clang-format off
2552 static const FunctionInfo functions[] = {
2553 {31, nullptr, "SendKeyboardLockKeyEvent"},
2554 {101, nullptr, "AcquireHomeButtonEventHandle"},
2555 {111, nullptr, "ActivateHomeButton"},
2556 {121, nullptr, "AcquireSleepButtonEventHandle"},
2557 {131, nullptr, "ActivateSleepButton"},
2558 {141, nullptr, "AcquireCaptureButtonEventHandle"},
2559 {151, nullptr, "ActivateCaptureButton"},
2560 {161, nullptr, "GetPlatformConfig"},
2561 {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
2562 {211, nullptr, "GetNpadsWithNfc"},
2563 {212, nullptr, "AcquireNfcActivateEventHandle"},
2564 {213, nullptr, "ActivateNfc"},
2565 {214, nullptr, "GetXcdHandleForNpadWithNfc"},
2566 {215, nullptr, "IsNfcActivated"},
2567 {230, nullptr, "AcquireIrSensorEventHandle"},
2568 {231, nullptr, "ActivateIrSensor"},
2569 {232, nullptr, "GetIrSensorState"},
2570 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
2571 {301, nullptr, "ActivateNpadSystem"},
2572 {303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
2573 {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
2574 {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
2575 {306, &HidSys::GetLastActiveNpad, "GetLastActiveNpad"},
2576 {307, nullptr, "GetNpadSystemExtStyle"},
2577 {308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
2578 {309, nullptr, "GetNpadFullKeyGripColor"},
2579 {310, nullptr, "GetMaskedSupportedNpadStyleSet"},
2580 {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
2581 {312, nullptr, "SetSupportedNpadStyleSetAll"},
2582 {313, nullptr, "GetNpadCaptureButtonAssignment"},
2583 {314, nullptr, "GetAppletFooterUiType"},
2584 {315, nullptr, "GetAppletDetailedUiType"},
2585 {316, nullptr, "GetNpadInterfaceType"},
2586 {317, nullptr, "GetNpadLeftRightInterfaceType"},
2587 {318, nullptr, "HasBattery"},
2588 {319, nullptr, "HasLeftRightBattery"},
2589 {321, &HidSys::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
2590 {322, nullptr, "GetIrSensorState"},
2591 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
2592 {324, nullptr, "GetUniquePadButtonSet"},
2593 {325, nullptr, "GetUniquePadColor"},
2594 {326, nullptr, "GetUniquePadAppletDetailedUiType"},
2595 {327, nullptr, "GetAbstractedPadIdDataFromNpad"},
2596 {328, nullptr, "AttachAbstractedPadToNpad"},
2597 {329, nullptr, "DetachAbstractedPadAll"},
2598 {330, nullptr, "CheckAbstractedPadConnection"},
2599 {500, nullptr, "SetAppletResourceUserId"},
2600 {501, nullptr, "RegisterAppletResourceUserId"},
2601 {502, nullptr, "UnregisterAppletResourceUserId"},
2602 {503, nullptr, "EnableAppletToGetInput"},
2603 {504, nullptr, "SetAruidValidForVibration"},
2604 {505, nullptr, "EnableAppletToGetSixAxisSensor"},
2605 {506, nullptr, "EnableAppletToGetPadInput"},
2606 {507, nullptr, "EnableAppletToGetTouchScreen"},
2607 {510, nullptr, "SetVibrationMasterVolume"},
2608 {511, nullptr, "GetVibrationMasterVolume"},
2609 {512, nullptr, "BeginPermitVibrationSession"},
2610 {513, nullptr, "EndPermitVibrationSession"},
2611 {514, nullptr, "Unknown514"},
2612 {520, nullptr, "EnableHandheldHids"},
2613 {521, nullptr, "DisableHandheldHids"},
2614 {522, nullptr, "SetJoyConRailEnabled"},
2615 {523, nullptr, "IsJoyConRailEnabled"},
2616 {524, nullptr, "IsHandheldHidsEnabled"},
2617 {525, nullptr, "IsJoyConAttachedOnAllRail"},
2618 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
2619 {541, nullptr, "GetPlayReportControllerUsages"},
2620 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
2621 {543, nullptr, "GetRegisteredDevicesOld"},
2622 {544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
2623 {545, nullptr, "SendConnectionTrigger"},
2624 {546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
2625 {547, nullptr, "GetAllowedBluetoothLinksCount"},
2626 {548, nullptr, "GetRegisteredDevices"},
2627 {549, nullptr, "GetConnectableRegisteredDevices"},
2628 {700, nullptr, "ActivateUniquePad"},
2629 {702, nullptr, "AcquireUniquePadConnectionEventHandle"},
2630 {703, nullptr, "GetUniquePadIds"},
2631 {751, &HidSys::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
2632 {800, nullptr, "ListSixAxisSensorHandles"},
2633 {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
2634 {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
2635 {803, nullptr, "StartSixAxisSensorUserCalibration"},
2636 {804, nullptr, "CancelSixAxisSensorUserCalibration"},
2637 {805, nullptr, "GetUniquePadBluetoothAddress"},
2638 {806, nullptr, "DisconnectUniquePad"},
2639 {807, nullptr, "GetUniquePadType"},
2640 {808, nullptr, "GetUniquePadInterface"},
2641 {809, nullptr, "GetUniquePadSerialNumber"},
2642 {810, nullptr, "GetUniquePadControllerNumber"},
2643 {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
2644 {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
2645 {821, nullptr, "StartAnalogStickManualCalibration"},
2646 {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
2647 {823, nullptr, "CancelAnalogStickManualCalibration"},
2648 {824, nullptr, "ResetAnalogStickManualCalibration"},
2649 {825, nullptr, "GetAnalogStickState"},
2650 {826, nullptr, "GetAnalogStickManualCalibrationStage"},
2651 {827, nullptr, "IsAnalogStickButtonPressed"},
2652 {828, nullptr, "IsAnalogStickInReleasePosition"},
2653 {829, nullptr, "IsAnalogStickInCircumference"},
2654 {830, nullptr, "SetNotificationLedPattern"},
2655 {831, nullptr, "SetNotificationLedPatternWithTimeout"},
2656 {832, nullptr, "PrepareHidsForNotificationWake"},
2657 {850, &HidSys::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
2658 {851, nullptr, "EnableUsbFullKeyController"},
2659 {852, nullptr, "IsUsbConnected"},
2660 {870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
2661 {900, nullptr, "ActivateInputDetector"},
2662 {901, nullptr, "NotifyInputDetector"},
2663 {1000, nullptr, "InitializeFirmwareUpdate"},
2664 {1001, nullptr, "GetFirmwareVersion"},
2665 {1002, nullptr, "GetAvailableFirmwareVersion"},
2666 {1003, nullptr, "IsFirmwareUpdateAvailable"},
2667 {1004, nullptr, "CheckFirmwareUpdateRequired"},
2668 {1005, nullptr, "StartFirmwareUpdate"},
2669 {1006, nullptr, "AbortFirmwareUpdate"},
2670 {1007, nullptr, "GetFirmwareUpdateState"},
2671 {1008, nullptr, "ActivateAudioControl"},
2672 {1009, nullptr, "AcquireAudioControlEventHandle"},
2673 {1010, nullptr, "GetAudioControlStates"},
2674 {1011, nullptr, "DeactivateAudioControl"},
2675 {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
2676 {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
2677 {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
2678 {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
2679 {1100, nullptr, "GetHidbusSystemServiceObject"},
2680 {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
2681 {1130, nullptr, "InitializeUsbFirmwareUpdate"},
2682 {1131, nullptr, "FinalizeUsbFirmwareUpdate"},
2683 {1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
2684 {1133, nullptr, "StartUsbFirmwareUpdate"},
2685 {1134, nullptr, "GetUsbFirmwareUpdateState"},
2686 {1150, nullptr, "SetTouchScreenMagnification"},
2687 {1151, nullptr, "GetTouchScreenFirmwareVersion"},
2688 {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
2689 {1153, &HidSys::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
2690 {1154, nullptr, "IsFirmwareAvailableForNotification"},
2691 {1155, nullptr, "SetForceHandheldStyleVibration"},
2692 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
2693 {1157, nullptr, "CancelConnectionTrigger"},
2694 {1200, nullptr, "IsButtonConfigSupported"},
2695 {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
2696 {1202, nullptr, "DeleteButtonConfig"},
2697 {1203, nullptr, "DeleteButtonConfigEmbedded"},
2698 {1204, nullptr, "SetButtonConfigEnabled"},
2699 {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
2700 {1206, nullptr, "IsButtonConfigEnabled"},
2701 {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
2702 {1208, nullptr, "SetButtonConfigEmbedded"},
2703 {1209, nullptr, "SetButtonConfigFull"},
2704 {1210, nullptr, "SetButtonConfigLeft"},
2705 {1211, nullptr, "SetButtonConfigRight"},
2706 {1212, nullptr, "GetButtonConfigEmbedded"},
2707 {1213, nullptr, "GetButtonConfigFull"},
2708 {1214, nullptr, "GetButtonConfigLeft"},
2709 {1215, nullptr, "GetButtonConfigRight"},
2710 {1250, nullptr, "IsCustomButtonConfigSupported"},
2711 {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
2712 {1252, nullptr, "IsDefaultButtonConfigFull"},
2713 {1253, nullptr, "IsDefaultButtonConfigLeft"},
2714 {1254, nullptr, "IsDefaultButtonConfigRight"},
2715 {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
2716 {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
2717 {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
2718 {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
2719 {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
2720 {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
2721 {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
2722 {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
2723 {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
2724 {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
2725 {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
2726 {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
2727 {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
2728 {1268, nullptr, "DeleteButtonConfigStorageFull"},
2729 {1269, nullptr, "DeleteButtonConfigStorageLeft"},
2730 {1270, nullptr, "DeleteButtonConfigStorageRight"},
2731 {1271, nullptr, "IsUsingCustomButtonConfig"},
2732 {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
2733 {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
2734 {1274, nullptr, "SetDefaultButtonConfig"},
2735 {1275, nullptr, "SetAllDefaultButtonConfig"},
2736 {1276, nullptr, "SetHidButtonConfigEmbedded"},
2737 {1277, nullptr, "SetHidButtonConfigFull"},
2738 {1278, nullptr, "SetHidButtonConfigLeft"},
2739 {1279, nullptr, "SetHidButtonConfigRight"},
2740 {1280, nullptr, "GetHidButtonConfigEmbedded"},
2741 {1281, nullptr, "GetHidButtonConfigFull"},
2742 {1282, nullptr, "GetHidButtonConfigLeft"},
2743 {1283, nullptr, "GetHidButtonConfigRight"},
2744 {1284, nullptr, "GetButtonConfigStorageEmbedded"},
2745 {1285, nullptr, "GetButtonConfigStorageFull"},
2746 {1286, nullptr, "GetButtonConfigStorageLeft"},
2747 {1287, nullptr, "GetButtonConfigStorageRight"},
2748 {1288, nullptr, "SetButtonConfigStorageEmbedded"},
2749 {1289, nullptr, "SetButtonConfigStorageFull"},
2750 {1290, nullptr, "DeleteButtonConfigStorageRight"},
2751 {1291, nullptr, "DeleteButtonConfigStorageRight"},
2752 };
2753 // clang-format on
2754
2755 RegisterHandlers(functions);
2756
2757 joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
2758 }
2759
2760 ~HidSys() {
2761 service_context.CloseEvent(joy_detach_event);
2762 };
2763
2764private:
2765 void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
2766 LOG_WARNING(Service_HID, "called");
2767
2768 GetAppletResource()
2769 ->GetController<Controller_NPad>(HidController::NPad)
2770 .ApplyNpadSystemCommonPolicy();
2771
2772 IPC::ResponseBuilder rb{ctx, 2};
2773 rb.Push(ResultSuccess);
2774 }
2775
2776 void GetLastActiveNpad(HLERequestContext& ctx) {
2777 LOG_DEBUG(Service_HID, "(STUBBED) called");
2778
2779 IPC::ResponseBuilder rb{ctx, 3};
2780 rb.Push(ResultSuccess);
2781 rb.PushEnum(system.HIDCore().GetLastActiveController());
2782 }
2783
2784 void GetUniquePadsFromNpad(HLERequestContext& ctx) {
2785 IPC::RequestParser rp{ctx};
2786 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
2787
2788 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
2789
2790 const std::vector<Core::HID::UniquePadId> unique_pads{};
2791
2792 ctx.WriteBuffer(unique_pads);
2793
2794 IPC::ResponseBuilder rb{ctx, 3};
2795 rb.Push(ResultSuccess);
2796 rb.Push(static_cast<u32>(unique_pads.size()));
2797 }
2798
2799 void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
2800 LOG_INFO(Service_AM, "called");
2801
2802 IPC::ResponseBuilder rb{ctx, 2, 1};
2803 rb.Push(ResultSuccess);
2804 rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
2805 }
2806
2807 void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
2808 const bool is_enabled = false;
2809
2810 LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
2811
2812 IPC::ResponseBuilder rb{ctx, 3};
2813 rb.Push(ResultSuccess);
2814 rb.Push(is_enabled);
2815 }
2816
2817 void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
2818 LOG_WARNING(Service_HID, "(STUBBED) called");
2819
2820 Core::HID::TouchScreenConfigurationForNx touchscreen_config{
2821 .mode = Core::HID::TouchScreenModeForNx::Finger,
2822 };
2823
2824 if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
2825 touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
2826 touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
2827 }
2828
2829 IPC::ResponseBuilder rb{ctx, 6};
2830 rb.Push(ResultSuccess);
2831 rb.PushRaw(touchscreen_config);
2832 }
2833
2834 std::shared_ptr<IAppletResource> GetAppletResource() {
2835 if (applet_resource == nullptr) {
2836 applet_resource = std::make_shared<IAppletResource>(system, service_context);
2837 }
2838
2839 return applet_resource;
2840 }
2841
2842 Kernel::KEvent* joy_detach_event;
2843 KernelHelpers::ServiceContext service_context;
2844 std::shared_ptr<IAppletResource> applet_resource;
2845};
2846
2847void LoopProcess(Core::System& system) { 17void LoopProcess(Core::System& system) {
2848 auto server_manager = std::make_unique<ServerManager>(system); 18 auto server_manager = std::make_unique<ServerManager>(system);
2849 std::shared_ptr<IAppletResource> applet_resource; 19 std::shared_ptr<ResourceManager> resouce_manager = std::make_shared<ResourceManager>(system);
20 std::shared_ptr<HidFirmwareSettings> firmware_settings =
21 std::make_shared<HidFirmwareSettings>();
22
23 server_manager->RegisterNamedService(
24 "hid", std::make_shared<IHidServer>(system, resouce_manager, firmware_settings));
25 server_manager->RegisterNamedService(
26 "hid:dbg", std::make_shared<IHidDebugServer>(system, resouce_manager));
27 server_manager->RegisterNamedService(
28 "hid:sys", std::make_shared<IHidSystemServer>(system, resouce_manager));
2850 29
2851 server_manager->RegisterNamedService("hid", std::make_shared<Hid>(system, applet_resource));
2852 server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system)); 30 server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system));
2853 server_manager->RegisterNamedService("hid:dbg", std::make_shared<HidDbg>(system));
2854 server_manager->RegisterNamedService("hid:sys",
2855 std::make_shared<HidSys>(system, applet_resource));
2856 31
2857 server_manager->RegisterNamedService("irs", std::make_shared<Service::IRS::IRS>(system)); 32 server_manager->RegisterNamedService("irs", std::make_shared<IRS::IRS>(system));
2858 server_manager->RegisterNamedService("irs:sys", 33 server_manager->RegisterNamedService("irs:sys", std::make_shared<IRS::IRS_SYS>(system));
2859 std::make_shared<Service::IRS::IRS_SYS>(system));
2860 34
2861 server_manager->RegisterNamedService("xcd:sys", std::make_shared<XCD_SYS>(system)); 35 server_manager->RegisterNamedService("xcd:sys", std::make_shared<XCD_SYS>(system));
36
2862 system.RunServer(std::move(server_manager)); 37 system.RunServer(std::move(server_manager));
2863} 38}
2864 39
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 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <chrono> 6namespace Core {
7 7class System;
8#include "core/hle/service/hid/controllers/controller_base.h"
9#include "core/hle/service/kernel_helpers.h"
10#include "core/hle/service/service.h"
11
12namespace Core::Timing {
13struct EventType;
14}
15
16namespace Service::SM {
17class ServiceManager;
18} 8}
19 9
20namespace Service::HID { 10namespace Service::HID {
21 11
22enum class HidController : std::size_t {
23 DebugPad,
24 Touchscreen,
25 Mouse,
26 Keyboard,
27 XPad,
28 HomeButton,
29 SleepButton,
30 CaptureButton,
31 InputDetector,
32 UniquePad,
33 NPad,
34 Gesture,
35 ConsoleSixAxisSensor,
36 DebugMouse,
37 Palma,
38
39 MaxControllers,
40};
41
42class IAppletResource final : public ServiceFramework<IAppletResource> {
43public:
44 explicit IAppletResource(Core::System& system_,
45 KernelHelpers::ServiceContext& service_context_);
46 ~IAppletResource() override;
47
48 void ActivateController(HidController controller);
49 void DeactivateController(HidController controller);
50
51 template <typename T>
52 T& GetController(HidController controller) {
53 return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
54 }
55
56 template <typename T>
57 const T& GetController(HidController controller) const {
58 return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
59 }
60
61private:
62 template <typename T>
63 void MakeController(HidController controller, u8* shared_memory) {
64 if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
65 controllers[static_cast<std::size_t>(controller)] =
66 std::make_unique<T>(system, shared_memory);
67 } else {
68 controllers[static_cast<std::size_t>(controller)] =
69 std::make_unique<T>(system.HIDCore(), shared_memory);
70 }
71 }
72
73 template <typename T>
74 void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
75 controllers[static_cast<std::size_t>(controller)] =
76 std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
77 }
78
79 void GetSharedMemoryHandle(HLERequestContext& ctx);
80 void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
81 void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
82 void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
83 void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
84
85 KernelHelpers::ServiceContext& service_context;
86
87 std::shared_ptr<Core::Timing::EventType> npad_update_event;
88 std::shared_ptr<Core::Timing::EventType> default_update_event;
89 std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
90 std::shared_ptr<Core::Timing::EventType> motion_update_event;
91
92 std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
93 controllers{};
94};
95
96class Hid final : public ServiceFramework<Hid> {
97public:
98 explicit Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_);
99 ~Hid() override;
100
101 std::shared_ptr<IAppletResource> GetAppletResource();
102
103private:
104 void CreateAppletResource(HLERequestContext& ctx);
105 void ActivateDebugPad(HLERequestContext& ctx);
106 void ActivateTouchScreen(HLERequestContext& ctx);
107 void ActivateMouse(HLERequestContext& ctx);
108 void ActivateKeyboard(HLERequestContext& ctx);
109 void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
110 void ActivateXpad(HLERequestContext& ctx);
111 void GetXpadIDs(HLERequestContext& ctx);
112 void ActivateSixAxisSensor(HLERequestContext& ctx);
113 void DeactivateSixAxisSensor(HLERequestContext& ctx);
114 void StartSixAxisSensor(HLERequestContext& ctx);
115 void StopSixAxisSensor(HLERequestContext& ctx);
116 void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
117 void EnableSixAxisSensorFusion(HLERequestContext& ctx);
118 void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
119 void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
120 void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
121 void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
122 void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
123 void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
124 void IsSixAxisSensorAtRest(HLERequestContext& ctx);
125 void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
126 void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
127 void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
128 void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
129 void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
130 void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
131 void ActivateGesture(HLERequestContext& ctx);
132 void SetSupportedNpadStyleSet(HLERequestContext& ctx);
133 void GetSupportedNpadStyleSet(HLERequestContext& ctx);
134 void SetSupportedNpadIdType(HLERequestContext& ctx);
135 void ActivateNpad(HLERequestContext& ctx);
136 void DeactivateNpad(HLERequestContext& ctx);
137 void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
138 void DisconnectNpad(HLERequestContext& ctx);
139 void GetPlayerLedPattern(HLERequestContext& ctx);
140 void ActivateNpadWithRevision(HLERequestContext& ctx);
141 void SetNpadJoyHoldType(HLERequestContext& ctx);
142 void GetNpadJoyHoldType(HLERequestContext& ctx);
143 void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
144 void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
145 void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
146 void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
147 void StartLrAssignmentMode(HLERequestContext& ctx);
148 void StopLrAssignmentMode(HLERequestContext& ctx);
149 void SetNpadHandheldActivationMode(HLERequestContext& ctx);
150 void GetNpadHandheldActivationMode(HLERequestContext& ctx);
151 void SwapNpadAssignment(HLERequestContext& ctx);
152 void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
153 void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
154 void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
155 void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
156 void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
157 void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
158 void GetVibrationDeviceInfo(HLERequestContext& ctx);
159 void SendVibrationValue(HLERequestContext& ctx);
160 void GetActualVibrationValue(HLERequestContext& ctx);
161 void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
162 void PermitVibration(HLERequestContext& ctx);
163 void IsVibrationPermitted(HLERequestContext& ctx);
164 void SendVibrationValues(HLERequestContext& ctx);
165 void SendVibrationGcErmCommand(HLERequestContext& ctx);
166 void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
167 void BeginPermitVibrationSession(HLERequestContext& ctx);
168 void EndPermitVibrationSession(HLERequestContext& ctx);
169 void IsVibrationDeviceMounted(HLERequestContext& ctx);
170 void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
171 void StartConsoleSixAxisSensor(HLERequestContext& ctx);
172 void StopConsoleSixAxisSensor(HLERequestContext& ctx);
173 void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
174 void StartSevenSixAxisSensor(HLERequestContext& ctx);
175 void StopSevenSixAxisSensor(HLERequestContext& ctx);
176 void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
177 void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
178 void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
179 void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
180 void GetPalmaConnectionHandle(HLERequestContext& ctx);
181 void InitializePalma(HLERequestContext& ctx);
182 void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
183 void GetPalmaOperationInfo(HLERequestContext& ctx);
184 void PlayPalmaActivity(HLERequestContext& ctx);
185 void SetPalmaFrModeType(HLERequestContext& ctx);
186 void ReadPalmaStep(HLERequestContext& ctx);
187 void EnablePalmaStep(HLERequestContext& ctx);
188 void ResetPalmaStep(HLERequestContext& ctx);
189 void ReadPalmaApplicationSection(HLERequestContext& ctx);
190 void WritePalmaApplicationSection(HLERequestContext& ctx);
191 void ReadPalmaUniqueCode(HLERequestContext& ctx);
192 void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
193 void WritePalmaActivityEntry(HLERequestContext& ctx);
194 void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
195 void WritePalmaWaveEntry(HLERequestContext& ctx);
196 void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
197 void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
198 void SuspendPalmaFeature(HLERequestContext& ctx);
199 void GetPalmaOperationResult(HLERequestContext& ctx);
200 void ReadPalmaPlayLog(HLERequestContext& ctx);
201 void ResetPalmaPlayLog(HLERequestContext& ctx);
202 void SetIsPalmaAllConnectable(HLERequestContext& ctx);
203 void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
204 void PairPalma(HLERequestContext& ctx);
205 void SetPalmaBoostMode(HLERequestContext& ctx);
206 void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
207 void EnablePalmaBoostMode(HLERequestContext& ctx);
208 void GetPalmaBluetoothAddress(HLERequestContext& ctx);
209 void SetDisallowedPalmaConnection(HLERequestContext& ctx);
210 void SetNpadCommunicationMode(HLERequestContext& ctx);
211 void GetNpadCommunicationMode(HLERequestContext& ctx);
212 void SetTouchScreenConfiguration(HLERequestContext& ctx);
213 void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
214
215 std::shared_ptr<IAppletResource> applet_resource;
216
217 KernelHelpers::ServiceContext service_context;
218};
219
220void LoopProcess(Core::System& system); 12void LoopProcess(Core::System& system);
221 13
222} // namespace Service::HID 14} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/hid/hid_debug_server.h"
5#include "core/hle/service/hid/resource_manager.h"
6#include "core/hle/service/ipc_helpers.h"
7
8namespace Service::HID {
9
10IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
11 : ServiceFramework{system_, "hid:dbg"}, resource_manager{resource} {
12 // clang-format off
13 static const FunctionInfo functions[] = {
14 {0, nullptr, "DeactivateDebugPad"},
15 {1, nullptr, "SetDebugPadAutoPilotState"},
16 {2, nullptr, "UnsetDebugPadAutoPilotState"},
17 {10, nullptr, "DeactivateTouchScreen"},
18 {11, nullptr, "SetTouchScreenAutoPilotState"},
19 {12, nullptr, "UnsetTouchScreenAutoPilotState"},
20 {13, nullptr, "GetTouchScreenConfiguration"},
21 {14, nullptr, "ProcessTouchScreenAutoTune"},
22 {15, nullptr, "ForceStopTouchScreenManagement"},
23 {16, nullptr, "ForceRestartTouchScreenManagement"},
24 {17, nullptr, "IsTouchScreenManaged"},
25 {20, nullptr, "DeactivateMouse"},
26 {21, nullptr, "SetMouseAutoPilotState"},
27 {22, nullptr, "UnsetMouseAutoPilotState"},
28 {25, nullptr, "SetDebugMouseAutoPilotState"},
29 {26, nullptr, "UnsetDebugMouseAutoPilotState"},
30 {30, nullptr, "DeactivateKeyboard"},
31 {31, nullptr, "SetKeyboardAutoPilotState"},
32 {32, nullptr, "UnsetKeyboardAutoPilotState"},
33 {50, nullptr, "DeactivateXpad"},
34 {51, nullptr, "SetXpadAutoPilotState"},
35 {52, nullptr, "UnsetXpadAutoPilotState"},
36 {53, nullptr, "DeactivateJoyXpad"},
37 {60, nullptr, "ClearNpadSystemCommonPolicy"},
38 {61, nullptr, "DeactivateNpad"},
39 {62, nullptr, "ForceDisconnectNpad"},
40 {91, nullptr, "DeactivateGesture"},
41 {110, nullptr, "DeactivateHomeButton"},
42 {111, nullptr, "SetHomeButtonAutoPilotState"},
43 {112, nullptr, "UnsetHomeButtonAutoPilotState"},
44 {120, nullptr, "DeactivateSleepButton"},
45 {121, nullptr, "SetSleepButtonAutoPilotState"},
46 {122, nullptr, "UnsetSleepButtonAutoPilotState"},
47 {123, nullptr, "DeactivateInputDetector"},
48 {130, nullptr, "DeactivateCaptureButton"},
49 {131, nullptr, "SetCaptureButtonAutoPilotState"},
50 {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
51 {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
52 {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
53 {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
54 {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
55 {140, nullptr, "DeactivateConsoleSixAxisSensor"},
56 {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
57 {142, nullptr, "DeactivateSevenSixAxisSensor"},
58 {143, nullptr, "GetConsoleSixAxisSensorCountStates"},
59 {144, nullptr, "GetAccelerometerFsr"},
60 {145, nullptr, "SetAccelerometerFsr"},
61 {146, nullptr, "GetAccelerometerOdr"},
62 {147, nullptr, "SetAccelerometerOdr"},
63 {148, nullptr, "GetGyroscopeFsr"},
64 {149, nullptr, "SetGyroscopeFsr"},
65 {150, nullptr, "GetGyroscopeOdr"},
66 {151, nullptr, "SetGyroscopeOdr"},
67 {152, nullptr, "GetWhoAmI"},
68 {201, nullptr, "ActivateFirmwareUpdate"},
69 {202, nullptr, "DeactivateFirmwareUpdate"},
70 {203, nullptr, "StartFirmwareUpdate"},
71 {204, nullptr, "GetFirmwareUpdateStage"},
72 {205, nullptr, "GetFirmwareVersion"},
73 {206, nullptr, "GetDestinationFirmwareVersion"},
74 {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
75 {208, nullptr, "StartFirmwareUpdateForRevert"},
76 {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
77 {210, nullptr, "IsFirmwareUpdatingDevice"},
78 {211, nullptr, "StartFirmwareUpdateIndividual"},
79 {215, nullptr, "SetUsbFirmwareForceUpdateEnabled"},
80 {216, nullptr, "SetAllKuinaDevicesToFirmwareUpdateMode"},
81 {221, nullptr, "UpdateControllerColor"},
82 {222, nullptr, "ConnectUsbPadsAsync"},
83 {223, nullptr, "DisconnectUsbPadsAsync"},
84 {224, nullptr, "UpdateDesignInfo"},
85 {225, nullptr, "GetUniquePadDriverState"},
86 {226, nullptr, "GetSixAxisSensorDriverStates"},
87 {227, nullptr, "GetRxPacketHistory"},
88 {228, nullptr, "AcquireOperationEventHandle"},
89 {229, nullptr, "ReadSerialFlash"},
90 {230, nullptr, "WriteSerialFlash"},
91 {231, nullptr, "GetOperationResult"},
92 {232, nullptr, "EnableShipmentMode"},
93 {233, nullptr, "ClearPairingInfo"},
94 {234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
95 {235, nullptr, "EnableAnalogStickPower"},
96 {236, nullptr, "RequestKuinaUartClockCal"},
97 {237, nullptr, "GetKuinaUartClockCal"},
98 {238, nullptr, "SetKuinaUartClockTrim"},
99 {239, nullptr, "KuinaLoopbackTest"},
100 {240, nullptr, "RequestBatteryVoltage"},
101 {241, nullptr, "GetBatteryVoltage"},
102 {242, nullptr, "GetUniquePadPowerInfo"},
103 {243, nullptr, "RebootUniquePad"},
104 {244, nullptr, "RequestKuinaFirmwareVersion"},
105 {245, nullptr, "GetKuinaFirmwareVersion"},
106 {246, nullptr, "GetVidPid"},
107 {247, nullptr, "GetAnalogStickCalibrationValue"},
108 {248, nullptr, "GetUniquePadIdsFull"},
109 {249, nullptr, "ConnectUniquePad"},
110 {250, nullptr, "IsVirtual"},
111 {251, nullptr, "GetAnalogStickModuleParam"},
112 {301, nullptr, "GetAbstractedPadHandles"},
113 {302, nullptr, "GetAbstractedPadState"},
114 {303, nullptr, "GetAbstractedPadsState"},
115 {321, nullptr, "SetAutoPilotVirtualPadState"},
116 {322, nullptr, "UnsetAutoPilotVirtualPadState"},
117 {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
118 {324, nullptr, "AttachHdlsWorkBuffer"},
119 {325, nullptr, "ReleaseHdlsWorkBuffer"},
120 {326, nullptr, "DumpHdlsNpadAssignmentState"},
121 {327, nullptr, "DumpHdlsStates"},
122 {328, nullptr, "ApplyHdlsNpadAssignmentState"},
123 {329, nullptr, "ApplyHdlsStateList"},
124 {330, nullptr, "AttachHdlsVirtualDevice"},
125 {331, nullptr, "DetachHdlsVirtualDevice"},
126 {332, nullptr, "SetHdlsState"},
127 {350, nullptr, "AddRegisteredDevice"},
128 {400, nullptr, "DisableExternalMcuOnNxDevice"},
129 {401, nullptr, "DisableRailDeviceFiltering"},
130 {402, nullptr, "EnableWiredPairing"},
131 {403, nullptr, "EnableShipmentModeAutoClear"},
132 {404, nullptr, "SetRailEnabled"},
133 {500, nullptr, "SetFactoryInt"},
134 {501, nullptr, "IsFactoryBootEnabled"},
135 {550, nullptr, "SetAnalogStickModelDataTemporarily"},
136 {551, nullptr, "GetAnalogStickModelData"},
137 {552, nullptr, "ResetAnalogStickModelData"},
138 {600, nullptr, "ConvertPadState"},
139 {650, nullptr, "AddButtonPlayData"},
140 {651, nullptr, "StartButtonPlayData"},
141 {652, nullptr, "StopButtonPlayData"},
142 {2000, nullptr, "DeactivateDigitizer"},
143 {2001, nullptr, "SetDigitizerAutoPilotState"},
144 {2002, nullptr, "UnsetDigitizerAutoPilotState"},
145 {2002, nullptr, "ReloadFirmwareDebugSettings"},
146 };
147 // clang-format on
148
149 RegisterHandlers(functions);
150}
151
152IHidDebugServer::~IHidDebugServer() = default;
153
154std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() {
155 resource_manager->Initialize();
156 return resource_manager;
157}
158
159} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Core {
9class System;
10}
11
12namespace Service::HID {
13class ResourceManager;
14
15class IHidDebugServer final : public ServiceFramework<IHidDebugServer> {
16public:
17 explicit IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
18 ~IHidDebugServer() override;
19
20private:
21 std::shared_ptr<ResourceManager> GetResourceManager();
22
23 std::shared_ptr<ResourceManager> resource_manager;
24};
25
26} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/hid/hid_firmware_settings.h"
5
6namespace Service::HID {
7
8HidFirmwareSettings::HidFirmwareSettings() {
9 LoadSettings(true);
10}
11
12void HidFirmwareSettings::Reload() {
13 LoadSettings(true);
14}
15
16void HidFirmwareSettings::LoadSettings(bool reload_config) {
17 if (is_initalized && !reload_config) {
18 return;
19 }
20
21 // TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values
22
23 is_debug_pad_enabled = true;
24 is_device_managed = true;
25 is_touch_i2c_managed = is_device_managed;
26 is_future_devices_emulated = false;
27 is_mcu_hardware_error_emulated = false;
28 is_rail_enabled = true;
29 is_firmware_update_failure_emulated = false;
30 is_firmware_update_failure = {};
31 is_ble_disabled = false;
32 is_dscale_disabled = false;
33 is_handheld_forced = true;
34 features_per_id_disabled = {};
35 is_touch_firmware_auto_update_disabled = false;
36 is_initalized = true;
37}
38
39bool HidFirmwareSettings::IsDebugPadEnabled() {
40 LoadSettings(false);
41 return is_debug_pad_enabled;
42}
43
44bool HidFirmwareSettings::IsDeviceManaged() {
45 LoadSettings(false);
46 return is_device_managed;
47}
48
49bool HidFirmwareSettings::IsEmulateFutureDevice() {
50 LoadSettings(false);
51 return is_future_devices_emulated;
52}
53
54bool HidFirmwareSettings::IsTouchI2cManaged() {
55 LoadSettings(false);
56 return is_touch_i2c_managed;
57}
58
59bool HidFirmwareSettings::IsHandheldForced() {
60 LoadSettings(false);
61 return is_handheld_forced;
62}
63
64bool HidFirmwareSettings::IsRailEnabled() {
65 LoadSettings(false);
66 return is_rail_enabled;
67}
68
69bool HidFirmwareSettings::IsHardwareErrorEmulated() {
70 LoadSettings(false);
71 return is_mcu_hardware_error_emulated;
72}
73
74bool HidFirmwareSettings::IsBleDisabled() {
75 LoadSettings(false);
76 return is_ble_disabled;
77}
78
79bool HidFirmwareSettings::IsDscaleDisabled() {
80 LoadSettings(false);
81 return is_dscale_disabled;
82}
83
84bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() {
85 LoadSettings(false);
86 return is_touch_firmware_auto_update_disabled;
87}
88
89HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() {
90 LoadSettings(false);
91 return is_firmware_update_failure;
92}
93
94HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() {
95 LoadSettings(false);
96 return features_per_id_disabled;
97}
98
99} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/common_types.h"
7
8namespace Service::HID {
9
10/// Loads firmware config from nn::settings::fwdbg
11class HidFirmwareSettings {
12public:
13 using FirmwareSetting = std::array<u8, 4>;
14 using FeaturesPerId = std::array<bool, 0xA8>;
15
16 HidFirmwareSettings();
17
18 void Reload();
19 void LoadSettings(bool reload_config);
20
21 bool IsDebugPadEnabled();
22 bool IsDeviceManaged();
23 bool IsEmulateFutureDevice();
24 bool IsTouchI2cManaged();
25 bool IsHandheldForced();
26 bool IsRailEnabled();
27 bool IsHardwareErrorEmulated();
28 bool IsBleDisabled();
29 bool IsDscaleDisabled();
30 bool IsTouchAutoUpdateDisabled();
31
32 FirmwareSetting GetFirmwareUpdateFailure();
33 FeaturesPerId FeaturesDisabledPerId();
34
35private:
36 bool is_initalized{};
37
38 // Debug settings
39 bool is_debug_pad_enabled{};
40 bool is_device_managed{};
41 bool is_touch_i2c_managed{};
42 bool is_future_devices_emulated{};
43 bool is_mcu_hardware_error_emulated{};
44 bool is_rail_enabled{};
45 bool is_firmware_update_failure_emulated{};
46 bool is_ble_disabled{};
47 bool is_dscale_disabled{};
48 bool is_handheld_forced{};
49 bool is_touch_firmware_auto_update_disabled{};
50 FirmwareSetting is_firmware_update_failure{};
51 FeaturesPerId features_per_id_disabled{};
52};
53
54} // 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..583142e35
--- /dev/null
+++ b/src/core/hle/service/hid/hid_server.cpp
@@ -0,0 +1,2371 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include <array>
5#include "common/common_types.h"
6#include "common/logging/log.h"
7#include "common/settings.h"
8#include "core/hid/hid_core.h"
9#include "core/hle/kernel/k_shared_memory.h"
10#include "core/hle/kernel/k_transfer_memory.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/service/hid/errors.h"
13#include "core/hle/service/hid/hid_firmware_settings.h"
14#include "core/hle/service/hid/hid_server.h"
15#include "core/hle/service/hid/hid_util.h"
16#include "core/hle/service/hid/resource_manager.h"
17#include "core/hle/service/ipc_helpers.h"
18#include "core/memory.h"
19
20#include "core/hle/service/hid/controllers/console_six_axis.h"
21#include "core/hle/service/hid/controllers/controller_base.h"
22#include "core/hle/service/hid/controllers/debug_pad.h"
23#include "core/hle/service/hid/controllers/gesture.h"
24#include "core/hle/service/hid/controllers/keyboard.h"
25#include "core/hle/service/hid/controllers/mouse.h"
26#include "core/hle/service/hid/controllers/npad.h"
27#include "core/hle/service/hid/controllers/palma.h"
28#include "core/hle/service/hid/controllers/seven_six_axis.h"
29#include "core/hle/service/hid/controllers/six_axis.h"
30#include "core/hle/service/hid/controllers/touchscreen.h"
31
32namespace Service::HID {
33
34class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
35public:
36 explicit IActiveVibrationDeviceList(Core::System& system_,
37 std::shared_ptr<ResourceManager> resource)
38 : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) {
39 // clang-format off
40 static const FunctionInfo functions[] = {
41 {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"},
42 };
43 // clang-format on
44
45 RegisterHandlers(functions);
46 }
47
48private:
49 void InitializeVibrationDevice(HLERequestContext& ctx) {
50 IPC::RequestParser rp{ctx};
51 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
52
53 if (resource_manager != nullptr) {
54 resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle);
55 }
56
57 LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}",
58 vibration_device_handle.npad_type, vibration_device_handle.npad_id,
59 vibration_device_handle.device_index);
60
61 IPC::ResponseBuilder rb{ctx, 2};
62 rb.Push(ResultSuccess);
63 }
64
65 std::shared_ptr<ResourceManager> resource_manager;
66};
67
68IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource,
69 std::shared_ptr<HidFirmwareSettings> settings)
70 : ServiceFramework{system_, "hid"}, resource_manager{resource}, firmware_settings{settings} {
71 // clang-format off
72 static const FunctionInfo functions[] = {
73 {0, &IHidServer::CreateAppletResource, "CreateAppletResource"},
74 {1, &IHidServer::ActivateDebugPad, "ActivateDebugPad"},
75 {11, &IHidServer::ActivateTouchScreen, "ActivateTouchScreen"},
76 {21, &IHidServer::ActivateMouse, "ActivateMouse"},
77 {26, nullptr, "ActivateDebugMouse"},
78 {31, &IHidServer::ActivateKeyboard, "ActivateKeyboard"},
79 {32, &IHidServer::SendKeyboardLockKeyEvent, "SendKeyboardLockKeyEvent"},
80 {40, &IHidServer::AcquireXpadIdEventHandle, "AcquireXpadIdEventHandle"},
81 {41, &IHidServer::ReleaseXpadIdEventHandle, "ReleaseXpadIdEventHandle"},
82 {51, &IHidServer::ActivateXpad, "ActivateXpad"},
83 {55, &IHidServer::GetXpadIds, "GetXpadIds"},
84 {56, &IHidServer::ActivateJoyXpad, "ActivateJoyXpad"},
85 {58, &IHidServer::GetJoyXpadLifoHandle, "GetJoyXpadLifoHandle"},
86 {59, &IHidServer::GetJoyXpadIds, "GetJoyXpadIds"},
87 {60, &IHidServer::ActivateSixAxisSensor, "ActivateSixAxisSensor"},
88 {61, &IHidServer::DeactivateSixAxisSensor, "DeactivateSixAxisSensor"},
89 {62, &IHidServer::GetSixAxisSensorLifoHandle, "GetSixAxisSensorLifoHandle"},
90 {63, &IHidServer::ActivateJoySixAxisSensor, "ActivateJoySixAxisSensor"},
91 {64, &IHidServer::DeactivateJoySixAxisSensor, "DeactivateJoySixAxisSensor"},
92 {65, &IHidServer::GetJoySixAxisSensorLifoHandle, "GetJoySixAxisSensorLifoHandle"},
93 {66, &IHidServer::StartSixAxisSensor, "StartSixAxisSensor"},
94 {67, &IHidServer::StopSixAxisSensor, "StopSixAxisSensor"},
95 {68, &IHidServer::IsSixAxisSensorFusionEnabled, "IsSixAxisSensorFusionEnabled"},
96 {69, &IHidServer::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
97 {70, &IHidServer::SetSixAxisSensorFusionParameters, "SetSixAxisSensorFusionParameters"},
98 {71, &IHidServer::GetSixAxisSensorFusionParameters, "GetSixAxisSensorFusionParameters"},
99 {72, &IHidServer::ResetSixAxisSensorFusionParameters, "ResetSixAxisSensorFusionParameters"},
100 {73, nullptr, "SetAccelerometerParameters"},
101 {74, nullptr, "GetAccelerometerParameters"},
102 {75, nullptr, "ResetAccelerometerParameters"},
103 {76, nullptr, "SetAccelerometerPlayMode"},
104 {77, nullptr, "GetAccelerometerPlayMode"},
105 {78, nullptr, "ResetAccelerometerPlayMode"},
106 {79, &IHidServer::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
107 {80, &IHidServer::GetGyroscopeZeroDriftMode, "GetGyroscopeZeroDriftMode"},
108 {81, &IHidServer::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
109 {82, &IHidServer::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
110 {83, &IHidServer::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
111 {84, &IHidServer::EnableSixAxisSensorUnalteredPassthrough, "EnableSixAxisSensorUnalteredPassthrough"},
112 {85, &IHidServer::IsSixAxisSensorUnalteredPassthroughEnabled, "IsSixAxisSensorUnalteredPassthroughEnabled"},
113 {86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
114 {87, &IHidServer::LoadSixAxisSensorCalibrationParameter, "LoadSixAxisSensorCalibrationParameter"},
115 {88, &IHidServer::GetSixAxisSensorIcInformation, "GetSixAxisSensorIcInformation"},
116 {89, &IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
117 {91, &IHidServer::ActivateGesture, "ActivateGesture"},
118 {100, &IHidServer::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
119 {101, &IHidServer::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
120 {102, &IHidServer::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
121 {103, &IHidServer::ActivateNpad, "ActivateNpad"},
122 {104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
123 {106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
124 {107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
125 {108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"},
126 {109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
127 {120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
128 {121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
129 {122, &IHidServer::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
130 {123, &IHidServer::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"},
131 {124, &IHidServer::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
132 {125, &IHidServer::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
133 {126, &IHidServer::StartLrAssignmentMode, "StartLrAssignmentMode"},
134 {127, &IHidServer::StopLrAssignmentMode, "StopLrAssignmentMode"},
135 {128, &IHidServer::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
136 {129, &IHidServer::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
137 {130, &IHidServer::SwapNpadAssignment, "SwapNpadAssignment"},
138 {131, &IHidServer::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
139 {132, &IHidServer::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
140 {133, &IHidServer::SetNpadJoyAssignmentModeSingleWithDestination, "SetNpadJoyAssignmentModeSingleWithDestination"},
141 {134, &IHidServer::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
142 {135, &IHidServer::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"},
143 {136, &IHidServer::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"},
144 {200, &IHidServer::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
145 {201, &IHidServer::SendVibrationValue, "SendVibrationValue"},
146 {202, &IHidServer::GetActualVibrationValue, "GetActualVibrationValue"},
147 {203, &IHidServer::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
148 {204, &IHidServer::PermitVibration, "PermitVibration"},
149 {205, &IHidServer::IsVibrationPermitted, "IsVibrationPermitted"},
150 {206, &IHidServer::SendVibrationValues, "SendVibrationValues"},
151 {207, &IHidServer::SendVibrationGcErmCommand, "SendVibrationGcErmCommand"},
152 {208, &IHidServer::GetActualVibrationGcErmCommand, "GetActualVibrationGcErmCommand"},
153 {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
154 {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"},
155 {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
156 {212, nullptr, "SendVibrationValueInBool"},
157 {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
158 {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
159 {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"},
160 {303, &IHidServer::ActivateSevenSixAxisSensor, "ActivateSevenSixAxisSensor"},
161 {304, &IHidServer::StartSevenSixAxisSensor, "StartSevenSixAxisSensor"},
162 {305, &IHidServer::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"},
163 {306, &IHidServer::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
164 {307, &IHidServer::FinalizeSevenSixAxisSensor, "FinalizeSevenSixAxisSensor"},
165 {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
166 {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
167 {310, &IHidServer::ResetSevenSixAxisSensorTimestamp, "ResetSevenSixAxisSensorTimestamp"},
168 {400, &IHidServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
169 {401, nullptr, "EnableUsbFullKeyController"},
170 {402, nullptr, "IsUsbFullKeyControllerConnected"},
171 {403, nullptr, "HasBattery"},
172 {404, nullptr, "HasLeftRightBattery"},
173 {405, nullptr, "GetNpadInterfaceType"},
174 {406, nullptr, "GetNpadLeftRightInterfaceType"},
175 {407, nullptr, "GetNpadOfHighestBatteryLevel"},
176 {408, nullptr, "GetNpadOfHighestBatteryLevelForJoyRight"},
177 {500, &IHidServer::GetPalmaConnectionHandle, "GetPalmaConnectionHandle"},
178 {501, &IHidServer::InitializePalma, "InitializePalma"},
179 {502, &IHidServer::AcquirePalmaOperationCompleteEvent, "AcquirePalmaOperationCompleteEvent"},
180 {503, &IHidServer::GetPalmaOperationInfo, "GetPalmaOperationInfo"},
181 {504, &IHidServer::PlayPalmaActivity, "PlayPalmaActivity"},
182 {505, &IHidServer::SetPalmaFrModeType, "SetPalmaFrModeType"},
183 {506, &IHidServer::ReadPalmaStep, "ReadPalmaStep"},
184 {507, &IHidServer::EnablePalmaStep, "EnablePalmaStep"},
185 {508, &IHidServer::ResetPalmaStep, "ResetPalmaStep"},
186 {509, &IHidServer::ReadPalmaApplicationSection, "ReadPalmaApplicationSection"},
187 {510, &IHidServer::WritePalmaApplicationSection, "WritePalmaApplicationSection"},
188 {511, &IHidServer::ReadPalmaUniqueCode, "ReadPalmaUniqueCode"},
189 {512, &IHidServer::SetPalmaUniqueCodeInvalid, "SetPalmaUniqueCodeInvalid"},
190 {513, &IHidServer::WritePalmaActivityEntry, "WritePalmaActivityEntry"},
191 {514, &IHidServer::WritePalmaRgbLedPatternEntry, "WritePalmaRgbLedPatternEntry"},
192 {515, &IHidServer::WritePalmaWaveEntry, "WritePalmaWaveEntry"},
193 {516, &IHidServer::SetPalmaDataBaseIdentificationVersion, "SetPalmaDataBaseIdentificationVersion"},
194 {517, &IHidServer::GetPalmaDataBaseIdentificationVersion, "GetPalmaDataBaseIdentificationVersion"},
195 {518, &IHidServer::SuspendPalmaFeature, "SuspendPalmaFeature"},
196 {519, &IHidServer::GetPalmaOperationResult, "GetPalmaOperationResult"},
197 {520, &IHidServer::ReadPalmaPlayLog, "ReadPalmaPlayLog"},
198 {521, &IHidServer::ResetPalmaPlayLog, "ResetPalmaPlayLog"},
199 {522, &IHidServer::SetIsPalmaAllConnectable, "SetIsPalmaAllConnectable"},
200 {523, &IHidServer::SetIsPalmaPairedConnectable, "SetIsPalmaPairedConnectable"},
201 {524, &IHidServer::PairPalma, "PairPalma"},
202 {525, &IHidServer::SetPalmaBoostMode, "SetPalmaBoostMode"},
203 {526, &IHidServer::CancelWritePalmaWaveEntry, "CancelWritePalmaWaveEntry"},
204 {527, &IHidServer::EnablePalmaBoostMode, "EnablePalmaBoostMode"},
205 {528, &IHidServer::GetPalmaBluetoothAddress, "GetPalmaBluetoothAddress"},
206 {529, &IHidServer::SetDisallowedPalmaConnection, "SetDisallowedPalmaConnection"},
207 {1000, &IHidServer::SetNpadCommunicationMode, "SetNpadCommunicationMode"},
208 {1001, &IHidServer::GetNpadCommunicationMode, "GetNpadCommunicationMode"},
209 {1002, &IHidServer::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"},
210 {1003, &IHidServer::IsFirmwareUpdateNeededForNotification, "IsFirmwareUpdateNeededForNotification"},
211 {2000, nullptr, "ActivateDigitizer"},
212 };
213 // clang-format on
214
215 RegisterHandlers(functions);
216}
217
218IHidServer::~IHidServer() = default;
219
220void IHidServer::CreateAppletResource(HLERequestContext& ctx) {
221 IPC::RequestParser rp{ctx};
222 const auto applet_resource_user_id{rp.Pop<u64>()};
223
224 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
225
226 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
227 rb.Push(ResultSuccess);
228 rb.PushIpcInterface<IAppletResource>(system, resource_manager);
229}
230
231void IHidServer::ActivateDebugPad(HLERequestContext& ctx) {
232 IPC::RequestParser rp{ctx};
233 const auto applet_resource_user_id{rp.Pop<u64>()};
234
235 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
236
237 Result result = ResultSuccess;
238 auto debug_pad = GetResourceManager()->GetDebugPad();
239
240 if (!firmware_settings->IsDeviceManaged()) {
241 result = debug_pad->Activate();
242 }
243
244 if (result.IsSuccess()) {
245 result = debug_pad->Activate(applet_resource_user_id);
246 }
247
248 IPC::ResponseBuilder rb{ctx, 2};
249 rb.Push(result);
250}
251
252void IHidServer::ActivateTouchScreen(HLERequestContext& ctx) {
253 IPC::RequestParser rp{ctx};
254 const auto applet_resource_user_id{rp.Pop<u64>()};
255
256 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
257
258 Result result = ResultSuccess;
259 auto touch_screen = GetResourceManager()->GetTouchScreen();
260
261 if (!firmware_settings->IsDeviceManaged()) {
262 result = touch_screen->Activate();
263 }
264
265 if (result.IsSuccess()) {
266 result = touch_screen->Activate(applet_resource_user_id);
267 }
268
269 IPC::ResponseBuilder rb{ctx, 2};
270 rb.Push(result);
271}
272
273void IHidServer::ActivateMouse(HLERequestContext& ctx) {
274 IPC::RequestParser rp{ctx};
275 const auto applet_resource_user_id{rp.Pop<u64>()};
276
277 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
278
279 Result result = ResultSuccess;
280 auto mouse = GetResourceManager()->GetMouse();
281
282 if (!firmware_settings->IsDeviceManaged()) {
283 result = mouse->Activate();
284 }
285
286 if (result.IsSuccess()) {
287 result = mouse->Activate(applet_resource_user_id);
288 }
289
290 IPC::ResponseBuilder rb{ctx, 2};
291 rb.Push(result);
292}
293
294void IHidServer::ActivateKeyboard(HLERequestContext& ctx) {
295 IPC::RequestParser rp{ctx};
296 const auto applet_resource_user_id{rp.Pop<u64>()};
297
298 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
299
300 Result result = ResultSuccess;
301 auto keyboard = GetResourceManager()->GetKeyboard();
302
303 if (!firmware_settings->IsDeviceManaged()) {
304 result = keyboard->Activate();
305 }
306
307 if (result.IsSuccess()) {
308 result = keyboard->Activate(applet_resource_user_id);
309 }
310
311 IPC::ResponseBuilder rb{ctx, 2};
312 rb.Push(result);
313}
314
315void IHidServer::SendKeyboardLockKeyEvent(HLERequestContext& ctx) {
316 IPC::RequestParser rp{ctx};
317 const auto flags{rp.Pop<u32>()};
318
319 LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags);
320
321 IPC::ResponseBuilder rb{ctx, 2};
322 rb.Push(ResultSuccess);
323}
324
325void IHidServer::AcquireXpadIdEventHandle(HLERequestContext& ctx) {
326 IPC::RequestParser rp{ctx};
327 const auto applet_resource_user_id{rp.Pop<u64>()};
328
329 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
330
331 // This function has been stubbed since 10.0.0+
332
333 IPC::ResponseBuilder rb{ctx, 2, 1};
334 rb.Push(ResultSuccess);
335 // Handle returned is null here
336}
337
338void IHidServer::ReleaseXpadIdEventHandle(HLERequestContext& ctx) {
339 IPC::RequestParser rp{ctx};
340 const auto applet_resource_user_id{rp.Pop<u64>()};
341
342 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
343
344 // This function has been stubbed since 10.0.0+
345
346 IPC::ResponseBuilder rb{ctx, 2};
347 rb.Push(ResultSuccess);
348}
349
350void IHidServer::ActivateXpad(HLERequestContext& ctx) {
351 IPC::RequestParser rp{ctx};
352 struct Parameters {
353 u32 basic_xpad_id;
354 INSERT_PADDING_WORDS_NOINIT(1);
355 u64 applet_resource_user_id;
356 };
357 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
358
359 const auto parameters{rp.PopRaw<Parameters>()};
360
361 LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}",
362 parameters.basic_xpad_id, parameters.applet_resource_user_id);
363
364 // This function has been stubbed since 10.0.0+
365
366 IPC::ResponseBuilder rb{ctx, 2};
367 rb.Push(ResultSuccess);
368}
369
370void IHidServer::GetXpadIds(HLERequestContext& ctx) {
371 LOG_DEBUG(Service_HID, "called");
372
373 // This function has been hardcoded since 10.0.0+
374 const std::array<u32, 4> basic_xpad_id{0, 1, 2, 3};
375 ctx.WriteBuffer(basic_xpad_id);
376
377 IPC::ResponseBuilder rb{ctx, 4};
378 rb.Push(ResultSuccess);
379 rb.Push<s64>(basic_xpad_id.size());
380}
381
382void IHidServer::ActivateJoyXpad(HLERequestContext& ctx) {
383 IPC::RequestParser rp{ctx};
384 const auto joy_xpad_id{rp.Pop<u32>()};
385
386 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
387
388 // This function has been stubbed since 10.0.0+
389
390 IPC::ResponseBuilder rb{ctx, 2};
391 rb.Push(ResultSuccess);
392}
393
394void IHidServer::GetJoyXpadLifoHandle(HLERequestContext& ctx) {
395 IPC::RequestParser rp{ctx};
396 const auto joy_xpad_id{rp.Pop<u32>()};
397
398 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
399
400 // This function has been stubbed since 10.0.0+
401
402 IPC::ResponseBuilder rb{ctx, 2, 1};
403 rb.Push(ResultSuccess);
404 // Handle returned is null here
405}
406
407void IHidServer::GetJoyXpadIds(HLERequestContext& ctx) {
408 LOG_DEBUG(Service_HID, "called");
409
410 // This function has been hardcoded since 10.0.0+
411 const s64 basic_xpad_id_count{};
412
413 IPC::ResponseBuilder rb{ctx, 4};
414 rb.Push(ResultSuccess);
415 rb.Push(basic_xpad_id_count);
416}
417
418void IHidServer::ActivateSixAxisSensor(HLERequestContext& ctx) {
419 IPC::RequestParser rp{ctx};
420 const auto joy_xpad_id{rp.Pop<u32>()};
421
422 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
423
424 // This function has been stubbed since 10.0.0+
425
426 IPC::ResponseBuilder rb{ctx, 2};
427 rb.Push(ResultSuccess);
428}
429
430void IHidServer::DeactivateSixAxisSensor(HLERequestContext& ctx) {
431 IPC::RequestParser rp{ctx};
432 const auto joy_xpad_id{rp.Pop<u32>()};
433
434 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
435
436 // This function has been stubbed since 10.0.0+
437
438 IPC::ResponseBuilder rb{ctx, 2, 1};
439 rb.Push(ResultSuccess);
440}
441
442void IHidServer::GetSixAxisSensorLifoHandle(HLERequestContext& ctx) {
443 IPC::RequestParser rp{ctx};
444 const auto joy_xpad_id{rp.Pop<u32>()};
445
446 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
447
448 // This function has been stubbed since 10.0.0+
449
450 IPC::ResponseBuilder rb{ctx, 2};
451 rb.Push(ResultSuccess);
452}
453
454void IHidServer::ActivateJoySixAxisSensor(HLERequestContext& ctx) {
455 IPC::RequestParser rp{ctx};
456 const auto joy_xpad_id{rp.Pop<u32>()};
457
458 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
459
460 // This function has been stubbed since 10.0.0+
461
462 IPC::ResponseBuilder rb{ctx, 2};
463 rb.Push(ResultSuccess);
464}
465
466void IHidServer::DeactivateJoySixAxisSensor(HLERequestContext& ctx) {
467 IPC::RequestParser rp{ctx};
468 const auto joy_xpad_id{rp.Pop<u32>()};
469
470 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
471
472 // This function has been stubbed since 10.0.0+
473
474 IPC::ResponseBuilder rb{ctx, 2};
475 rb.Push(ResultSuccess);
476}
477
478void IHidServer::GetJoySixAxisSensorLifoHandle(HLERequestContext& ctx) {
479 IPC::RequestParser rp{ctx};
480 const auto joy_xpad_id{rp.Pop<u32>()};
481
482 LOG_DEBUG(Service_HID, "called, joy_xpad_id={}", joy_xpad_id);
483
484 // This function has been stubbed since 10.0.0+
485
486 IPC::ResponseBuilder rb{ctx, 2, 1};
487 rb.Push(ResultSuccess);
488 // Handle returned is null here
489}
490
491void IHidServer::StartSixAxisSensor(HLERequestContext& ctx) {
492 IPC::RequestParser rp{ctx};
493 struct Parameters {
494 Core::HID::SixAxisSensorHandle sixaxis_handle;
495 INSERT_PADDING_WORDS_NOINIT(1);
496 u64 applet_resource_user_id;
497 };
498 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
499
500 const auto parameters{rp.PopRaw<Parameters>()};
501
502 auto six_axis = GetResourceManager()->GetSixAxis();
503 const auto result = six_axis->SetSixAxisEnabled(parameters.sixaxis_handle, true);
504
505 LOG_DEBUG(Service_HID,
506 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
507 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
508 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
509
510 IPC::ResponseBuilder rb{ctx, 2};
511 rb.Push(result);
512}
513
514void IHidServer::StopSixAxisSensor(HLERequestContext& ctx) {
515 IPC::RequestParser rp{ctx};
516 struct Parameters {
517 Core::HID::SixAxisSensorHandle sixaxis_handle;
518 INSERT_PADDING_WORDS_NOINIT(1);
519 u64 applet_resource_user_id;
520 };
521 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
522
523 const auto parameters{rp.PopRaw<Parameters>()};
524
525 auto six_axis = GetResourceManager()->GetSixAxis();
526 const auto result = six_axis->SetSixAxisEnabled(parameters.sixaxis_handle, false);
527
528 LOG_DEBUG(Service_HID,
529 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
530 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
531 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
532
533 IPC::ResponseBuilder rb{ctx, 2};
534 rb.Push(result);
535}
536
537void IHidServer::IsSixAxisSensorFusionEnabled(HLERequestContext& ctx) {
538 IPC::RequestParser rp{ctx};
539 struct Parameters {
540 Core::HID::SixAxisSensorHandle sixaxis_handle;
541 INSERT_PADDING_WORDS_NOINIT(1);
542 u64 applet_resource_user_id;
543 };
544 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
545
546 const auto parameters{rp.PopRaw<Parameters>()};
547
548 bool is_enabled{};
549 auto six_axis = GetResourceManager()->GetSixAxis();
550 const auto result =
551 six_axis->IsSixAxisSensorFusionEnabled(parameters.sixaxis_handle, is_enabled);
552
553 LOG_DEBUG(Service_HID,
554 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
555 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
556 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
557
558 IPC::ResponseBuilder rb{ctx, 3};
559 rb.Push(result);
560 rb.Push(is_enabled);
561}
562
563void IHidServer::EnableSixAxisSensorFusion(HLERequestContext& ctx) {
564 IPC::RequestParser rp{ctx};
565 struct Parameters {
566 bool enable_sixaxis_sensor_fusion;
567 INSERT_PADDING_BYTES_NOINIT(3);
568 Core::HID::SixAxisSensorHandle sixaxis_handle;
569 u64 applet_resource_user_id;
570 };
571 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
572
573 const auto parameters{rp.PopRaw<Parameters>()};
574
575 auto six_axis = GetResourceManager()->GetSixAxis();
576 const auto result = six_axis->SetSixAxisFusionEnabled(parameters.sixaxis_handle,
577 parameters.enable_sixaxis_sensor_fusion);
578
579 LOG_DEBUG(Service_HID,
580 "called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, "
581 "device_index={}, applet_resource_user_id={}",
582 parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type,
583 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
584 parameters.applet_resource_user_id);
585
586 IPC::ResponseBuilder rb{ctx, 2};
587 rb.Push(result);
588}
589
590void IHidServer::SetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
591 IPC::RequestParser rp{ctx};
592 struct Parameters {
593 Core::HID::SixAxisSensorHandle sixaxis_handle;
594 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion;
595 INSERT_PADDING_WORDS_NOINIT(1);
596 u64 applet_resource_user_id;
597 };
598 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
599
600 const auto parameters{rp.PopRaw<Parameters>()};
601
602 auto six_axis = GetResourceManager()->GetSixAxis();
603 const auto result =
604 six_axis->SetSixAxisFusionParameters(parameters.sixaxis_handle, parameters.sixaxis_fusion);
605
606 LOG_DEBUG(Service_HID,
607 "called, npad_type={}, npad_id={}, device_index={}, parameter1={}, "
608 "parameter2={}, applet_resource_user_id={}",
609 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
610 parameters.sixaxis_handle.device_index, parameters.sixaxis_fusion.parameter1,
611 parameters.sixaxis_fusion.parameter2, parameters.applet_resource_user_id);
612
613 IPC::ResponseBuilder rb{ctx, 2};
614 rb.Push(result);
615}
616
617void IHidServer::GetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
618 IPC::RequestParser rp{ctx};
619 struct Parameters {
620 Core::HID::SixAxisSensorHandle sixaxis_handle;
621 INSERT_PADDING_WORDS_NOINIT(1);
622 u64 applet_resource_user_id;
623 };
624 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
625
626 const auto parameters{rp.PopRaw<Parameters>()};
627
628 Core::HID::SixAxisSensorFusionParameters fusion_parameters{};
629 auto six_axis = GetResourceManager()->GetSixAxis();
630 const auto result =
631 six_axis->GetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
632
633 LOG_DEBUG(Service_HID,
634 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
635 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
636 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
637
638 IPC::ResponseBuilder rb{ctx, 4};
639 rb.Push(result);
640 rb.PushRaw(fusion_parameters);
641}
642
643void IHidServer::ResetSixAxisSensorFusionParameters(HLERequestContext& ctx) {
644 IPC::RequestParser rp{ctx};
645 struct Parameters {
646 Core::HID::SixAxisSensorHandle sixaxis_handle;
647 INSERT_PADDING_WORDS_NOINIT(1);
648 u64 applet_resource_user_id;
649 };
650 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
651
652 const auto parameters{rp.PopRaw<Parameters>()};
653
654 // Since these parameters are unknown just use what HW outputs
655 const Core::HID::SixAxisSensorFusionParameters fusion_parameters{
656 .parameter1 = 0.03f,
657 .parameter2 = 0.4f,
658 };
659 auto six_axis = GetResourceManager()->GetSixAxis();
660 const auto result1 =
661 six_axis->SetSixAxisFusionParameters(parameters.sixaxis_handle, fusion_parameters);
662 const auto result2 = six_axis->SetSixAxisFusionEnabled(parameters.sixaxis_handle, true);
663
664 LOG_DEBUG(Service_HID,
665 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
666 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
667 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
668
669 IPC::ResponseBuilder rb{ctx, 2};
670 if (result1.IsError()) {
671 rb.Push(result1);
672 return;
673 }
674 rb.Push(result2);
675}
676
677void IHidServer::SetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
678 IPC::RequestParser rp{ctx};
679 const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
680 const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()};
681 const auto applet_resource_user_id{rp.Pop<u64>()};
682
683 auto six_axis = GetResourceManager()->GetSixAxis();
684 const auto result = six_axis->SetGyroscopeZeroDriftMode(sixaxis_handle, drift_mode);
685
686 LOG_DEBUG(Service_HID,
687 "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, "
688 "applet_resource_user_id={}",
689 sixaxis_handle.npad_type, sixaxis_handle.npad_id, sixaxis_handle.device_index,
690 drift_mode, applet_resource_user_id);
691
692 IPC::ResponseBuilder rb{ctx, 2};
693 rb.Push(result);
694}
695
696void IHidServer::GetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
697 IPC::RequestParser rp{ctx};
698 struct Parameters {
699 Core::HID::SixAxisSensorHandle sixaxis_handle;
700 INSERT_PADDING_WORDS_NOINIT(1);
701 u64 applet_resource_user_id;
702 };
703 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
704
705 const auto parameters{rp.PopRaw<Parameters>()};
706
707 auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
708 auto six_axis = GetResourceManager()->GetSixAxis();
709 const auto result = six_axis->GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
710
711 LOG_DEBUG(Service_HID,
712 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
713 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
714 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
715
716 IPC::ResponseBuilder rb{ctx, 3};
717 rb.Push(result);
718 rb.PushEnum(drift_mode);
719}
720
721void IHidServer::ResetGyroscopeZeroDriftMode(HLERequestContext& ctx) {
722 IPC::RequestParser rp{ctx};
723 struct Parameters {
724 Core::HID::SixAxisSensorHandle sixaxis_handle;
725 INSERT_PADDING_WORDS_NOINIT(1);
726 u64 applet_resource_user_id;
727 };
728 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
729
730 const auto parameters{rp.PopRaw<Parameters>()};
731
732 const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
733 auto six_axis = GetResourceManager()->GetSixAxis();
734 const auto result = six_axis->SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
735
736 LOG_DEBUG(Service_HID,
737 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
738 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
739 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
740
741 IPC::ResponseBuilder rb{ctx, 2};
742 rb.Push(result);
743}
744
745void IHidServer::IsSixAxisSensorAtRest(HLERequestContext& ctx) {
746 IPC::RequestParser rp{ctx};
747 struct Parameters {
748 Core::HID::SixAxisSensorHandle sixaxis_handle;
749 INSERT_PADDING_WORDS_NOINIT(1);
750 u64 applet_resource_user_id;
751 };
752 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
753
754 const auto parameters{rp.PopRaw<Parameters>()};
755
756 bool is_at_rest{};
757 auto six_axis = GetResourceManager()->GetSixAxis();
758 six_axis->IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
759
760 LOG_DEBUG(Service_HID,
761 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
762 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
763 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
764
765 IPC::ResponseBuilder rb{ctx, 3};
766 rb.Push(ResultSuccess);
767 rb.Push(is_at_rest);
768}
769
770void IHidServer::IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx) {
771 IPC::RequestParser rp{ctx};
772 struct Parameters {
773 Core::HID::SixAxisSensorHandle sixaxis_handle;
774 INSERT_PADDING_WORDS_NOINIT(1);
775 u64 applet_resource_user_id;
776 };
777 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
778
779 const auto parameters{rp.PopRaw<Parameters>()};
780
781 bool is_firmware_available{};
782 auto controller = GetResourceManager()->GetNpad();
783 controller->IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
784 is_firmware_available);
785
786 LOG_WARNING(
787 Service_HID,
788 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
789 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
790 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
791
792 IPC::ResponseBuilder rb{ctx, 3};
793 rb.Push(ResultSuccess);
794 rb.Push(is_firmware_available);
795}
796
797void IHidServer::EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx) {
798 IPC::RequestParser rp{ctx};
799 struct Parameters {
800 bool enabled;
801 Core::HID::SixAxisSensorHandle sixaxis_handle;
802 u64 applet_resource_user_id;
803 };
804 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
805
806 const auto parameters{rp.PopRaw<Parameters>()};
807
808 auto six_axis = GetResourceManager()->GetSixAxis();
809 const auto result = six_axis->EnableSixAxisSensorUnalteredPassthrough(parameters.sixaxis_handle,
810 parameters.enabled);
811
812 LOG_DEBUG(Service_HID,
813 "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
814 "applet_resource_user_id={}",
815 parameters.enabled, parameters.sixaxis_handle.npad_type,
816 parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
817 parameters.applet_resource_user_id);
818
819 IPC::ResponseBuilder rb{ctx, 2};
820 rb.Push(result);
821}
822
823void IHidServer::IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx) {
824 IPC::RequestParser rp{ctx};
825 struct Parameters {
826 Core::HID::SixAxisSensorHandle sixaxis_handle;
827 INSERT_PADDING_WORDS_NOINIT(1);
828 u64 applet_resource_user_id;
829 };
830 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
831
832 const auto parameters{rp.PopRaw<Parameters>()};
833
834 bool is_unaltered_sisxaxis_enabled{};
835 auto six_axis = GetResourceManager()->GetSixAxis();
836 const auto result = six_axis->IsSixAxisSensorUnalteredPassthroughEnabled(
837 parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
838
839 LOG_DEBUG(
840 Service_HID,
841 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
842 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
843 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
844
845 IPC::ResponseBuilder rb{ctx, 3};
846 rb.Push(result);
847 rb.Push(is_unaltered_sisxaxis_enabled);
848}
849
850void IHidServer::LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx) {
851 IPC::RequestParser rp{ctx};
852 struct Parameters {
853 Core::HID::SixAxisSensorHandle sixaxis_handle;
854 INSERT_PADDING_WORDS_NOINIT(1);
855 u64 applet_resource_user_id;
856 };
857 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
858
859 const auto parameters{rp.PopRaw<Parameters>()};
860
861 Core::HID::SixAxisSensorCalibrationParameter calibration{};
862 auto six_axis = GetResourceManager()->GetSixAxis();
863 const auto result =
864 six_axis->LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
865
866 LOG_WARNING(
867 Service_HID,
868 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
869 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
870 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
871
872 if (result.IsSuccess()) {
873 ctx.WriteBuffer(calibration);
874 }
875
876 IPC::ResponseBuilder rb{ctx, 2};
877 rb.Push(result);
878}
879
880void IHidServer::GetSixAxisSensorIcInformation(HLERequestContext& ctx) {
881 IPC::RequestParser rp{ctx};
882 struct Parameters {
883 Core::HID::SixAxisSensorHandle sixaxis_handle;
884 INSERT_PADDING_WORDS_NOINIT(1);
885 u64 applet_resource_user_id;
886 };
887 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
888
889 const auto parameters{rp.PopRaw<Parameters>()};
890
891 Core::HID::SixAxisSensorIcInformation ic_information{};
892 auto six_axis = GetResourceManager()->GetSixAxis();
893 const auto result =
894 six_axis->GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
895
896 LOG_WARNING(
897 Service_HID,
898 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
899 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
900 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
901
902 if (result.IsSuccess()) {
903 ctx.WriteBuffer(ic_information);
904 }
905
906 IPC::ResponseBuilder rb{ctx, 2};
907 rb.Push(result);
908}
909
910void IHidServer::ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx) {
911 IPC::RequestParser rp{ctx};
912 struct Parameters {
913 Core::HID::SixAxisSensorHandle sixaxis_handle;
914 INSERT_PADDING_WORDS_NOINIT(1);
915 u64 applet_resource_user_id;
916 };
917 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
918
919 const auto parameters{rp.PopRaw<Parameters>()};
920
921 auto controller = GetResourceManager()->GetNpad();
922 const auto result =
923 controller->ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
924
925 LOG_WARNING(
926 Service_HID,
927 "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
928 parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
929 parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
930
931 IPC::ResponseBuilder rb{ctx, 2};
932 rb.Push(result);
933}
934
935void IHidServer::ActivateGesture(HLERequestContext& ctx) {
936 IPC::RequestParser rp{ctx};
937 struct Parameters {
938 u32 basic_gesture_id;
939 INSERT_PADDING_WORDS_NOINIT(1);
940 u64 applet_resource_user_id;
941 };
942 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
943
944 const auto parameters{rp.PopRaw<Parameters>()};
945
946 LOG_INFO(Service_HID, "called, basic_gesture_id={}, applet_resource_user_id={}",
947 parameters.basic_gesture_id, parameters.applet_resource_user_id);
948
949 Result result = ResultSuccess;
950 auto gesture = GetResourceManager()->GetGesture();
951
952 if (!firmware_settings->IsDeviceManaged()) {
953 result = gesture->Activate();
954 }
955
956 if (result.IsSuccess()) {
957 // TODO: Use gesture id here
958 result = gesture->Activate(parameters.applet_resource_user_id);
959 }
960
961 IPC::ResponseBuilder rb{ctx, 2};
962 rb.Push(result);
963}
964
965void IHidServer::SetSupportedNpadStyleSet(HLERequestContext& ctx) {
966 IPC::RequestParser rp{ctx};
967 struct Parameters {
968 Core::HID::NpadStyleSet supported_styleset;
969 INSERT_PADDING_WORDS_NOINIT(1);
970 u64 applet_resource_user_id;
971 };
972 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
973
974 const auto parameters{rp.PopRaw<Parameters>()};
975
976 GetResourceManager()->GetNpad()->SetSupportedStyleSet({parameters.supported_styleset});
977
978 LOG_DEBUG(Service_HID, "called, supported_styleset={}, applet_resource_user_id={}",
979 parameters.supported_styleset, parameters.applet_resource_user_id);
980
981 IPC::ResponseBuilder rb{ctx, 2};
982 rb.Push(ResultSuccess);
983}
984
985void IHidServer::GetSupportedNpadStyleSet(HLERequestContext& ctx) {
986 IPC::RequestParser rp{ctx};
987 const auto applet_resource_user_id{rp.Pop<u64>()};
988
989 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
990
991 IPC::ResponseBuilder rb{ctx, 3};
992 rb.Push(ResultSuccess);
993 rb.PushEnum(GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw);
994}
995
996void IHidServer::SetSupportedNpadIdType(HLERequestContext& ctx) {
997 IPC::RequestParser rp{ctx};
998 const auto applet_resource_user_id{rp.Pop<u64>()};
999
1000 const auto result = GetResourceManager()->GetNpad()->SetSupportedNpadIdTypes(ctx.ReadBuffer());
1001
1002 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1003
1004 IPC::ResponseBuilder rb{ctx, 2};
1005 rb.Push(result);
1006}
1007
1008void IHidServer::ActivateNpad(HLERequestContext& ctx) {
1009 IPC::RequestParser rp{ctx};
1010 const auto applet_resource_user_id{rp.Pop<u64>()};
1011
1012 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1013
1014 auto npad = GetResourceManager()->GetNpad();
1015
1016 // TODO: npad->SetRevision(applet_resource_user_id, NpadRevision::Revision0);
1017 const Result result = npad->Activate(applet_resource_user_id);
1018
1019 IPC::ResponseBuilder rb{ctx, 2};
1020 rb.Push(result);
1021}
1022
1023void IHidServer::DeactivateNpad(HLERequestContext& ctx) {
1024 IPC::RequestParser rp{ctx};
1025 const auto applet_resource_user_id{rp.Pop<u64>()};
1026
1027 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1028
1029 // This function does nothing since 10.0.0+
1030
1031 IPC::ResponseBuilder rb{ctx, 2};
1032 rb.Push(ResultSuccess);
1033}
1034
1035void IHidServer::AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx) {
1036 IPC::RequestParser rp{ctx};
1037 struct Parameters {
1038 Core::HID::NpadIdType npad_id;
1039 INSERT_PADDING_WORDS_NOINIT(1);
1040 u64 applet_resource_user_id;
1041 u64 unknown;
1042 };
1043 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1044
1045 const auto parameters{rp.PopRaw<Parameters>()};
1046
1047 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
1048 parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown);
1049
1050 // Games expect this event to be signaled after calling this function
1051 GetResourceManager()->GetNpad()->SignalStyleSetChangedEvent(parameters.npad_id);
1052
1053 IPC::ResponseBuilder rb{ctx, 2, 1};
1054 rb.Push(ResultSuccess);
1055 rb.PushCopyObjects(
1056 GetResourceManager()->GetNpad()->GetStyleSetChangedEvent(parameters.npad_id));
1057}
1058
1059void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
1060 IPC::RequestParser rp{ctx};
1061 struct Parameters {
1062 Core::HID::NpadIdType npad_id;
1063 INSERT_PADDING_WORDS_NOINIT(1);
1064 u64 applet_resource_user_id;
1065 };
1066 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1067
1068 const auto parameters{rp.PopRaw<Parameters>()};
1069
1070 auto controller = GetResourceManager()->GetNpad();
1071 controller->DisconnectNpad(parameters.npad_id);
1072
1073 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1074 parameters.applet_resource_user_id);
1075
1076 IPC::ResponseBuilder rb{ctx, 2};
1077 rb.Push(ResultSuccess);
1078}
1079
1080void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
1081 IPC::RequestParser rp{ctx};
1082 const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
1083
1084 Core::HID::LedPattern pattern{0, 0, 0, 0};
1085 auto controller = GetResourceManager()->GetNpad();
1086 const auto result = controller->GetLedPattern(npad_id, pattern);
1087
1088 LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
1089
1090 IPC::ResponseBuilder rb{ctx, 4};
1091 rb.Push(result);
1092 rb.Push(pattern.raw);
1093}
1094
1095void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
1096 IPC::RequestParser rp{ctx};
1097 struct Parameters {
1098 NPad::NpadRevision revision;
1099 INSERT_PADDING_WORDS_NOINIT(1);
1100 u64 applet_resource_user_id;
1101 };
1102 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1103
1104 const auto parameters{rp.PopRaw<Parameters>()};
1105
1106 LOG_DEBUG(Service_HID, "called, revision={}, applet_resource_user_id={}", parameters.revision,
1107 parameters.applet_resource_user_id);
1108
1109 auto npad = GetResourceManager()->GetNpad();
1110
1111 // TODO: npad->SetRevision(applet_resource_user_id, revision);
1112 const auto result = npad->Activate(parameters.applet_resource_user_id);
1113
1114 IPC::ResponseBuilder rb{ctx, 2};
1115 rb.Push(result);
1116}
1117
1118void IHidServer::SetNpadJoyHoldType(HLERequestContext& ctx) {
1119 IPC::RequestParser rp{ctx};
1120 const auto applet_resource_user_id{rp.Pop<u64>()};
1121 const auto hold_type{rp.PopEnum<NPad::NpadJoyHoldType>()};
1122
1123 GetResourceManager()->GetNpad()->SetHoldType(hold_type);
1124
1125 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}",
1126 applet_resource_user_id, hold_type);
1127
1128 IPC::ResponseBuilder rb{ctx, 2};
1129 rb.Push(ResultSuccess);
1130}
1131
1132void IHidServer::GetNpadJoyHoldType(HLERequestContext& ctx) {
1133 IPC::RequestParser rp{ctx};
1134 const auto applet_resource_user_id{rp.Pop<u64>()};
1135
1136 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1137
1138 IPC::ResponseBuilder rb{ctx, 4};
1139 rb.Push(ResultSuccess);
1140 rb.PushEnum(GetResourceManager()->GetNpad()->GetHoldType());
1141}
1142
1143void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) {
1144 IPC::RequestParser rp{ctx};
1145 struct Parameters {
1146 Core::HID::NpadIdType npad_id;
1147 INSERT_PADDING_WORDS_NOINIT(1);
1148 u64 applet_resource_user_id;
1149 };
1150 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1151
1152 const auto parameters{rp.PopRaw<Parameters>()};
1153
1154 Core::HID::NpadIdType new_npad_id{};
1155 auto controller = GetResourceManager()->GetNpad();
1156 controller->SetNpadMode(new_npad_id, parameters.npad_id, NPad::NpadJoyDeviceType::Left,
1157 NPad::NpadJoyAssignmentMode::Single);
1158
1159 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1160 parameters.applet_resource_user_id);
1161
1162 IPC::ResponseBuilder rb{ctx, 2};
1163 rb.Push(ResultSuccess);
1164}
1165
1166void IHidServer::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
1167 IPC::RequestParser rp{ctx};
1168 struct Parameters {
1169 Core::HID::NpadIdType npad_id;
1170 INSERT_PADDING_WORDS_NOINIT(1);
1171 u64 applet_resource_user_id;
1172 NPad::NpadJoyDeviceType npad_joy_device_type;
1173 };
1174 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1175
1176 const auto parameters{rp.PopRaw<Parameters>()};
1177
1178 Core::HID::NpadIdType new_npad_id{};
1179 auto controller = GetResourceManager()->GetNpad();
1180 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1181 NPad::NpadJoyAssignmentMode::Single);
1182
1183 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1184 parameters.npad_id, parameters.applet_resource_user_id,
1185 parameters.npad_joy_device_type);
1186
1187 IPC::ResponseBuilder rb{ctx, 2};
1188 rb.Push(ResultSuccess);
1189}
1190
1191void IHidServer::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
1192 IPC::RequestParser rp{ctx};
1193 struct Parameters {
1194 Core::HID::NpadIdType npad_id;
1195 INSERT_PADDING_WORDS_NOINIT(1);
1196 u64 applet_resource_user_id;
1197 };
1198 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1199
1200 const auto parameters{rp.PopRaw<Parameters>()};
1201
1202 Core::HID::NpadIdType new_npad_id{};
1203 auto controller = GetResourceManager()->GetNpad();
1204 controller->SetNpadMode(new_npad_id, parameters.npad_id, {}, NPad::NpadJoyAssignmentMode::Dual);
1205
1206 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1207 parameters.applet_resource_user_id); // Spams a lot when controller applet is open
1208
1209 IPC::ResponseBuilder rb{ctx, 2};
1210 rb.Push(ResultSuccess);
1211}
1212
1213void IHidServer::MergeSingleJoyAsDualJoy(HLERequestContext& ctx) {
1214 IPC::RequestParser rp{ctx};
1215 const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
1216 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1217 const auto applet_resource_user_id{rp.Pop<u64>()};
1218
1219 auto controller = GetResourceManager()->GetNpad();
1220 const auto result = controller->MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
1221
1222 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1223 npad_id_1, npad_id_2, applet_resource_user_id);
1224
1225 IPC::ResponseBuilder rb{ctx, 2};
1226 rb.Push(result);
1227}
1228
1229void IHidServer::StartLrAssignmentMode(HLERequestContext& ctx) {
1230 IPC::RequestParser rp{ctx};
1231 const auto applet_resource_user_id{rp.Pop<u64>()};
1232
1233 GetResourceManager()->GetNpad()->StartLRAssignmentMode();
1234
1235 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1236
1237 IPC::ResponseBuilder rb{ctx, 2};
1238 rb.Push(ResultSuccess);
1239}
1240
1241void IHidServer::StopLrAssignmentMode(HLERequestContext& ctx) {
1242 IPC::RequestParser rp{ctx};
1243 const auto applet_resource_user_id{rp.Pop<u64>()};
1244
1245 GetResourceManager()->GetNpad()->StopLRAssignmentMode();
1246
1247 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1248
1249 IPC::ResponseBuilder rb{ctx, 2};
1250 rb.Push(ResultSuccess);
1251}
1252
1253void IHidServer::SetNpadHandheldActivationMode(HLERequestContext& ctx) {
1254 IPC::RequestParser rp{ctx};
1255 const auto applet_resource_user_id{rp.Pop<u64>()};
1256 const auto activation_mode{rp.PopEnum<NPad::NpadHandheldActivationMode>()};
1257
1258 GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(activation_mode);
1259
1260 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}",
1261 applet_resource_user_id, activation_mode);
1262
1263 IPC::ResponseBuilder rb{ctx, 2};
1264 rb.Push(ResultSuccess);
1265}
1266
1267void IHidServer::GetNpadHandheldActivationMode(HLERequestContext& ctx) {
1268 IPC::RequestParser rp{ctx};
1269 const auto applet_resource_user_id{rp.Pop<u64>()};
1270
1271 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1272
1273 IPC::ResponseBuilder rb{ctx, 4};
1274 rb.Push(ResultSuccess);
1275 rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode());
1276}
1277
1278void IHidServer::SwapNpadAssignment(HLERequestContext& ctx) {
1279 IPC::RequestParser rp{ctx};
1280 const auto npad_id_1{rp.PopEnum<Core::HID::NpadIdType>()};
1281 const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
1282 const auto applet_resource_user_id{rp.Pop<u64>()};
1283
1284 auto controller = GetResourceManager()->GetNpad();
1285 const auto result = controller->SwapNpadAssignment(npad_id_1, npad_id_2);
1286
1287 LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
1288 npad_id_1, npad_id_2, applet_resource_user_id);
1289
1290 IPC::ResponseBuilder rb{ctx, 2};
1291 rb.Push(result);
1292}
1293
1294void IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx) {
1295 IPC::RequestParser rp{ctx};
1296 struct Parameters {
1297 Core::HID::NpadIdType npad_id;
1298 INSERT_PADDING_WORDS_NOINIT(1);
1299 u64 applet_resource_user_id;
1300 };
1301 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1302
1303 const auto parameters{rp.PopRaw<Parameters>()};
1304
1305 bool is_enabled = false;
1306 auto controller = GetResourceManager()->GetNpad();
1307 const auto result =
1308 controller->IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
1309
1310 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
1311 parameters.npad_id, parameters.applet_resource_user_id);
1312
1313 IPC::ResponseBuilder rb{ctx, 3};
1314 rb.Push(result);
1315 rb.Push(is_enabled);
1316}
1317
1318void IHidServer::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
1319 IPC::RequestParser rp{ctx};
1320 struct Parameters {
1321 bool is_enabled;
1322 INSERT_PADDING_BYTES_NOINIT(3);
1323 Core::HID::NpadIdType npad_id;
1324 u64 applet_resource_user_id;
1325 };
1326 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1327
1328 const auto parameters{rp.PopRaw<Parameters>()};
1329
1330 auto controller = GetResourceManager()->GetNpad();
1331 const auto result = controller->SetUnintendedHomeButtonInputProtectionEnabled(
1332 parameters.is_enabled, parameters.npad_id);
1333
1334 LOG_DEBUG(Service_HID,
1335 "(STUBBED) called, is_enabled={}, npad_id={}, applet_resource_user_id={}",
1336 parameters.is_enabled, parameters.npad_id, parameters.applet_resource_user_id);
1337
1338 IPC::ResponseBuilder rb{ctx, 2};
1339 rb.Push(result);
1340}
1341
1342void IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx) {
1343 IPC::RequestParser rp{ctx};
1344 struct Parameters {
1345 Core::HID::NpadIdType npad_id;
1346 INSERT_PADDING_WORDS_NOINIT(1);
1347 u64 applet_resource_user_id;
1348 NPad::NpadJoyDeviceType npad_joy_device_type;
1349 };
1350 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1351
1352 const auto parameters{rp.PopRaw<Parameters>()};
1353
1354 Core::HID::NpadIdType new_npad_id{};
1355 auto controller = GetResourceManager()->GetNpad();
1356 const auto is_reassigned =
1357 controller->SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1358 NPad::NpadJoyAssignmentMode::Single);
1359
1360 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1361 parameters.npad_id, parameters.applet_resource_user_id,
1362 parameters.npad_joy_device_type);
1363
1364 IPC::ResponseBuilder rb{ctx, 4};
1365 rb.Push(ResultSuccess);
1366 rb.Push(is_reassigned);
1367 rb.PushEnum(new_npad_id);
1368}
1369
1370void IHidServer::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
1371 IPC::RequestParser rp{ctx};
1372 struct Parameters {
1373 bool analog_stick_use_center_clamp;
1374 INSERT_PADDING_BYTES_NOINIT(7);
1375 u64 applet_resource_user_id;
1376 };
1377 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1378
1379 const auto parameters{rp.PopRaw<Parameters>()};
1380
1381 GetResourceManager()->GetNpad()->SetAnalogStickUseCenterClamp(
1382 parameters.analog_stick_use_center_clamp);
1383
1384 LOG_WARNING(Service_HID,
1385 "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
1386 parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id);
1387
1388 IPC::ResponseBuilder rb{ctx, 2};
1389 rb.Push(ResultSuccess);
1390}
1391
1392void IHidServer::SetNpadCaptureButtonAssignment(HLERequestContext& ctx) {
1393 IPC::RequestParser rp{ctx};
1394 struct Parameters {
1395 Core::HID::NpadStyleSet npad_styleset;
1396 INSERT_PADDING_WORDS_NOINIT(1);
1397 u64 applet_resource_user_id;
1398 Core::HID::NpadButton button;
1399 };
1400 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1401
1402 const auto parameters{rp.PopRaw<Parameters>()};
1403
1404 LOG_WARNING(Service_HID,
1405 "(STUBBED) called, npad_styleset={}, applet_resource_user_id={}, button={}",
1406 parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button);
1407
1408 IPC::ResponseBuilder rb{ctx, 2};
1409 rb.Push(ResultSuccess);
1410}
1411
1412void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
1413 IPC::RequestParser rp{ctx};
1414 const auto applet_resource_user_id{rp.Pop<u64>()};
1415
1416 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1417 applet_resource_user_id);
1418
1419 IPC::ResponseBuilder rb{ctx, 2};
1420 rb.Push(ResultSuccess);
1421}
1422
1423void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
1424 IPC::RequestParser rp{ctx};
1425 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
1426 const auto controller = GetResourceManager()->GetNpad();
1427
1428 Core::HID::VibrationDeviceInfo vibration_device_info;
1429 bool check_device_index = false;
1430
1431 switch (vibration_device_handle.npad_type) {
1432 case Core::HID::NpadStyleIndex::ProController:
1433 case Core::HID::NpadStyleIndex::Handheld:
1434 case Core::HID::NpadStyleIndex::JoyconDual:
1435 case Core::HID::NpadStyleIndex::JoyconLeft:
1436 case Core::HID::NpadStyleIndex::JoyconRight:
1437 vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
1438 check_device_index = true;
1439 break;
1440 case Core::HID::NpadStyleIndex::GameCube:
1441 vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
1442 break;
1443 case Core::HID::NpadStyleIndex::N64:
1444 vibration_device_info.type = Core::HID::VibrationDeviceType::N64;
1445 break;
1446 default:
1447 vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
1448 break;
1449 }
1450
1451 vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
1452 if (check_device_index) {
1453 switch (vibration_device_handle.device_index) {
1454 case Core::HID::DeviceIndex::Left:
1455 vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
1456 break;
1457 case Core::HID::DeviceIndex::Right:
1458 vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
1459 break;
1460 case Core::HID::DeviceIndex::None:
1461 default:
1462 ASSERT_MSG(false, "DeviceIndex should never be None!");
1463 break;
1464 }
1465 }
1466
1467 LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}",
1468 vibration_device_info.type, vibration_device_info.position);
1469
1470 const auto result = IsVibrationHandleValid(vibration_device_handle);
1471 if (result.IsError()) {
1472 IPC::ResponseBuilder rb{ctx, 2};
1473 rb.Push(result);
1474 return;
1475 }
1476
1477 IPC::ResponseBuilder rb{ctx, 4};
1478 rb.Push(ResultSuccess);
1479 rb.PushRaw(vibration_device_info);
1480}
1481
1482void IHidServer::SendVibrationValue(HLERequestContext& ctx) {
1483 IPC::RequestParser rp{ctx};
1484 struct Parameters {
1485 Core::HID::VibrationDeviceHandle vibration_device_handle;
1486 Core::HID::VibrationValue vibration_value;
1487 INSERT_PADDING_WORDS_NOINIT(1);
1488 u64 applet_resource_user_id;
1489 };
1490 static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
1491
1492 const auto parameters{rp.PopRaw<Parameters>()};
1493
1494 GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle,
1495 parameters.vibration_value);
1496
1497 LOG_DEBUG(Service_HID,
1498 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1499 parameters.vibration_device_handle.npad_type,
1500 parameters.vibration_device_handle.npad_id,
1501 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1502
1503 IPC::ResponseBuilder rb{ctx, 2};
1504 rb.Push(ResultSuccess);
1505}
1506
1507void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) {
1508 IPC::RequestParser rp{ctx};
1509 struct Parameters {
1510 Core::HID::VibrationDeviceHandle vibration_device_handle;
1511 INSERT_PADDING_WORDS_NOINIT(1);
1512 u64 applet_resource_user_id;
1513 };
1514 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1515
1516 const auto parameters{rp.PopRaw<Parameters>()};
1517
1518 LOG_DEBUG(Service_HID,
1519 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1520 parameters.vibration_device_handle.npad_type,
1521 parameters.vibration_device_handle.npad_id,
1522 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1523
1524 IPC::ResponseBuilder rb{ctx, 6};
1525 rb.Push(ResultSuccess);
1526 rb.PushRaw(
1527 GetResourceManager()->GetNpad()->GetLastVibration(parameters.vibration_device_handle));
1528}
1529
1530void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) {
1531 LOG_DEBUG(Service_HID, "called");
1532
1533 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1534 rb.Push(ResultSuccess);
1535 rb.PushIpcInterface<IActiveVibrationDeviceList>(system, GetResourceManager());
1536}
1537
1538void IHidServer::PermitVibration(HLERequestContext& ctx) {
1539 IPC::RequestParser rp{ctx};
1540 const auto can_vibrate{rp.Pop<bool>()};
1541
1542 // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
1543 // by converting it to a bool
1544 Settings::values.vibration_enabled.SetValue(can_vibrate);
1545
1546 LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
1547
1548 IPC::ResponseBuilder rb{ctx, 2};
1549 rb.Push(ResultSuccess);
1550}
1551
1552void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) {
1553 LOG_DEBUG(Service_HID, "called");
1554
1555 // nnSDK checks if a float is greater than zero. We return the bool we stored earlier
1556 const auto is_enabled = Settings::values.vibration_enabled.GetValue();
1557
1558 IPC::ResponseBuilder rb{ctx, 3};
1559 rb.Push(ResultSuccess);
1560 rb.Push(is_enabled);
1561}
1562
1563void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
1564 IPC::RequestParser rp{ctx};
1565 const auto applet_resource_user_id{rp.Pop<u64>()};
1566
1567 const auto handle_data = ctx.ReadBuffer(0);
1568 const auto handle_count = ctx.GetReadBufferNumElements<Core::HID::VibrationDeviceHandle>(0);
1569 const auto vibration_data = ctx.ReadBuffer(1);
1570 const auto vibration_count = ctx.GetReadBufferNumElements<Core::HID::VibrationValue>(1);
1571
1572 auto vibration_device_handles =
1573 std::span(reinterpret_cast<const Core::HID::VibrationDeviceHandle*>(handle_data.data()),
1574 handle_count);
1575 auto vibration_values = std::span(
1576 reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
1577
1578 GetResourceManager()->GetNpad()->VibrateControllers(vibration_device_handles, vibration_values);
1579
1580 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1581
1582 IPC::ResponseBuilder rb{ctx, 2};
1583 rb.Push(ResultSuccess);
1584}
1585
1586void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
1587 IPC::RequestParser rp{ctx};
1588 struct Parameters {
1589 Core::HID::VibrationDeviceHandle vibration_device_handle;
1590 INSERT_PADDING_WORDS_NOINIT(1);
1591 u64 applet_resource_user_id;
1592 Core::HID::VibrationGcErmCommand gc_erm_command;
1593 };
1594 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1595
1596 const auto parameters{rp.PopRaw<Parameters>()};
1597
1598 /**
1599 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1600 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below,
1601 * in order to differentiate between Stop and StopHard commands.
1602 * This is done to reuse the controller vibration functions made for regular controllers.
1603 */
1604 const auto vibration_value = [parameters] {
1605 switch (parameters.gc_erm_command) {
1606 case Core::HID::VibrationGcErmCommand::Stop:
1607 return Core::HID::VibrationValue{
1608 .low_amplitude = 0.0f,
1609 .low_frequency = 160.0f,
1610 .high_amplitude = 0.0f,
1611 .high_frequency = 320.0f,
1612 };
1613 case Core::HID::VibrationGcErmCommand::Start:
1614 return Core::HID::VibrationValue{
1615 .low_amplitude = 1.0f,
1616 .low_frequency = 160.0f,
1617 .high_amplitude = 1.0f,
1618 .high_frequency = 320.0f,
1619 };
1620 case Core::HID::VibrationGcErmCommand::StopHard:
1621 return Core::HID::VibrationValue{
1622 .low_amplitude = 0.0f,
1623 .low_frequency = 0.0f,
1624 .high_amplitude = 0.0f,
1625 .high_frequency = 0.0f,
1626 };
1627 default:
1628 return Core::HID::DEFAULT_VIBRATION_VALUE;
1629 }
1630 }();
1631
1632 GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle,
1633 vibration_value);
1634
1635 LOG_DEBUG(Service_HID,
1636 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
1637 "gc_erm_command={}",
1638 parameters.vibration_device_handle.npad_type,
1639 parameters.vibration_device_handle.npad_id,
1640 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id,
1641 parameters.gc_erm_command);
1642
1643 IPC::ResponseBuilder rb{ctx, 2};
1644 rb.Push(ResultSuccess);
1645}
1646
1647void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
1648 IPC::RequestParser rp{ctx};
1649 struct Parameters {
1650 Core::HID::VibrationDeviceHandle vibration_device_handle;
1651 INSERT_PADDING_WORDS_NOINIT(1);
1652 u64 applet_resource_user_id;
1653 };
1654
1655 const auto parameters{rp.PopRaw<Parameters>()};
1656
1657 const auto last_vibration =
1658 GetResourceManager()->GetNpad()->GetLastVibration(parameters.vibration_device_handle);
1659
1660 const auto gc_erm_command = [last_vibration] {
1661 if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
1662 return Core::HID::VibrationGcErmCommand::Start;
1663 }
1664
1665 /**
1666 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1667 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function
1668 * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
1669 * This is done to reuse the controller vibration functions made for regular controllers.
1670 */
1671 if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
1672 return Core::HID::VibrationGcErmCommand::StopHard;
1673 }
1674
1675 return Core::HID::VibrationGcErmCommand::Stop;
1676 }();
1677
1678 LOG_DEBUG(Service_HID,
1679 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1680 parameters.vibration_device_handle.npad_type,
1681 parameters.vibration_device_handle.npad_id,
1682 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1683
1684 IPC::ResponseBuilder rb{ctx, 4};
1685 rb.Push(ResultSuccess);
1686 rb.PushEnum(gc_erm_command);
1687}
1688
1689void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
1690 IPC::RequestParser rp{ctx};
1691 const auto applet_resource_user_id{rp.Pop<u64>()};
1692
1693 GetResourceManager()->GetNpad()->SetPermitVibrationSession(true);
1694
1695 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1696
1697 IPC::ResponseBuilder rb{ctx, 2};
1698 rb.Push(ResultSuccess);
1699}
1700
1701void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) {
1702 GetResourceManager()->GetNpad()->SetPermitVibrationSession(false);
1703
1704 LOG_DEBUG(Service_HID, "called");
1705
1706 IPC::ResponseBuilder rb{ctx, 2};
1707 rb.Push(ResultSuccess);
1708}
1709
1710void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) {
1711 IPC::RequestParser rp{ctx};
1712 struct Parameters {
1713 Core::HID::VibrationDeviceHandle vibration_device_handle;
1714 INSERT_PADDING_WORDS_NOINIT(1);
1715 u64 applet_resource_user_id;
1716 };
1717 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1718
1719 const auto parameters{rp.PopRaw<Parameters>()};
1720
1721 LOG_DEBUG(Service_HID,
1722 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1723 parameters.vibration_device_handle.npad_type,
1724 parameters.vibration_device_handle.npad_id,
1725 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1726
1727 IPC::ResponseBuilder rb{ctx, 3};
1728 rb.Push(ResultSuccess);
1729 rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted(
1730 parameters.vibration_device_handle));
1731}
1732
1733void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
1734 IPC::RequestParser rp{ctx};
1735 const auto applet_resource_user_id{rp.Pop<u64>()};
1736
1737 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1738
1739 Result result = ResultSuccess;
1740 auto console_sixaxis = GetResourceManager()->GetConsoleSixAxis();
1741
1742 if (!firmware_settings->IsDeviceManaged()) {
1743 result = console_sixaxis->Activate();
1744 }
1745
1746 if (result.IsSuccess()) {
1747 result = console_sixaxis->Activate(applet_resource_user_id);
1748 }
1749
1750 IPC::ResponseBuilder rb{ctx, 2};
1751 rb.Push(result);
1752}
1753
1754void IHidServer::StartConsoleSixAxisSensor(HLERequestContext& ctx) {
1755 IPC::RequestParser rp{ctx};
1756 struct Parameters {
1757 Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
1758 INSERT_PADDING_WORDS_NOINIT(1);
1759 u64 applet_resource_user_id;
1760 };
1761 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1762
1763 const auto parameters{rp.PopRaw<Parameters>()};
1764
1765 LOG_WARNING(Service_HID,
1766 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
1767 parameters.console_sixaxis_handle.unknown_1,
1768 parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
1769
1770 IPC::ResponseBuilder rb{ctx, 2};
1771 rb.Push(ResultSuccess);
1772}
1773
1774void IHidServer::StopConsoleSixAxisSensor(HLERequestContext& ctx) {
1775 IPC::RequestParser rp{ctx};
1776 struct Parameters {
1777 Core::HID::ConsoleSixAxisSensorHandle console_sixaxis_handle;
1778 INSERT_PADDING_WORDS_NOINIT(1);
1779 u64 applet_resource_user_id;
1780 };
1781 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1782
1783 const auto parameters{rp.PopRaw<Parameters>()};
1784
1785 LOG_WARNING(Service_HID,
1786 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
1787 parameters.console_sixaxis_handle.unknown_1,
1788 parameters.console_sixaxis_handle.unknown_2, parameters.applet_resource_user_id);
1789
1790 IPC::ResponseBuilder rb{ctx, 2};
1791 rb.Push(ResultSuccess);
1792}
1793
1794void IHidServer::ActivateSevenSixAxisSensor(HLERequestContext& ctx) {
1795 IPC::RequestParser rp{ctx};
1796 const auto applet_resource_user_id{rp.Pop<u64>()};
1797
1798 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1799
1800 Result result = ResultSuccess;
1801 auto seven_sixaxis = GetResourceManager()->GetSevenSixAxis();
1802
1803 if (!firmware_settings->IsDeviceManaged()) {
1804 result = seven_sixaxis->Activate();
1805 }
1806
1807 if (result.IsSuccess()) {
1808 seven_sixaxis->Activate(applet_resource_user_id);
1809 }
1810
1811 IPC::ResponseBuilder rb{ctx, 2};
1812 rb.Push(ResultSuccess);
1813}
1814
1815void IHidServer::StartSevenSixAxisSensor(HLERequestContext& ctx) {
1816 IPC::RequestParser rp{ctx};
1817 const auto applet_resource_user_id{rp.Pop<u64>()};
1818
1819 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1820 applet_resource_user_id);
1821
1822 IPC::ResponseBuilder rb{ctx, 2};
1823 rb.Push(ResultSuccess);
1824}
1825
1826void IHidServer::StopSevenSixAxisSensor(HLERequestContext& ctx) {
1827 IPC::RequestParser rp{ctx};
1828 const auto applet_resource_user_id{rp.Pop<u64>()};
1829
1830 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1831 applet_resource_user_id);
1832
1833 IPC::ResponseBuilder rb{ctx, 2};
1834 rb.Push(ResultSuccess);
1835}
1836
1837void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
1838 IPC::RequestParser rp{ctx};
1839 const auto applet_resource_user_id{rp.Pop<u64>()};
1840 const auto t_mem_1_size{rp.Pop<u64>()};
1841 const auto t_mem_2_size{rp.Pop<u64>()};
1842 const auto t_mem_1_handle{ctx.GetCopyHandle(0)};
1843 const auto t_mem_2_handle{ctx.GetCopyHandle(1)};
1844
1845 ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
1846 ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
1847
1848 auto t_mem_1 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
1849 t_mem_1_handle);
1850
1851 if (t_mem_1.IsNull()) {
1852 LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
1853 IPC::ResponseBuilder rb{ctx, 2};
1854 rb.Push(ResultUnknown);
1855 return;
1856 }
1857
1858 auto t_mem_2 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
1859 t_mem_2_handle);
1860
1861 if (t_mem_2.IsNull()) {
1862 LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
1863 IPC::ResponseBuilder rb{ctx, 2};
1864 rb.Push(ResultUnknown);
1865 return;
1866 }
1867
1868 ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size");
1869 ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
1870
1871 // Activate console six axis controller
1872 GetResourceManager()->GetConsoleSixAxis()->Activate();
1873 GetResourceManager()->GetSevenSixAxis()->Activate();
1874
1875 GetResourceManager()->GetSevenSixAxis()->SetTransferMemoryAddress(t_mem_1->GetSourceAddress());
1876
1877 LOG_WARNING(Service_HID,
1878 "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
1879 "applet_resource_user_id={}",
1880 t_mem_1_handle, t_mem_2_handle, applet_resource_user_id);
1881
1882 IPC::ResponseBuilder rb{ctx, 2};
1883 rb.Push(ResultSuccess);
1884}
1885
1886void IHidServer::FinalizeSevenSixAxisSensor(HLERequestContext& ctx) {
1887 IPC::RequestParser rp{ctx};
1888 const auto applet_resource_user_id{rp.Pop<u64>()};
1889
1890 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1891 applet_resource_user_id);
1892
1893 IPC::ResponseBuilder rb{ctx, 2};
1894 rb.Push(ResultSuccess);
1895}
1896
1897void IHidServer::ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx) {
1898 IPC::RequestParser rp{ctx};
1899 const auto applet_resource_user_id{rp.Pop<u64>()};
1900
1901 GetResourceManager()->GetSevenSixAxis()->ResetTimestamp();
1902
1903 LOG_WARNING(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1904
1905 IPC::ResponseBuilder rb{ctx, 2};
1906 rb.Push(ResultSuccess);
1907}
1908
1909void IHidServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
1910 IPC::RequestParser rp{ctx};
1911
1912 LOG_WARNING(Service_HID, "(STUBBED) called");
1913
1914 IPC::ResponseBuilder rb{ctx, 3};
1915 rb.Push(ResultSuccess);
1916 rb.Push(false);
1917}
1918
1919void IHidServer::GetPalmaConnectionHandle(HLERequestContext& ctx) {
1920 IPC::RequestParser rp{ctx};
1921 struct Parameters {
1922 Core::HID::NpadIdType npad_id;
1923 INSERT_PADDING_WORDS_NOINIT(1);
1924 u64 applet_resource_user_id;
1925 };
1926 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1927
1928 const auto parameters{rp.PopRaw<Parameters>()};
1929
1930 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
1931 parameters.npad_id, parameters.applet_resource_user_id);
1932
1933 Palma::PalmaConnectionHandle handle;
1934 auto controller = GetResourceManager()->GetPalma();
1935 const auto result = controller->GetPalmaConnectionHandle(parameters.npad_id, handle);
1936
1937 IPC::ResponseBuilder rb{ctx, 4};
1938 rb.Push(result);
1939 rb.PushRaw(handle);
1940}
1941
1942void IHidServer::InitializePalma(HLERequestContext& ctx) {
1943 IPC::RequestParser rp{ctx};
1944 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
1945
1946 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
1947
1948 auto controller = GetResourceManager()->GetPalma();
1949 const auto result = controller->InitializePalma(connection_handle);
1950
1951 IPC::ResponseBuilder rb{ctx, 2};
1952 rb.Push(result);
1953}
1954
1955void IHidServer::AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx) {
1956 IPC::RequestParser rp{ctx};
1957 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
1958
1959 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
1960
1961 auto controller = GetResourceManager()->GetPalma();
1962
1963 IPC::ResponseBuilder rb{ctx, 2, 1};
1964 rb.Push(ResultSuccess);
1965 rb.PushCopyObjects(controller->AcquirePalmaOperationCompleteEvent(connection_handle));
1966}
1967
1968void IHidServer::GetPalmaOperationInfo(HLERequestContext& ctx) {
1969 IPC::RequestParser rp{ctx};
1970 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
1971
1972 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
1973
1974 Palma::PalmaOperationType operation_type;
1975 Palma::PalmaOperationData data;
1976 auto controller = GetResourceManager()->GetPalma();
1977 const auto result = controller->GetPalmaOperationInfo(connection_handle, operation_type, data);
1978
1979 if (result.IsError()) {
1980 IPC::ResponseBuilder rb{ctx, 2};
1981 rb.Push(result);
1982 }
1983
1984 ctx.WriteBuffer(data);
1985 IPC::ResponseBuilder rb{ctx, 4};
1986 rb.Push(result);
1987 rb.Push(static_cast<u64>(operation_type));
1988}
1989
1990void IHidServer::PlayPalmaActivity(HLERequestContext& ctx) {
1991 IPC::RequestParser rp{ctx};
1992 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
1993 const auto palma_activity{rp.Pop<u64>()};
1994
1995 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, palma_activity={}",
1996 connection_handle.npad_id, palma_activity);
1997
1998 auto controller = GetResourceManager()->GetPalma();
1999 const auto result = controller->PlayPalmaActivity(connection_handle, palma_activity);
2000
2001 IPC::ResponseBuilder rb{ctx, 2};
2002 rb.Push(result);
2003}
2004
2005void IHidServer::SetPalmaFrModeType(HLERequestContext& ctx) {
2006 IPC::RequestParser rp{ctx};
2007 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2008 const auto fr_mode{rp.PopEnum<Palma::PalmaFrModeType>()};
2009
2010 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, fr_mode={}",
2011 connection_handle.npad_id, fr_mode);
2012
2013 auto controller = GetResourceManager()->GetPalma();
2014 const auto result = controller->SetPalmaFrModeType(connection_handle, fr_mode);
2015
2016 IPC::ResponseBuilder rb{ctx, 2};
2017 rb.Push(result);
2018}
2019
2020void IHidServer::ReadPalmaStep(HLERequestContext& ctx) {
2021 IPC::RequestParser rp{ctx};
2022 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2023
2024 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2025
2026 auto controller = GetResourceManager()->GetPalma();
2027 const auto result = controller->ReadPalmaStep(connection_handle);
2028
2029 IPC::ResponseBuilder rb{ctx, 2};
2030 rb.Push(result);
2031}
2032
2033void IHidServer::EnablePalmaStep(HLERequestContext& ctx) {
2034 IPC::RequestParser rp{ctx};
2035 struct Parameters {
2036 bool is_enabled;
2037 INSERT_PADDING_WORDS_NOINIT(1);
2038 Palma::PalmaConnectionHandle connection_handle;
2039 };
2040 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2041
2042 const auto parameters{rp.PopRaw<Parameters>()};
2043
2044 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, is_enabled={}",
2045 parameters.connection_handle.npad_id, parameters.is_enabled);
2046
2047 auto controller = GetResourceManager()->GetPalma();
2048 const auto result =
2049 controller->EnablePalmaStep(parameters.connection_handle, parameters.is_enabled);
2050
2051 IPC::ResponseBuilder rb{ctx, 2};
2052 rb.Push(result);
2053}
2054
2055void IHidServer::ResetPalmaStep(HLERequestContext& ctx) {
2056 IPC::RequestParser rp{ctx};
2057 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2058
2059 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2060
2061 auto controller = GetResourceManager()->GetPalma();
2062 const auto result = controller->ResetPalmaStep(connection_handle);
2063
2064 IPC::ResponseBuilder rb{ctx, 2};
2065 rb.Push(result);
2066}
2067
2068void IHidServer::ReadPalmaApplicationSection(HLERequestContext& ctx) {
2069 LOG_WARNING(Service_HID, "(STUBBED) called");
2070
2071 IPC::ResponseBuilder rb{ctx, 2};
2072 rb.Push(ResultSuccess);
2073}
2074
2075void IHidServer::WritePalmaApplicationSection(HLERequestContext& ctx) {
2076 LOG_WARNING(Service_HID, "(STUBBED) called");
2077
2078 IPC::ResponseBuilder rb{ctx, 2};
2079 rb.Push(ResultSuccess);
2080}
2081
2082void IHidServer::ReadPalmaUniqueCode(HLERequestContext& ctx) {
2083 IPC::RequestParser rp{ctx};
2084 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2085
2086 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2087
2088 GetResourceManager()->GetPalma()->ReadPalmaUniqueCode(connection_handle);
2089
2090 IPC::ResponseBuilder rb{ctx, 2};
2091 rb.Push(ResultSuccess);
2092}
2093
2094void IHidServer::SetPalmaUniqueCodeInvalid(HLERequestContext& ctx) {
2095 IPC::RequestParser rp{ctx};
2096 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2097
2098 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2099
2100 GetResourceManager()->GetPalma()->SetPalmaUniqueCodeInvalid(connection_handle);
2101
2102 IPC::ResponseBuilder rb{ctx, 2};
2103 rb.Push(ResultSuccess);
2104}
2105
2106void IHidServer::WritePalmaActivityEntry(HLERequestContext& ctx) {
2107 LOG_CRITICAL(Service_HID, "(STUBBED) called");
2108
2109 IPC::ResponseBuilder rb{ctx, 2};
2110 rb.Push(ResultSuccess);
2111}
2112
2113void IHidServer::WritePalmaRgbLedPatternEntry(HLERequestContext& ctx) {
2114 IPC::RequestParser rp{ctx};
2115 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2116 const auto unknown{rp.Pop<u64>()};
2117
2118 [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
2119
2120 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, unknown={}",
2121 connection_handle.npad_id, unknown);
2122
2123 GetResourceManager()->GetPalma()->WritePalmaRgbLedPatternEntry(connection_handle, unknown);
2124
2125 IPC::ResponseBuilder rb{ctx, 2};
2126 rb.Push(ResultSuccess);
2127}
2128
2129void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) {
2130 IPC::RequestParser rp{ctx};
2131 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2132 const auto wave_set{rp.PopEnum<Palma::PalmaWaveSet>()};
2133 const auto unknown{rp.Pop<u64>()};
2134 const auto t_mem_size{rp.Pop<u64>()};
2135 const auto t_mem_handle{ctx.GetCopyHandle(0)};
2136 const auto size{rp.Pop<u64>()};
2137
2138 ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes");
2139
2140 auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
2141 t_mem_handle);
2142
2143 if (t_mem.IsNull()) {
2144 LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
2145 IPC::ResponseBuilder rb{ctx, 2};
2146 rb.Push(ResultUnknown);
2147 return;
2148 }
2149
2150 ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size");
2151
2152 LOG_WARNING(Service_HID,
2153 "(STUBBED) called, connection_handle={}, wave_set={}, unknown={}, "
2154 "t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
2155 connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
2156
2157 GetResourceManager()->GetPalma()->WritePalmaWaveEntry(connection_handle, wave_set,
2158 t_mem->GetSourceAddress(), t_mem_size);
2159
2160 IPC::ResponseBuilder rb{ctx, 2};
2161 rb.Push(ResultSuccess);
2162}
2163
2164void IHidServer::SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2165 IPC::RequestParser rp{ctx};
2166 struct Parameters {
2167 s32 database_id_version;
2168 INSERT_PADDING_WORDS_NOINIT(1);
2169 Palma::PalmaConnectionHandle connection_handle;
2170 };
2171 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2172
2173 const auto parameters{rp.PopRaw<Parameters>()};
2174
2175 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}, database_id_version={}",
2176 parameters.connection_handle.npad_id, parameters.database_id_version);
2177
2178 GetResourceManager()->GetPalma()->SetPalmaDataBaseIdentificationVersion(
2179 parameters.connection_handle, parameters.database_id_version);
2180
2181 IPC::ResponseBuilder rb{ctx, 2};
2182 rb.Push(ResultSuccess);
2183}
2184
2185void IHidServer::GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx) {
2186 IPC::RequestParser rp{ctx};
2187 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2188
2189 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2190
2191 GetResourceManager()->GetPalma()->GetPalmaDataBaseIdentificationVersion(connection_handle);
2192
2193 IPC::ResponseBuilder rb{ctx, 2};
2194 rb.Push(ResultSuccess);
2195}
2196
2197void IHidServer::SuspendPalmaFeature(HLERequestContext& ctx) {
2198 LOG_WARNING(Service_HID, "(STUBBED) called");
2199
2200 IPC::ResponseBuilder rb{ctx, 2};
2201 rb.Push(ResultSuccess);
2202}
2203
2204void IHidServer::GetPalmaOperationResult(HLERequestContext& ctx) {
2205 IPC::RequestParser rp{ctx};
2206 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2207
2208 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2209
2210 const auto result =
2211 GetResourceManager()->GetPalma()->GetPalmaOperationResult(connection_handle);
2212
2213 IPC::ResponseBuilder rb{ctx, 2};
2214 rb.Push(result);
2215}
2216
2217void IHidServer::ReadPalmaPlayLog(HLERequestContext& ctx) {
2218 LOG_WARNING(Service_HID, "(STUBBED) called");
2219
2220 IPC::ResponseBuilder rb{ctx, 2};
2221 rb.Push(ResultSuccess);
2222}
2223
2224void IHidServer::ResetPalmaPlayLog(HLERequestContext& ctx) {
2225 LOG_WARNING(Service_HID, "(STUBBED) called");
2226
2227 IPC::ResponseBuilder rb{ctx, 2};
2228 rb.Push(ResultSuccess);
2229}
2230
2231void IHidServer::SetIsPalmaAllConnectable(HLERequestContext& ctx) {
2232 IPC::RequestParser rp{ctx};
2233 struct Parameters {
2234 bool is_palma_all_connectable;
2235 INSERT_PADDING_BYTES_NOINIT(7);
2236 u64 applet_resource_user_id;
2237 };
2238 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2239
2240 const auto parameters{rp.PopRaw<Parameters>()};
2241
2242 LOG_WARNING(Service_HID,
2243 "(STUBBED) called, is_palma_all_connectable={},applet_resource_user_id={}",
2244 parameters.is_palma_all_connectable, parameters.applet_resource_user_id);
2245
2246 GetResourceManager()->GetPalma()->SetIsPalmaAllConnectable(parameters.is_palma_all_connectable);
2247
2248 IPC::ResponseBuilder rb{ctx, 2};
2249 rb.Push(ResultSuccess);
2250}
2251
2252void IHidServer::SetIsPalmaPairedConnectable(HLERequestContext& ctx) {
2253 LOG_WARNING(Service_HID, "(STUBBED) called");
2254
2255 IPC::ResponseBuilder rb{ctx, 2};
2256 rb.Push(ResultSuccess);
2257}
2258
2259void IHidServer::PairPalma(HLERequestContext& ctx) {
2260 IPC::RequestParser rp{ctx};
2261 const auto connection_handle{rp.PopRaw<Palma::PalmaConnectionHandle>()};
2262
2263 LOG_WARNING(Service_HID, "(STUBBED) called, connection_handle={}", connection_handle.npad_id);
2264
2265 GetResourceManager()->GetPalma()->PairPalma(connection_handle);
2266
2267 IPC::ResponseBuilder rb{ctx, 2};
2268 rb.Push(ResultSuccess);
2269}
2270
2271void IHidServer::SetPalmaBoostMode(HLERequestContext& ctx) {
2272 IPC::RequestParser rp{ctx};
2273 const auto palma_boost_mode{rp.Pop<bool>()};
2274
2275 LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode);
2276
2277 GetResourceManager()->GetPalma()->SetPalmaBoostMode(palma_boost_mode);
2278
2279 IPC::ResponseBuilder rb{ctx, 2};
2280 rb.Push(ResultSuccess);
2281}
2282
2283void IHidServer::CancelWritePalmaWaveEntry(HLERequestContext& ctx) {
2284 LOG_WARNING(Service_HID, "(STUBBED) called");
2285
2286 IPC::ResponseBuilder rb{ctx, 2};
2287 rb.Push(ResultSuccess);
2288}
2289
2290void IHidServer::EnablePalmaBoostMode(HLERequestContext& ctx) {
2291 LOG_WARNING(Service_HID, "(STUBBED) called");
2292
2293 IPC::ResponseBuilder rb{ctx, 2};
2294 rb.Push(ResultSuccess);
2295}
2296
2297void IHidServer::GetPalmaBluetoothAddress(HLERequestContext& ctx) {
2298 LOG_WARNING(Service_HID, "(STUBBED) called");
2299
2300 IPC::ResponseBuilder rb{ctx, 2};
2301 rb.Push(ResultSuccess);
2302}
2303
2304void IHidServer::SetDisallowedPalmaConnection(HLERequestContext& ctx) {
2305 LOG_WARNING(Service_HID, "(STUBBED) called");
2306
2307 IPC::ResponseBuilder rb{ctx, 2};
2308 rb.Push(ResultSuccess);
2309}
2310
2311void IHidServer::SetNpadCommunicationMode(HLERequestContext& ctx) {
2312 IPC::RequestParser rp{ctx};
2313 const auto applet_resource_user_id{rp.Pop<u64>()};
2314 const auto communication_mode{rp.PopEnum<NPad::NpadCommunicationMode>()};
2315
2316 GetResourceManager()->GetNpad()->SetNpadCommunicationMode(communication_mode);
2317
2318 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}",
2319 applet_resource_user_id, communication_mode);
2320
2321 IPC::ResponseBuilder rb{ctx, 2};
2322 rb.Push(ResultSuccess);
2323}
2324
2325void IHidServer::GetNpadCommunicationMode(HLERequestContext& ctx) {
2326 IPC::RequestParser rp{ctx};
2327
2328 LOG_WARNING(Service_HID, "(STUBBED) called");
2329
2330 IPC::ResponseBuilder rb{ctx, 4};
2331 rb.Push(ResultSuccess);
2332 rb.PushEnum(GetResourceManager()->GetNpad()->GetNpadCommunicationMode());
2333}
2334
2335void IHidServer::SetTouchScreenConfiguration(HLERequestContext& ctx) {
2336 IPC::RequestParser rp{ctx};
2337 const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()};
2338 const auto applet_resource_user_id{rp.Pop<u64>()};
2339
2340 LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
2341 touchscreen_mode.mode, applet_resource_user_id);
2342
2343 IPC::ResponseBuilder rb{ctx, 2};
2344 rb.Push(ResultSuccess);
2345}
2346
2347void IHidServer::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) {
2348 IPC::RequestParser rp{ctx};
2349 struct Parameters {
2350 s32 unknown;
2351 INSERT_PADDING_WORDS_NOINIT(1);
2352 u64 applet_resource_user_id;
2353 };
2354 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
2355
2356 const auto parameters{rp.PopRaw<Parameters>()};
2357
2358 LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}",
2359 parameters.unknown, parameters.applet_resource_user_id);
2360
2361 IPC::ResponseBuilder rb{ctx, 3};
2362 rb.Push(ResultSuccess);
2363 rb.Push(false);
2364}
2365
2366std::shared_ptr<ResourceManager> IHidServer::GetResourceManager() {
2367 resource_manager->Initialize();
2368 return resource_manager;
2369}
2370
2371} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Core {
9class System;
10}
11
12namespace Service::HID {
13class ResourceManager;
14class HidFirmwareSettings;
15
16class IHidServer final : public ServiceFramework<IHidServer> {
17public:
18 explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource,
19 std::shared_ptr<HidFirmwareSettings> settings);
20 ~IHidServer() override;
21
22 std::shared_ptr<ResourceManager> GetResourceManager();
23
24private:
25 void CreateAppletResource(HLERequestContext& ctx);
26 void ActivateDebugPad(HLERequestContext& ctx);
27 void ActivateTouchScreen(HLERequestContext& ctx);
28 void ActivateMouse(HLERequestContext& ctx);
29 void ActivateKeyboard(HLERequestContext& ctx);
30 void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
31 void AcquireXpadIdEventHandle(HLERequestContext& ctx);
32 void ReleaseXpadIdEventHandle(HLERequestContext& ctx);
33 void ActivateXpad(HLERequestContext& ctx);
34 void GetXpadIds(HLERequestContext& ctx);
35 void ActivateJoyXpad(HLERequestContext& ctx);
36 void GetJoyXpadLifoHandle(HLERequestContext& ctx);
37 void GetJoyXpadIds(HLERequestContext& ctx);
38 void ActivateSixAxisSensor(HLERequestContext& ctx);
39 void DeactivateSixAxisSensor(HLERequestContext& ctx);
40 void GetSixAxisSensorLifoHandle(HLERequestContext& ctx);
41 void ActivateJoySixAxisSensor(HLERequestContext& ctx);
42 void DeactivateJoySixAxisSensor(HLERequestContext& ctx);
43 void GetJoySixAxisSensorLifoHandle(HLERequestContext& ctx);
44 void StartSixAxisSensor(HLERequestContext& ctx);
45 void StopSixAxisSensor(HLERequestContext& ctx);
46 void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
47 void EnableSixAxisSensorFusion(HLERequestContext& ctx);
48 void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
49 void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
50 void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
51 void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
52 void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
53 void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
54 void IsSixAxisSensorAtRest(HLERequestContext& ctx);
55 void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
56 void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
57 void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
58 void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
59 void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
60 void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
61 void ActivateGesture(HLERequestContext& ctx);
62 void SetSupportedNpadStyleSet(HLERequestContext& ctx);
63 void GetSupportedNpadStyleSet(HLERequestContext& ctx);
64 void SetSupportedNpadIdType(HLERequestContext& ctx);
65 void ActivateNpad(HLERequestContext& ctx);
66 void DeactivateNpad(HLERequestContext& ctx);
67 void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
68 void DisconnectNpad(HLERequestContext& ctx);
69 void GetPlayerLedPattern(HLERequestContext& ctx);
70 void ActivateNpadWithRevision(HLERequestContext& ctx);
71 void SetNpadJoyHoldType(HLERequestContext& ctx);
72 void GetNpadJoyHoldType(HLERequestContext& ctx);
73 void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
74 void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
75 void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
76 void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
77 void StartLrAssignmentMode(HLERequestContext& ctx);
78 void StopLrAssignmentMode(HLERequestContext& ctx);
79 void SetNpadHandheldActivationMode(HLERequestContext& ctx);
80 void GetNpadHandheldActivationMode(HLERequestContext& ctx);
81 void SwapNpadAssignment(HLERequestContext& ctx);
82 void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
83 void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
84 void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
85 void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
86 void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
87 void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
88 void GetVibrationDeviceInfo(HLERequestContext& ctx);
89 void SendVibrationValue(HLERequestContext& ctx);
90 void GetActualVibrationValue(HLERequestContext& ctx);
91 void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
92 void PermitVibration(HLERequestContext& ctx);
93 void IsVibrationPermitted(HLERequestContext& ctx);
94 void SendVibrationValues(HLERequestContext& ctx);
95 void SendVibrationGcErmCommand(HLERequestContext& ctx);
96 void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
97 void BeginPermitVibrationSession(HLERequestContext& ctx);
98 void EndPermitVibrationSession(HLERequestContext& ctx);
99 void IsVibrationDeviceMounted(HLERequestContext& ctx);
100 void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
101 void StartConsoleSixAxisSensor(HLERequestContext& ctx);
102 void StopConsoleSixAxisSensor(HLERequestContext& ctx);
103 void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
104 void StartSevenSixAxisSensor(HLERequestContext& ctx);
105 void StopSevenSixAxisSensor(HLERequestContext& ctx);
106 void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
107 void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
108 void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
109 void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
110 void GetPalmaConnectionHandle(HLERequestContext& ctx);
111 void InitializePalma(HLERequestContext& ctx);
112 void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
113 void GetPalmaOperationInfo(HLERequestContext& ctx);
114 void PlayPalmaActivity(HLERequestContext& ctx);
115 void SetPalmaFrModeType(HLERequestContext& ctx);
116 void ReadPalmaStep(HLERequestContext& ctx);
117 void EnablePalmaStep(HLERequestContext& ctx);
118 void ResetPalmaStep(HLERequestContext& ctx);
119 void ReadPalmaApplicationSection(HLERequestContext& ctx);
120 void WritePalmaApplicationSection(HLERequestContext& ctx);
121 void ReadPalmaUniqueCode(HLERequestContext& ctx);
122 void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
123 void WritePalmaActivityEntry(HLERequestContext& ctx);
124 void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
125 void WritePalmaWaveEntry(HLERequestContext& ctx);
126 void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
127 void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
128 void SuspendPalmaFeature(HLERequestContext& ctx);
129 void GetPalmaOperationResult(HLERequestContext& ctx);
130 void ReadPalmaPlayLog(HLERequestContext& ctx);
131 void ResetPalmaPlayLog(HLERequestContext& ctx);
132 void SetIsPalmaAllConnectable(HLERequestContext& ctx);
133 void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
134 void PairPalma(HLERequestContext& ctx);
135 void SetPalmaBoostMode(HLERequestContext& ctx);
136 void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
137 void EnablePalmaBoostMode(HLERequestContext& ctx);
138 void GetPalmaBluetoothAddress(HLERequestContext& ctx);
139 void SetDisallowedPalmaConnection(HLERequestContext& ctx);
140 void SetNpadCommunicationMode(HLERequestContext& ctx);
141 void GetNpadCommunicationMode(HLERequestContext& ctx);
142 void SetTouchScreenConfiguration(HLERequestContext& ctx);
143 void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
144
145 std::shared_ptr<ResourceManager> resource_manager;
146 std::shared_ptr<HidFirmwareSettings> firmware_settings;
147};
148
149} // 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..b56d0347a
--- /dev/null
+++ b/src/core/hle/service/hid/hid_system_server.cpp
@@ -0,0 +1,539 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hid/hid_core.h"
5#include "core/hle/service/hid/controllers/npad.h"
6#include "core/hle/service/hid/controllers/touchscreen.h"
7#include "core/hle/service/hid/errors.h"
8#include "core/hle/service/hid/hid_system_server.h"
9#include "core/hle/service/hid/resource_manager.h"
10#include "core/hle/service/ipc_helpers.h"
11
12namespace Service::HID {
13
14IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
15 : ServiceFramework{system_, "hid:sys"}, service_context{system_, service_name},
16 resource_manager{resource} {
17 // clang-format off
18 static const FunctionInfo functions[] = {
19 {31, nullptr, "SendKeyboardLockKeyEvent"},
20 {101, nullptr, "AcquireHomeButtonEventHandle"},
21 {111, nullptr, "ActivateHomeButton"},
22 {121, nullptr, "AcquireSleepButtonEventHandle"},
23 {131, nullptr, "ActivateSleepButton"},
24 {141, nullptr, "AcquireCaptureButtonEventHandle"},
25 {151, nullptr, "ActivateCaptureButton"},
26 {161, nullptr, "GetPlatformConfig"},
27 {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
28 {211, nullptr, "GetNpadsWithNfc"},
29 {212, nullptr, "AcquireNfcActivateEventHandle"},
30 {213, nullptr, "ActivateNfc"},
31 {214, nullptr, "GetXcdHandleForNpadWithNfc"},
32 {215, nullptr, "IsNfcActivated"},
33 {230, nullptr, "AcquireIrSensorEventHandle"},
34 {231, nullptr, "ActivateIrSensor"},
35 {232, nullptr, "GetIrSensorState"},
36 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
37 {301, nullptr, "ActivateNpadSystem"},
38 {303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
39 {304, &IHidSystemServer::EnableAssigningSingleOnSlSrPress, "EnableAssigningSingleOnSlSrPress"},
40 {305, &IHidSystemServer::DisableAssigningSingleOnSlSrPress, "DisableAssigningSingleOnSlSrPress"},
41 {306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"},
42 {307, nullptr, "GetNpadSystemExtStyle"},
43 {308, &IHidSystemServer::ApplyNpadSystemCommonPolicyFull, "ApplyNpadSystemCommonPolicyFull"},
44 {309, &IHidSystemServer::GetNpadFullKeyGripColor, "GetNpadFullKeyGripColor"},
45 {310, &IHidSystemServer::GetMaskedSupportedNpadStyleSet, "GetMaskedSupportedNpadStyleSet"},
46 {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
47 {312, &IHidSystemServer::SetSupportedNpadStyleSetAll, "SetSupportedNpadStyleSetAll"},
48 {313, nullptr, "GetNpadCaptureButtonAssignment"},
49 {314, nullptr, "GetAppletFooterUiType"},
50 {315, &IHidSystemServer::GetAppletDetailedUiType, "GetAppletDetailedUiType"},
51 {316, &IHidSystemServer::GetNpadInterfaceType, "GetNpadInterfaceType"},
52 {317, &IHidSystemServer::GetNpadLeftRightInterfaceType, "GetNpadLeftRightInterfaceType"},
53 {318, &IHidSystemServer::HasBattery, "HasBattery"},
54 {319, &IHidSystemServer::HasLeftRightBattery, "HasLeftRightBattery"},
55 {321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
56 {322, &IHidSystemServer::GetIrSensorState, "GetIrSensorState"},
57 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
58 {324, nullptr, "GetUniquePadButtonSet"},
59 {325, nullptr, "GetUniquePadColor"},
60 {326, nullptr, "GetUniquePadAppletDetailedUiType"},
61 {327, nullptr, "GetAbstractedPadIdDataFromNpad"},
62 {328, nullptr, "AttachAbstractedPadToNpad"},
63 {329, nullptr, "DetachAbstractedPadAll"},
64 {330, nullptr, "CheckAbstractedPadConnection"},
65 {500, nullptr, "SetAppletResourceUserId"},
66 {501, nullptr, "RegisterAppletResourceUserId"},
67 {502, nullptr, "UnregisterAppletResourceUserId"},
68 {503, nullptr, "EnableAppletToGetInput"},
69 {504, nullptr, "SetAruidValidForVibration"},
70 {505, nullptr, "EnableAppletToGetSixAxisSensor"},
71 {506, nullptr, "EnableAppletToGetPadInput"},
72 {507, nullptr, "EnableAppletToGetTouchScreen"},
73 {510, nullptr, "SetVibrationMasterVolume"},
74 {511, nullptr, "GetVibrationMasterVolume"},
75 {512, nullptr, "BeginPermitVibrationSession"},
76 {513, nullptr, "EndPermitVibrationSession"},
77 {514, nullptr, "Unknown514"},
78 {520, nullptr, "EnableHandheldHids"},
79 {521, nullptr, "DisableHandheldHids"},
80 {522, nullptr, "SetJoyConRailEnabled"},
81 {523, nullptr, "IsJoyConRailEnabled"},
82 {524, nullptr, "IsHandheldHidsEnabled"},
83 {525, nullptr, "IsJoyConAttachedOnAllRail"},
84 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
85 {541, nullptr, "GetPlayReportControllerUsages"},
86 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
87 {543, nullptr, "GetRegisteredDevicesOld"},
88 {544, &IHidSystemServer::AcquireConnectionTriggerTimeoutEvent, "AcquireConnectionTriggerTimeoutEvent"},
89 {545, nullptr, "SendConnectionTrigger"},
90 {546, &IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport, "AcquireDeviceRegisteredEventForControllerSupport"},
91 {547, nullptr, "GetAllowedBluetoothLinksCount"},
92 {548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"},
93 {549, nullptr, "GetConnectableRegisteredDevices"},
94 {700, nullptr, "ActivateUniquePad"},
95 {702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"},
96 {703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"},
97 {751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
98 {800, nullptr, "ListSixAxisSensorHandles"},
99 {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
100 {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
101 {803, nullptr, "StartSixAxisSensorUserCalibration"},
102 {804, nullptr, "CancelSixAxisSensorUserCalibration"},
103 {805, nullptr, "GetUniquePadBluetoothAddress"},
104 {806, nullptr, "DisconnectUniquePad"},
105 {807, nullptr, "GetUniquePadType"},
106 {808, nullptr, "GetUniquePadInterface"},
107 {809, nullptr, "GetUniquePadSerialNumber"},
108 {810, nullptr, "GetUniquePadControllerNumber"},
109 {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
110 {812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
111 {821, nullptr, "StartAnalogStickManualCalibration"},
112 {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
113 {823, nullptr, "CancelAnalogStickManualCalibration"},
114 {824, nullptr, "ResetAnalogStickManualCalibration"},
115 {825, nullptr, "GetAnalogStickState"},
116 {826, nullptr, "GetAnalogStickManualCalibrationStage"},
117 {827, nullptr, "IsAnalogStickButtonPressed"},
118 {828, nullptr, "IsAnalogStickInReleasePosition"},
119 {829, nullptr, "IsAnalogStickInCircumference"},
120 {830, nullptr, "SetNotificationLedPattern"},
121 {831, nullptr, "SetNotificationLedPatternWithTimeout"},
122 {832, nullptr, "PrepareHidsForNotificationWake"},
123 {850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
124 {851, nullptr, "EnableUsbFullKeyController"},
125 {852, nullptr, "IsUsbConnected"},
126 {870, &IHidSystemServer::IsHandheldButtonPressedOnConsoleMode, "IsHandheldButtonPressedOnConsoleMode"},
127 {900, nullptr, "ActivateInputDetector"},
128 {901, nullptr, "NotifyInputDetector"},
129 {1000, &IHidSystemServer::InitializeFirmwareUpdate, "InitializeFirmwareUpdate"},
130 {1001, nullptr, "GetFirmwareVersion"},
131 {1002, nullptr, "GetAvailableFirmwareVersion"},
132 {1003, nullptr, "IsFirmwareUpdateAvailable"},
133 {1004, nullptr, "CheckFirmwareUpdateRequired"},
134 {1005, nullptr, "StartFirmwareUpdate"},
135 {1006, nullptr, "AbortFirmwareUpdate"},
136 {1007, nullptr, "GetFirmwareUpdateState"},
137 {1008, nullptr, "ActivateAudioControl"},
138 {1009, nullptr, "AcquireAudioControlEventHandle"},
139 {1010, nullptr, "GetAudioControlStates"},
140 {1011, nullptr, "DeactivateAudioControl"},
141 {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
142 {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
143 {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
144 {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
145 {1100, nullptr, "GetHidbusSystemServiceObject"},
146 {1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
147 {1130, nullptr, "InitializeUsbFirmwareUpdate"},
148 {1131, nullptr, "FinalizeUsbFirmwareUpdate"},
149 {1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
150 {1133, nullptr, "StartUsbFirmwareUpdate"},
151 {1134, nullptr, "GetUsbFirmwareUpdateState"},
152 {1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"},
153 {1150, nullptr, "SetTouchScreenMagnification"},
154 {1151, nullptr, "GetTouchScreenFirmwareVersion"},
155 {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
156 {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
157 {1154, nullptr, "IsFirmwareAvailableForNotification"},
158 {1155, nullptr, "SetForceHandheldStyleVibration"},
159 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
160 {1157, nullptr, "CancelConnectionTrigger"},
161 {1200, nullptr, "IsButtonConfigSupported"},
162 {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
163 {1202, nullptr, "DeleteButtonConfig"},
164 {1203, nullptr, "DeleteButtonConfigEmbedded"},
165 {1204, nullptr, "SetButtonConfigEnabled"},
166 {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
167 {1206, nullptr, "IsButtonConfigEnabled"},
168 {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
169 {1208, nullptr, "SetButtonConfigEmbedded"},
170 {1209, nullptr, "SetButtonConfigFull"},
171 {1210, nullptr, "SetButtonConfigLeft"},
172 {1211, nullptr, "SetButtonConfigRight"},
173 {1212, nullptr, "GetButtonConfigEmbedded"},
174 {1213, nullptr, "GetButtonConfigFull"},
175 {1214, nullptr, "GetButtonConfigLeft"},
176 {1215, nullptr, "GetButtonConfigRight"},
177 {1250, nullptr, "IsCustomButtonConfigSupported"},
178 {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
179 {1252, nullptr, "IsDefaultButtonConfigFull"},
180 {1253, nullptr, "IsDefaultButtonConfigLeft"},
181 {1254, nullptr, "IsDefaultButtonConfigRight"},
182 {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
183 {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
184 {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
185 {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
186 {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
187 {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
188 {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
189 {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
190 {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
191 {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
192 {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
193 {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
194 {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
195 {1268, nullptr, "DeleteButtonConfigStorageFull"},
196 {1269, nullptr, "DeleteButtonConfigStorageLeft"},
197 {1270, nullptr, "DeleteButtonConfigStorageRight"},
198 {1271, nullptr, "IsUsingCustomButtonConfig"},
199 {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
200 {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
201 {1274, nullptr, "SetDefaultButtonConfig"},
202 {1275, nullptr, "SetAllDefaultButtonConfig"},
203 {1276, nullptr, "SetHidButtonConfigEmbedded"},
204 {1277, nullptr, "SetHidButtonConfigFull"},
205 {1278, nullptr, "SetHidButtonConfigLeft"},
206 {1279, nullptr, "SetHidButtonConfigRight"},
207 {1280, nullptr, "GetHidButtonConfigEmbedded"},
208 {1281, nullptr, "GetHidButtonConfigFull"},
209 {1282, nullptr, "GetHidButtonConfigLeft"},
210 {1283, nullptr, "GetHidButtonConfigRight"},
211 {1284, nullptr, "GetButtonConfigStorageEmbedded"},
212 {1285, nullptr, "GetButtonConfigStorageFull"},
213 {1286, nullptr, "GetButtonConfigStorageLeft"},
214 {1287, nullptr, "GetButtonConfigStorageRight"},
215 {1288, nullptr, "SetButtonConfigStorageEmbedded"},
216 {1289, nullptr, "SetButtonConfigStorageFull"},
217 {1290, nullptr, "DeleteButtonConfigStorageRight"},
218 {1291, nullptr, "DeleteButtonConfigStorageRight"},
219 };
220 // clang-format on
221
222 RegisterHandlers(functions);
223
224 joy_detach_event = service_context.CreateEvent("IHidSystemServer::JoyDetachEvent");
225 acquire_device_registered_event =
226 service_context.CreateEvent("IHidSystemServer::AcquireDeviceRegisteredEvent");
227 acquire_connection_trigger_timeout_event =
228 service_context.CreateEvent("IHidSystemServer::AcquireConnectionTriggerTimeoutEvent");
229 unique_pad_connection_event =
230 service_context.CreateEvent("IHidSystemServer::AcquireUniquePadConnectionEventHandle");
231}
232
233IHidSystemServer::~IHidSystemServer() {
234 service_context.CloseEvent(joy_detach_event);
235 service_context.CloseEvent(acquire_device_registered_event);
236 service_context.CloseEvent(acquire_connection_trigger_timeout_event);
237 service_context.CloseEvent(unique_pad_connection_event);
238};
239
240void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
241 LOG_WARNING(Service_HID, "called");
242
243 GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
244
245 IPC::ResponseBuilder rb{ctx, 2};
246 rb.Push(ResultSuccess);
247}
248
249void IHidSystemServer::EnableAssigningSingleOnSlSrPress(HLERequestContext& ctx) {
250 LOG_WARNING(Service_HID, "(STUBBED) called");
251
252 IPC::ResponseBuilder rb{ctx, 2};
253 rb.Push(ResultSuccess);
254}
255
256void IHidSystemServer::DisableAssigningSingleOnSlSrPress(HLERequestContext& ctx) {
257 LOG_WARNING(Service_HID, "(STUBBED) called");
258
259 IPC::ResponseBuilder rb{ctx, 2};
260 rb.Push(ResultSuccess);
261}
262
263void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) {
264 LOG_DEBUG(Service_HID, "(STUBBED) called"); // Spams a lot when controller applet is running
265
266 IPC::ResponseBuilder rb{ctx, 3};
267 rb.Push(ResultSuccess);
268 rb.PushEnum(system.HIDCore().GetLastActiveController());
269}
270
271void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) {
272 LOG_WARNING(Service_HID, "called");
273
274 GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
275
276 IPC::ResponseBuilder rb{ctx, 2};
277 rb.Push(ResultSuccess);
278}
279
280void IHidSystemServer::GetNpadFullKeyGripColor(HLERequestContext& ctx) {
281 IPC::RequestParser rp{ctx};
282 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
283
284 LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
285 npad_id_type); // Spams a lot when controller applet is running
286
287 Core::HID::NpadColor left_color{};
288 Core::HID::NpadColor right_color{};
289 // TODO: Get colors from Npad
290
291 IPC::ResponseBuilder rb{ctx, 4};
292 rb.Push(ResultSuccess);
293 rb.PushRaw(left_color);
294 rb.PushRaw(right_color);
295}
296
297void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) {
298 IPC::RequestParser rp{ctx};
299
300 LOG_INFO(Service_HID, "(STUBBED) called");
301
302 Core::HID::NpadStyleSet supported_styleset =
303 GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
304
305 IPC::ResponseBuilder rb{ctx, 3};
306 rb.Push(ResultSuccess);
307 rb.PushEnum(supported_styleset);
308}
309
310void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) {
311 IPC::RequestParser rp{ctx};
312
313 LOG_INFO(Service_HID, "(STUBBED) called");
314
315 Core::HID::NpadStyleSet supported_styleset =
316 GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
317
318 IPC::ResponseBuilder rb{ctx, 3};
319 rb.Push(ResultSuccess);
320 rb.PushEnum(supported_styleset);
321}
322
323void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
324 IPC::RequestParser rp{ctx};
325 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
326
327 LOG_DEBUG(Service_HID, "called, npad_id_type={}",
328 npad_id_type); // Spams a lot when controller applet is running
329
330 const NPad::AppletDetailedUiType detailed_ui_type =
331 GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
332
333 IPC::ResponseBuilder rb{ctx, 3};
334 rb.Push(ResultSuccess);
335 rb.PushRaw(detailed_ui_type);
336}
337
338void IHidSystemServer::GetNpadInterfaceType(HLERequestContext& ctx) {
339 IPC::RequestParser rp{ctx};
340 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
341
342 LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
343 npad_id_type); // Spams a lot when controller applet is running
344
345 IPC::ResponseBuilder rb{ctx, 3};
346 rb.Push(ResultSuccess);
347 rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth);
348}
349
350void IHidSystemServer::GetNpadLeftRightInterfaceType(HLERequestContext& ctx) {
351 IPC::RequestParser rp{ctx};
352 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
353
354 LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
355 npad_id_type); // Spams a lot when controller applet is running
356
357 IPC::ResponseBuilder rb{ctx, 4};
358 rb.Push(ResultSuccess);
359 rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth);
360 rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth);
361}
362
363void IHidSystemServer::HasBattery(HLERequestContext& ctx) {
364 IPC::RequestParser rp{ctx};
365 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
366
367 LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
368 npad_id_type); // Spams a lot when controller applet is running
369
370 IPC::ResponseBuilder rb{ctx, 3};
371 rb.Push(ResultSuccess);
372 rb.Push(false);
373}
374
375void IHidSystemServer::HasLeftRightBattery(HLERequestContext& ctx) {
376 IPC::RequestParser rp{ctx};
377 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
378
379 LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
380 npad_id_type); // Spams a lot when controller applet is running
381
382 struct LeftRightBattery {
383 bool left;
384 bool right;
385 };
386
387 LeftRightBattery left_right_battery{
388 .left = false,
389 .right = false,
390 };
391
392 IPC::ResponseBuilder rb{ctx, 3};
393 rb.Push(ResultSuccess);
394 rb.PushRaw(left_right_battery);
395}
396
397void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) {
398 IPC::RequestParser rp{ctx};
399 const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
400
401 LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
402 npad_id_type); // Spams a lot when controller applet is running
403
404 const std::vector<Core::HID::UniquePadId> unique_pads{};
405
406 if (!unique_pads.empty()) {
407 ctx.WriteBuffer(unique_pads);
408 }
409
410 IPC::ResponseBuilder rb{ctx, 3};
411 rb.Push(ResultSuccess);
412 rb.Push(static_cast<u32>(unique_pads.size()));
413}
414
415void IHidSystemServer::GetIrSensorState(HLERequestContext& ctx) {
416 IPC::RequestParser rp{ctx};
417
418 LOG_WARNING(Service_HID, "(STUBBED) called");
419
420 IPC::ResponseBuilder rb{ctx, 2};
421 rb.Push(ResultSuccess);
422}
423
424void IHidSystemServer::AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx) {
425 LOG_INFO(Service_AM, "(STUBBED) called");
426
427 IPC::ResponseBuilder rb{ctx, 2, 1};
428 rb.Push(ResultSuccess);
429 rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent());
430}
431
432void IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx) {
433 LOG_INFO(Service_HID, "(STUBBED) called");
434
435 IPC::ResponseBuilder rb{ctx, 2, 1};
436 rb.Push(ResultSuccess);
437 rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent());
438}
439
440void IHidSystemServer::GetRegisteredDevices(HLERequestContext& ctx) {
441 LOG_WARNING(Service_HID, "(STUBBED) called");
442
443 struct RegisterData {
444 std::array<u8, 0x68> data;
445 };
446 static_assert(sizeof(RegisterData) == 0x68, "RegisterData is an invalid size");
447 std::vector<RegisterData> registered_devices{};
448
449 if (!registered_devices.empty()) {
450 ctx.WriteBuffer(registered_devices);
451 }
452
453 IPC::ResponseBuilder rb{ctx, 4};
454 rb.Push(ResultSuccess);
455 rb.Push<u64>(registered_devices.size());
456}
457
458void IHidSystemServer::AcquireUniquePadConnectionEventHandle(HLERequestContext& ctx) {
459 LOG_WARNING(Service_HID, "(STUBBED) called");
460
461 IPC::ResponseBuilder rb{ctx, 2, 1};
462 rb.PushCopyObjects(unique_pad_connection_event->GetReadableEvent());
463 rb.Push(ResultSuccess);
464}
465
466void IHidSystemServer::GetUniquePadIds(HLERequestContext& ctx) {
467 LOG_WARNING(Service_HID, "(STUBBED) called");
468
469 IPC::ResponseBuilder rb{ctx, 4};
470 rb.Push(ResultSuccess);
471 rb.Push<u64>(0);
472}
473
474void IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
475 LOG_INFO(Service_AM, "called");
476
477 IPC::ResponseBuilder rb{ctx, 2, 1};
478 rb.Push(ResultSuccess);
479 rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
480}
481
482void IHidSystemServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
483 const bool is_enabled = false;
484
485 LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
486
487 IPC::ResponseBuilder rb{ctx, 3};
488 rb.Push(ResultSuccess);
489 rb.Push(is_enabled);
490}
491
492void IHidSystemServer::IsHandheldButtonPressedOnConsoleMode(HLERequestContext& ctx) {
493 const bool button_pressed = false;
494
495 LOG_DEBUG(Service_HID, "(STUBBED) called, is_enabled={}",
496 button_pressed); // Spams a lot when controller applet is open
497
498 IPC::ResponseBuilder rb{ctx, 3};
499 rb.Push(ResultSuccess);
500 rb.Push(button_pressed);
501}
502
503void IHidSystemServer::InitializeFirmwareUpdate(HLERequestContext& ctx) {
504 LOG_WARNING(Service_HID, "(STUBBED) called");
505
506 IPC::ResponseBuilder rb{ctx, 2};
507 rb.Push(ResultSuccess);
508}
509
510void IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx) {
511 LOG_WARNING(Service_HID, "(STUBBED) called");
512
513 IPC::ResponseBuilder rb{ctx, 2};
514 rb.Push(ResultSuccess);
515}
516
517void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
518 LOG_WARNING(Service_HID, "(STUBBED) called");
519
520 Core::HID::TouchScreenConfigurationForNx touchscreen_config{
521 .mode = Core::HID::TouchScreenModeForNx::Finger,
522 };
523
524 if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
525 touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
526 touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
527 }
528
529 IPC::ResponseBuilder rb{ctx, 6};
530 rb.Push(ResultSuccess);
531 rb.PushRaw(touchscreen_config);
532}
533
534std::shared_ptr<ResourceManager> IHidSystemServer::GetResourceManager() {
535 resource_manager->Initialize();
536 return resource_manager;
537}
538
539} // 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..822d5e5b9
--- /dev/null
+++ b/src/core/hle/service/hid/hid_system_server.h
@@ -0,0 +1,63 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Kernel {
14class KEvent;
15}
16
17namespace Service::HID {
18class ResourceManager;
19
20class IHidSystemServer final : public ServiceFramework<IHidSystemServer> {
21public:
22 explicit IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
23 ~IHidSystemServer() override;
24
25private:
26 void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx);
27 void EnableAssigningSingleOnSlSrPress(HLERequestContext& ctx);
28 void DisableAssigningSingleOnSlSrPress(HLERequestContext& ctx);
29 void GetLastActiveNpad(HLERequestContext& ctx);
30 void ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx);
31 void GetNpadFullKeyGripColor(HLERequestContext& ctx);
32 void GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx);
33 void SetSupportedNpadStyleSetAll(HLERequestContext& ctx);
34 void GetAppletDetailedUiType(HLERequestContext& ctx);
35 void GetNpadInterfaceType(HLERequestContext& ctx);
36 void GetNpadLeftRightInterfaceType(HLERequestContext& ctx);
37 void HasBattery(HLERequestContext& ctx);
38 void HasLeftRightBattery(HLERequestContext& ctx);
39 void GetUniquePadsFromNpad(HLERequestContext& ctx);
40 void GetIrSensorState(HLERequestContext& ctx);
41 void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx);
42 void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx);
43 void GetRegisteredDevices(HLERequestContext& ctx);
44 void AcquireUniquePadConnectionEventHandle(HLERequestContext& ctx);
45 void GetUniquePadIds(HLERequestContext& ctx);
46 void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx);
47 void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
48 void IsHandheldButtonPressedOnConsoleMode(HLERequestContext& ctx);
49 void InitializeFirmwareUpdate(HLERequestContext& ctx);
50 void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx);
51 void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx);
52
53 std::shared_ptr<ResourceManager> GetResourceManager();
54
55 Kernel::KEvent* acquire_connection_trigger_timeout_event;
56 Kernel::KEvent* acquire_device_registered_event;
57 Kernel::KEvent* joy_detach_event;
58 Kernel::KEvent* unique_pad_connection_event;
59 KernelHelpers::ServiceContext service_context;
60 std::shared_ptr<ResourceManager> resource_manager;
61};
62
63} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid_util.h b/src/core/hle/service/hid/hid_util.h
new file mode 100644
index 000000000..b87cc10e3
--- /dev/null
+++ b/src/core/hle/service/hid/hid_util.h
@@ -0,0 +1,146 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hid/hid_types.h"
7#include "core/hle/service/hid/errors.h"
8
9namespace Service::HID {
10
11constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) {
12 switch (npad_id) {
13 case Core::HID::NpadIdType::Player1:
14 case Core::HID::NpadIdType::Player2:
15 case Core::HID::NpadIdType::Player3:
16 case Core::HID::NpadIdType::Player4:
17 case Core::HID::NpadIdType::Player5:
18 case Core::HID::NpadIdType::Player6:
19 case Core::HID::NpadIdType::Player7:
20 case Core::HID::NpadIdType::Player8:
21 case Core::HID::NpadIdType::Other:
22 case Core::HID::NpadIdType::Handheld:
23 return true;
24 default:
25 return false;
26 }
27}
28
29constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) {
30 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id));
31 const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
32
33 if (!npad_id) {
34 return InvalidNpadId;
35 }
36 if (!device_index) {
37 return NpadDeviceIndexOutOfRange;
38 }
39
40 return ResultSuccess;
41}
42
43constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) {
44 switch (handle.npad_type) {
45 case Core::HID::NpadStyleIndex::ProController:
46 case Core::HID::NpadStyleIndex::Handheld:
47 case Core::HID::NpadStyleIndex::JoyconDual:
48 case Core::HID::NpadStyleIndex::JoyconLeft:
49 case Core::HID::NpadStyleIndex::JoyconRight:
50 case Core::HID::NpadStyleIndex::GameCube:
51 case Core::HID::NpadStyleIndex::N64:
52 case Core::HID::NpadStyleIndex::SystemExt:
53 case Core::HID::NpadStyleIndex::System:
54 // These support vibration
55 break;
56 default:
57 return VibrationInvalidStyleIndex;
58 }
59
60 if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) {
61 return VibrationInvalidNpadId;
62 }
63
64 if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) {
65 return VibrationDeviceIndexOutOfRange;
66 }
67
68 return ResultSuccess;
69}
70
71/// Converts a Core::HID::NpadIdType to an array index.
72constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) {
73 switch (npad_id_type) {
74 case Core::HID::NpadIdType::Player1:
75 return 0;
76 case Core::HID::NpadIdType::Player2:
77 return 1;
78 case Core::HID::NpadIdType::Player3:
79 return 2;
80 case Core::HID::NpadIdType::Player4:
81 return 3;
82 case Core::HID::NpadIdType::Player5:
83 return 4;
84 case Core::HID::NpadIdType::Player6:
85 return 5;
86 case Core::HID::NpadIdType::Player7:
87 return 6;
88 case Core::HID::NpadIdType::Player8:
89 return 7;
90 case Core::HID::NpadIdType::Handheld:
91 return 8;
92 case Core::HID::NpadIdType::Other:
93 return 9;
94 default:
95 return 8;
96 }
97}
98
99/// Converts an array index to a Core::HID::NpadIdType
100constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) {
101 switch (index) {
102 case 0:
103 return Core::HID::NpadIdType::Player1;
104 case 1:
105 return Core::HID::NpadIdType::Player2;
106 case 2:
107 return Core::HID::NpadIdType::Player3;
108 case 3:
109 return Core::HID::NpadIdType::Player4;
110 case 4:
111 return Core::HID::NpadIdType::Player5;
112 case 5:
113 return Core::HID::NpadIdType::Player6;
114 case 6:
115 return Core::HID::NpadIdType::Player7;
116 case 7:
117 return Core::HID::NpadIdType::Player8;
118 case 8:
119 return Core::HID::NpadIdType::Handheld;
120 case 9:
121 return Core::HID::NpadIdType::Other;
122 default:
123 return Core::HID::NpadIdType::Invalid;
124 }
125}
126
127constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) {
128 switch (index) {
129 case 0:
130 return Core::HID::NpadStyleSet::Fullkey;
131 case 1:
132 return Core::HID::NpadStyleSet::Handheld;
133 case 2:
134 return Core::HID::NpadStyleSet::JoyDual;
135 case 3:
136 return Core::HID::NpadStyleSet::JoyLeft;
137 case 4:
138 return Core::HID::NpadStyleSet::JoyRight;
139 case 5:
140 return Core::HID::NpadStyleSet::Palma;
141 default:
142 return Core::HID::NpadStyleSet::None;
143 }
144}
145
146} // namespace Service::HID
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index 221c33b86..39b9a4474 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -12,6 +12,7 @@
12#include "core/hle/kernel/k_transfer_memory.h" 12#include "core/hle/kernel/k_transfer_memory.h"
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/service/hid/errors.h" 14#include "core/hle/service/hid/errors.h"
15#include "core/hle/service/hid/hid_util.h"
15#include "core/hle/service/hid/irs.h" 16#include "core/hle/service/hid/irs.h"
16#include "core/hle/service/hid/irsensor/clustering_processor.h" 17#include "core/hle/service/hid/irsensor/clustering_processor.h"
17#include "core/hle/service/hid/irsensor/image_transfer_processor.h" 18#include "core/hle/service/hid/irsensor/image_transfer_processor.h"
@@ -138,7 +139,7 @@ void IRS::RunMomentProcessor(HLERequestContext& ctx) {
138 139
139 if (result.IsSuccess()) { 140 if (result.IsSuccess()) {
140 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); 141 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
141 MakeProcessor<MomentProcessor>(parameters.camera_handle, device); 142 MakeProcessorWithCoreContext<MomentProcessor>(parameters.camera_handle, device);
142 auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle); 143 auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle);
143 image_transfer_processor.SetConfig(parameters.processor_config); 144 image_transfer_processor.SetConfig(parameters.processor_config);
144 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, 145 npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
@@ -320,7 +321,7 @@ void IRS::GetNpadIrCameraHandle(HLERequestContext& ctx) {
320 } 321 }
321 322
322 Core::IrSensor::IrCameraHandle camera_handle{ 323 Core::IrSensor::IrCameraHandle camera_handle{
323 .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)), 324 .npad_id = static_cast<u8>(HID::NpadIdTypeToIndex(npad_id)),
324 .npad_type = Core::HID::NpadStyleIndex::None, 325 .npad_type = Core::HID::NpadStyleIndex::None,
325 }; 326 };
326 327
@@ -545,7 +546,7 @@ void IRS::ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx) {
545 546
546Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const { 547Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const {
547 if (camera_handle.npad_id > 548 if (camera_handle.npad_id >
548 static_cast<u8>(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) { 549 static_cast<u8>(HID::NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) {
549 return InvalidIrCameraHandle; 550 return InvalidIrCameraHandle;
550 } 551 }
551 if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) { 552 if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) {
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 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/core.h"
6#include "core/hid/hid_types.h" 7#include "core/hid/hid_types.h"
7#include "core/hid/irs_types.h" 8#include "core/hid/irs_types.h"
8#include "core/hle/service/hid/irsensor/processor_base.h" 9#include "core/hle/service/hid/irsensor/processor_base.h"
9#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
10 11
11namespace Core {
12class System;
13}
14
15namespace Core::HID { 12namespace Core::HID {
16class EmulatedController; 13class EmulatedController;
17} // namespace Core::HID 14} // 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 @@
3 3
4#include <queue> 4#include <queue>
5 5
6#include "core/core.h"
7#include "core/core_timing.h"
6#include "core/hid/emulated_controller.h" 8#include "core/hid/emulated_controller.h"
7#include "core/hid/hid_core.h" 9#include "core/hid/hid_core.h"
8#include "core/hle/service/hid/irsensor/clustering_processor.h" 10#include "core/hle/service/hid/irsensor/clustering_processor.h"
9 11
10namespace Service::IRS { 12namespace Service::IRS {
11ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_, 13ClusteringProcessor::ClusteringProcessor(Core::System& system_,
12 Core::IrSensor::DeviceFormat& device_format, 14 Core::IrSensor::DeviceFormat& device_format,
13 std::size_t npad_index) 15 std::size_t npad_index)
14 : device{device_format} { 16 : device{device_format}, system{system_} {
15 npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); 17 npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
16 18
17 device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; 19 device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor;
18 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; 20 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
@@ -48,7 +50,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
48 } 50 }
49 51
50 next_state = {}; 52 next_state = {};
51 const auto camera_data = npad_device->GetCamera(); 53 const auto& camera_data = npad_device->GetCamera();
52 auto filtered_image = camera_data.data; 54 auto filtered_image = camera_data.data;
53 55
54 RemoveLowIntensityData(filtered_image); 56 RemoveLowIntensityData(filtered_image);
@@ -83,7 +85,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty
83 } 85 }
84 86
85 next_state.sampling_number = camera_data.sample; 87 next_state.sampling_number = camera_data.sample;
86 next_state.timestamp = next_state.timestamp + 131; 88 next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
87 next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; 89 next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
88 shared_memory->clustering_lifo.WriteNextEntry(next_state); 90 shared_memory->clustering_lifo.WriteNextEntry(next_state);
89 91
@@ -202,14 +204,14 @@ ClusteringProcessor::ClusteringData ClusteringProcessor::MergeCluster(
202} 204}
203 205
204u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const { 206u8 ClusteringProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
205 if ((y * width) + x > data.size()) { 207 if ((y * width) + x >= data.size()) {
206 return 0; 208 return 0;
207 } 209 }
208 return data[(y * width) + x]; 210 return data[(y * width) + x];
209} 211}
210 212
211void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) { 213void ClusteringProcessor::SetPixel(std::vector<u8>& data, std::size_t x, std::size_t y, u8 value) {
212 if ((y * width) + x > data.size()) { 214 if ((y * width) + x >= data.size()) {
213 return; 215 return;
214 } 216 }
215 data[(y * width) + x] = value; 217 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 @@
8#include "core/hle/service/hid/irs_ring_lifo.h" 8#include "core/hle/service/hid/irs_ring_lifo.h"
9#include "core/hle/service/hid/irsensor/processor_base.h" 9#include "core/hle/service/hid/irsensor/processor_base.h"
10 10
11namespace Core {
12class System;
13}
14
11namespace Core::HID { 15namespace Core::HID {
12class EmulatedController; 16class EmulatedController;
13} // namespace Core::HID 17} // namespace Core::HID
@@ -15,8 +19,7 @@ class EmulatedController;
15namespace Service::IRS { 19namespace Service::IRS {
16class ClusteringProcessor final : public ProcessorBase { 20class ClusteringProcessor final : public ProcessorBase {
17public: 21public:
18 explicit ClusteringProcessor(Core::HID::HIDCore& hid_core_, 22 explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
19 Core::IrSensor::DeviceFormat& device_format,
20 std::size_t npad_index); 23 std::size_t npad_index);
21 ~ClusteringProcessor() override; 24 ~ClusteringProcessor() override;
22 25
@@ -106,5 +109,7 @@ private:
106 Core::IrSensor::DeviceFormat& device; 109 Core::IrSensor::DeviceFormat& device;
107 Core::HID::EmulatedController* npad_device; 110 Core::HID::EmulatedController* npad_device;
108 int callback_key{}; 111 int callback_key{};
112
113 Core::System& system;
109}; 114};
110} // namespace Service::IRS 115} // 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
49 return; 49 return;
50 } 50 }
51 51
52 const auto camera_data = npad_device->GetCamera(); 52 const auto& camera_data = npad_device->GetCamera();
53 53
54 // This indicates how much ambient light is present 54 // This indicates how much ambient light is present
55 processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; 55 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 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include "core/core.h"
5#include "core/core_timing.h"
6#include "core/hid/emulated_controller.h"
7#include "core/hid/hid_core.h"
4#include "core/hle/service/hid/irsensor/moment_processor.h" 8#include "core/hle/service/hid/irsensor/moment_processor.h"
5 9
6namespace Service::IRS { 10namespace Service::IRS {
7MomentProcessor::MomentProcessor(Core::IrSensor::DeviceFormat& device_format) 11static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30;
8 : device(device_format) { 12static constexpr std::size_t ImageWidth = 40;
13static constexpr std::size_t ImageHeight = 30;
14
15MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
16 std::size_t npad_index)
17 : device(device_format), system{system_} {
18 npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
19
9 device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; 20 device.mode = Core::IrSensor::IrSensorMode::MomentProcessor;
10 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; 21 device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
11 device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; 22 device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped;
23
24 shared_memory = std::construct_at(
25 reinterpret_cast<MomentSharedMemory*>(&device_format.state.processor_raw_data));
26
27 Core::HID::ControllerUpdateCallback engine_callback{
28 .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); },
29 .is_npad_service = true,
30 };
31 callback_key = npad_device->SetCallback(engine_callback);
12} 32}
13 33
14MomentProcessor::~MomentProcessor() = default; 34MomentProcessor::~MomentProcessor() {
35 npad_device->DeleteCallback(callback_key);
36};
15 37
16void MomentProcessor::StartProcessor() {} 38void MomentProcessor::StartProcessor() {
39 device.camera_status = Core::IrSensor::IrCameraStatus::Available;
40 device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready;
41}
17 42
18void MomentProcessor::SuspendProcessor() {} 43void MomentProcessor::SuspendProcessor() {}
19 44
20void MomentProcessor::StopProcessor() {} 45void MomentProcessor::StopProcessor() {}
21 46
47void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) {
48 if (type != Core::HID::ControllerTriggerType::IrSensor) {
49 return;
50 }
51
52 next_state = {};
53 const auto& camera_data = npad_device->GetCamera();
54
55 const auto window_width = static_cast<std::size_t>(current_config.window_of_interest.width);
56 const auto window_height = static_cast<std::size_t>(current_config.window_of_interest.height);
57 const auto window_start_x = static_cast<std::size_t>(current_config.window_of_interest.x);
58 const auto window_start_y = static_cast<std::size_t>(current_config.window_of_interest.y);
59
60 const std::size_t block_width = window_width / Columns;
61 const std::size_t block_height = window_height / Rows;
62
63 for (std::size_t row = 0; row < Rows; row++) {
64 for (std::size_t column = 0; column < Columns; column++) {
65 const size_t x_pos = (column * block_width) + window_start_x;
66 const size_t y_pos = (row * block_height) + window_start_y;
67 auto& statistic = next_state.statistic[column + (row * Columns)];
68 statistic = GetStatistic(camera_data.data, x_pos, y_pos, block_width, block_height);
69 }
70 }
71
72 next_state.sampling_number = camera_data.sample;
73 next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count();
74 next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
75 shared_memory->moment_lifo.WriteNextEntry(next_state);
76
77 if (!IsProcessorActive()) {
78 StartProcessor();
79 }
80}
81
82u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
83 if ((y * ImageWidth) + x >= data.size()) {
84 return 0;
85 }
86 return data[(y * ImageWidth) + x];
87}
88
89MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector<u8>& data,
90 std::size_t start_x,
91 std::size_t start_y,
92 std::size_t width,
93 std::size_t height) const {
94 // The actual implementation is always 320x240
95 static constexpr std::size_t RealWidth = 320;
96 static constexpr std::size_t RealHeight = 240;
97 static constexpr std::size_t Threshold = 30;
98 MomentStatistic statistic{};
99 std::size_t active_points{};
100
101 // Sum all data points on the block that meet with the threshold
102 for (std::size_t y = 0; y < width; y++) {
103 for (std::size_t x = 0; x < height; x++) {
104 const size_t x_pos = x + start_x;
105 const size_t y_pos = y + start_y;
106 const auto pixel =
107 GetPixel(data, x_pos * ImageWidth / RealWidth, y_pos * ImageHeight / RealHeight);
108
109 if (pixel < Threshold) {
110 continue;
111 }
112
113 statistic.average_intensity += pixel;
114
115 statistic.centroid.x += static_cast<float>(x_pos);
116 statistic.centroid.y += static_cast<float>(y_pos);
117
118 active_points++;
119 }
120 }
121
122 // Return an empty field if no points were available
123 if (active_points == 0) {
124 return {};
125 }
126
127 // Finally calculate the actual centroid and average intensity
128 statistic.centroid.x /= static_cast<float>(active_points);
129 statistic.centroid.y /= static_cast<float>(active_points);
130 statistic.average_intensity /= static_cast<f32>(width * height);
131
132 return statistic;
133}
134
22void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) { 135void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) {
23 current_config.camera_config.exposure_time = config.camera_config.exposure_time; 136 current_config.camera_config.exposure_time = config.camera_config.exposure_time;
24 current_config.camera_config.gain = config.camera_config.gain; 137 current_config.camera_config.gain = config.camera_config.gain;
@@ -29,6 +142,8 @@ void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig conf
29 current_config.preprocess = 142 current_config.preprocess =
30 static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); 143 static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
31 current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; 144 current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
145
146 npad_device->SetCameraFormat(format);
32} 147}
33 148
34} // namespace Service::IRS 149} // 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 @@
6#include "common/bit_field.h" 6#include "common/bit_field.h"
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/hid/irs_types.h" 8#include "core/hid/irs_types.h"
9#include "core/hle/service/hid/irs_ring_lifo.h"
9#include "core/hle/service/hid/irsensor/processor_base.h" 10#include "core/hle/service/hid/irsensor/processor_base.h"
10 11
12namespace Core {
13class System;
14}
15
16namespace Core::HID {
17class EmulatedController;
18} // namespace Core::HID
19
11namespace Service::IRS { 20namespace Service::IRS {
12class MomentProcessor final : public ProcessorBase { 21class MomentProcessor final : public ProcessorBase {
13public: 22public:
14 explicit MomentProcessor(Core::IrSensor::DeviceFormat& device_format); 23 explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
24 std::size_t npad_index);
15 ~MomentProcessor() override; 25 ~MomentProcessor() override;
16 26
17 // Called when the processor is initialized 27 // Called when the processor is initialized
@@ -27,6 +37,9 @@ public:
27 void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); 37 void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config);
28 38
29private: 39private:
40 static constexpr std::size_t Columns = 8;
41 static constexpr std::size_t Rows = 6;
42
30 // This is nn::irsensor::MomentProcessorConfig 43 // This is nn::irsensor::MomentProcessorConfig
31 struct MomentProcessorConfig { 44 struct MomentProcessorConfig {
32 Core::IrSensor::CameraConfig camera_config; 45 Core::IrSensor::CameraConfig camera_config;
@@ -50,12 +63,29 @@ private:
50 u64 timestamp; 63 u64 timestamp;
51 Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; 64 Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level;
52 INSERT_PADDING_BYTES(4); 65 INSERT_PADDING_BYTES(4);
53 std::array<MomentStatistic, 0x30> stadistic; 66 std::array<MomentStatistic, Columns * Rows> statistic;
54 }; 67 };
55 static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); 68 static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size");
56 69
70 struct MomentSharedMemory {
71 Service::IRS::Lifo<MomentProcessorState, 6> moment_lifo;
72 };
73 static_assert(sizeof(MomentSharedMemory) == 0xE20, "MomentSharedMemory is an invalid size");
74
75 void OnControllerUpdate(Core::HID::ControllerTriggerType type);
76 u8 GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const;
77 MomentStatistic GetStatistic(const std::vector<u8>& data, std::size_t start_x,
78 std::size_t start_y, std::size_t width, std::size_t height) const;
79
80 MomentSharedMemory* shared_memory = nullptr;
81 MomentProcessorState next_state{};
82
57 MomentProcessorConfig current_config{}; 83 MomentProcessorConfig current_config{};
58 Core::IrSensor::DeviceFormat& device; 84 Core::IrSensor::DeviceFormat& device;
85 Core::HID::EmulatedController* npad_device;
86 int callback_key{};
87
88 Core::System& system;
59}; 89};
60 90
61} // namespace Service::IRS 91} // 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..e76d4eea9
--- /dev/null
+++ b/src/core/hle/service/hid/resource_manager.cpp
@@ -0,0 +1,241 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "common/logging/log.h"
5#include "core/core.h"
6#include "core/core_timing.h"
7#include "core/hid/hid_core.h"
8#include "core/hle/kernel/k_shared_memory.h"
9#include "core/hle/service/hid/resource_manager.h"
10#include "core/hle/service/ipc_helpers.h"
11
12#include "core/hle/service/hid/controllers/console_six_axis.h"
13#include "core/hle/service/hid/controllers/debug_pad.h"
14#include "core/hle/service/hid/controllers/gesture.h"
15#include "core/hle/service/hid/controllers/keyboard.h"
16#include "core/hle/service/hid/controllers/mouse.h"
17#include "core/hle/service/hid/controllers/npad.h"
18#include "core/hle/service/hid/controllers/palma.h"
19#include "core/hle/service/hid/controllers/seven_six_axis.h"
20#include "core/hle/service/hid/controllers/six_axis.h"
21#include "core/hle/service/hid/controllers/stubbed.h"
22#include "core/hle/service/hid/controllers/touchscreen.h"
23#include "core/hle/service/hid/controllers/xpad.h"
24
25namespace Service::HID {
26
27// Updating period for each HID device.
28// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
29// Correct npad_update_ns is 4ms this is overclocked to lower input lag
30constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
31constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
32constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
33constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
34
35ResourceManager::ResourceManager(Core::System& system_)
36 : system{system_}, service_context{system_, "hid"} {}
37
38ResourceManager::~ResourceManager() = default;
39
40void ResourceManager::Initialize() {
41 if (is_initialized) {
42 return;
43 }
44
45 u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
46 debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory);
47 mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory);
48 debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory);
49 keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory);
50 unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory);
51 npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context);
52 gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory);
53 touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory);
54 xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory);
55
56 palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context);
57
58 home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory);
59 sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory);
60 capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory);
61
62 six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
63 console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory);
64 seven_six_axis = std::make_shared<SevenSixAxis>(system);
65
66 home_button->SetCommonHeaderOffset(0x4C00);
67 sleep_button->SetCommonHeaderOffset(0x4E00);
68 capture_button->SetCommonHeaderOffset(0x5000);
69 unique_pad->SetCommonHeaderOffset(0x5A00);
70 debug_mouse->SetCommonHeaderOffset(0x3DC00);
71
72 // Homebrew doesn't try to activate some controllers, so we activate them by default
73 npad->Activate();
74 six_axis->Activate();
75 touch_screen->Activate();
76
77 system.HIDCore().ReloadInputDevices();
78 is_initialized = true;
79}
80std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const {
81 return capture_button;
82}
83
84std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const {
85 return console_six_axis;
86}
87
88std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const {
89 return debug_mouse;
90}
91
92std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
93 return debug_pad;
94}
95
96std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
97 return gesture;
98}
99
100std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const {
101 return home_button;
102}
103
104std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const {
105 return keyboard;
106}
107
108std::shared_ptr<Mouse> ResourceManager::GetMouse() const {
109 return mouse;
110}
111
112std::shared_ptr<NPad> ResourceManager::GetNpad() const {
113 return npad;
114}
115
116std::shared_ptr<Palma> ResourceManager::GetPalma() const {
117 return palma;
118}
119
120std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const {
121 return seven_six_axis;
122}
123
124std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const {
125 return six_axis;
126}
127
128std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const {
129 return sleep_button;
130}
131
132std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const {
133 return touch_screen;
134}
135
136std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const {
137 return unique_pad;
138}
139
140void ResourceManager::UpdateControllers(std::uintptr_t user_data,
141 std::chrono::nanoseconds ns_late) {
142 auto& core_timing = system.CoreTiming();
143 debug_pad->OnUpdate(core_timing);
144 unique_pad->OnUpdate(core_timing);
145 gesture->OnUpdate(core_timing);
146 touch_screen->OnUpdate(core_timing);
147 palma->OnUpdate(core_timing);
148 home_button->OnUpdate(core_timing);
149 sleep_button->OnUpdate(core_timing);
150 capture_button->OnUpdate(core_timing);
151 xpad->OnUpdate(core_timing);
152}
153
154void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
155 auto& core_timing = system.CoreTiming();
156 npad->OnUpdate(core_timing);
157}
158
159void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
160 std::chrono::nanoseconds ns_late) {
161 auto& core_timing = system.CoreTiming();
162 mouse->OnUpdate(core_timing);
163 debug_mouse->OnUpdate(core_timing);
164 keyboard->OnUpdate(core_timing);
165}
166
167void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
168 auto& core_timing = system.CoreTiming();
169 six_axis->OnUpdate(core_timing);
170 seven_six_axis->OnUpdate(core_timing);
171 console_six_axis->OnUpdate(core_timing);
172}
173
174IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource)
175 : ServiceFramework{system_, "IAppletResource"} {
176 static const FunctionInfo functions[] = {
177 {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
178 };
179 RegisterHandlers(functions);
180
181 resource->Initialize();
182
183 // Register update callbacks
184 npad_update_event = Core::Timing::CreateEvent(
185 "HID::UpdatePadCallback",
186 [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
187 -> std::optional<std::chrono::nanoseconds> {
188 const auto guard = LockService();
189 resource->UpdateNpad(user_data, ns_late);
190 return std::nullopt;
191 });
192 default_update_event = Core::Timing::CreateEvent(
193 "HID::UpdateDefaultCallback",
194 [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
195 -> std::optional<std::chrono::nanoseconds> {
196 const auto guard = LockService();
197 resource->UpdateControllers(user_data, ns_late);
198 return std::nullopt;
199 });
200 mouse_keyboard_update_event = Core::Timing::CreateEvent(
201 "HID::UpdateMouseKeyboardCallback",
202 [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
203 -> std::optional<std::chrono::nanoseconds> {
204 const auto guard = LockService();
205 resource->UpdateMouseKeyboard(user_data, ns_late);
206 return std::nullopt;
207 });
208 motion_update_event = Core::Timing::CreateEvent(
209 "HID::UpdateMotionCallback",
210 [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
211 -> std::optional<std::chrono::nanoseconds> {
212 const auto guard = LockService();
213 resource->UpdateMotion(user_data, ns_late);
214 return std::nullopt;
215 });
216
217 system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
218 system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
219 default_update_event);
220 system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
221 mouse_keyboard_update_event);
222 system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
223 motion_update_event);
224}
225
226IAppletResource::~IAppletResource() {
227 system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
228 system.CoreTiming().UnscheduleEvent(default_update_event, 0);
229 system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
230 system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
231}
232
233void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
234 LOG_DEBUG(Service_HID, "called");
235
236 IPC::ResponseBuilder rb{ctx, 2, 1};
237 rb.Push(ResultSuccess);
238 rb.PushCopyObjects(&system.Kernel().GetHidSharedMem());
239}
240
241} // 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..2b6a9b5e6
--- /dev/null
+++ b/src/core/hle/service/hid/resource_manager.h
@@ -0,0 +1,111 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h"
8
9namespace Core::Timing {
10struct EventType;
11}
12
13namespace Service::HID {
14class Controller_Stubbed;
15class ConsoleSixAxis;
16class DebugPad;
17class Gesture;
18class Keyboard;
19class Mouse;
20class NPad;
21class Palma;
22class SevenSixAxis;
23class SixAxis;
24class TouchScreen;
25class XPad;
26
27using CaptureButton = Controller_Stubbed;
28using DebugMouse = Controller_Stubbed;
29using HomeButton = Controller_Stubbed;
30using SleepButton = Controller_Stubbed;
31using UniquePad = Controller_Stubbed;
32
33class ResourceManager {
34
35public:
36 explicit ResourceManager(Core::System& system_);
37 ~ResourceManager();
38
39 void Initialize();
40
41 std::shared_ptr<CaptureButton> GetCaptureButton() const;
42 std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
43 std::shared_ptr<DebugMouse> GetDebugMouse() const;
44 std::shared_ptr<DebugPad> GetDebugPad() const;
45 std::shared_ptr<Gesture> GetGesture() const;
46 std::shared_ptr<HomeButton> GetHomeButton() const;
47 std::shared_ptr<Keyboard> GetKeyboard() const;
48 std::shared_ptr<Mouse> GetMouse() const;
49 std::shared_ptr<NPad> GetNpad() const;
50 std::shared_ptr<Palma> GetPalma() const;
51 std::shared_ptr<SevenSixAxis> GetSevenSixAxis() const;
52 std::shared_ptr<SixAxis> GetSixAxis() const;
53 std::shared_ptr<SleepButton> GetSleepButton() const;
54 std::shared_ptr<TouchScreen> GetTouchScreen() const;
55 std::shared_ptr<UniquePad> GetUniquePad() const;
56
57 void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
58 void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
59 void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
60 void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
61
62private:
63 bool is_initialized{false};
64
65 std::shared_ptr<CaptureButton> capture_button = nullptr;
66 std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
67 std::shared_ptr<DebugMouse> debug_mouse = nullptr;
68 std::shared_ptr<DebugPad> debug_pad = nullptr;
69 std::shared_ptr<Gesture> gesture = nullptr;
70 std::shared_ptr<HomeButton> home_button = nullptr;
71 std::shared_ptr<Keyboard> keyboard = nullptr;
72 std::shared_ptr<Mouse> mouse = nullptr;
73 std::shared_ptr<NPad> npad = nullptr;
74 std::shared_ptr<Palma> palma = nullptr;
75 std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr;
76 std::shared_ptr<SixAxis> six_axis = nullptr;
77 std::shared_ptr<SleepButton> sleep_button = nullptr;
78 std::shared_ptr<TouchScreen> touch_screen = nullptr;
79 std::shared_ptr<UniquePad> unique_pad = nullptr;
80 std::shared_ptr<XPad> xpad = nullptr;
81
82 // TODO: Create these resources
83 // std::shared_ptr<AudioControl> audio_control = nullptr;
84 // std::shared_ptr<ButtonConfig> button_config = nullptr;
85 // std::shared_ptr<Config> config = nullptr;
86 // std::shared_ptr<Connection> connection = nullptr;
87 // std::shared_ptr<CustomConfig> custom_config = nullptr;
88 // std::shared_ptr<Digitizer> digitizer = nullptr;
89 // std::shared_ptr<Hdls> hdls = nullptr;
90 // std::shared_ptr<PlayReport> play_report = nullptr;
91 // std::shared_ptr<Rail> rail = nullptr;
92
93 Core::System& system;
94 KernelHelpers::ServiceContext service_context;
95};
96
97class IAppletResource final : public ServiceFramework<IAppletResource> {
98public:
99 explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource);
100 ~IAppletResource() override;
101
102private:
103 void GetSharedMemoryHandle(HLERequestContext& ctx);
104
105 std::shared_ptr<Core::Timing::EventType> npad_update_event;
106 std::shared_ptr<Core::Timing::EventType> default_update_event;
107 std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
108 std::shared_ptr<Core::Timing::EventType> motion_update_event;
109};
110
111} // 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 {
32 } 32 }
33 33
34 std::size_t GetPreviousEntryIndex() const { 34 std::size_t GetPreviousEntryIndex() const {
35 return static_cast<size_t>((buffer_tail + total_buffer_count - 1) % total_buffer_count); 35 return static_cast<size_t>((buffer_tail + max_buffer_size - 1) % max_buffer_size);
36 } 36 }
37 37
38 std::size_t GetNextEntryIndex() const { 38 std::size_t GetNextEntryIndex() const {
39 return static_cast<size_t>((buffer_tail + 1) % total_buffer_count); 39 return static_cast<size_t>((buffer_tail + 1) % max_buffer_size);
40 } 40 }
41 41
42 void WriteNextEntry(const State& new_state) { 42 void WriteNextEntry(const State& new_state) {
43 if (buffer_count < total_buffer_count - 1) { 43 if (buffer_count < static_cast<s64>(max_buffer_size) - 1) {
44 buffer_count++; 44 buffer_count++;
45 } 45 }
46 buffer_tail = GetNextEntryIndex(); 46 buffer_tail = GetNextEntryIndex();
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index 7927f8264..961f89a14 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -115,12 +115,20 @@ public:
115 {400, nullptr, "InitializeSystem"}, 115 {400, nullptr, "InitializeSystem"},
116 {401, nullptr, "FinalizeSystem"}, 116 {401, nullptr, "FinalizeSystem"},
117 {402, nullptr, "SetOperationMode"}, 117 {402, nullptr, "SetOperationMode"},
118 {403, nullptr, "InitializeSystem2"}, 118 {403, &ISystemLocalCommunicationService::InitializeSystem2, "InitializeSystem2"},
119 }; 119 };
120 // clang-format on 120 // clang-format on
121 121
122 RegisterHandlers(functions); 122 RegisterHandlers(functions);
123 } 123 }
124
125private:
126 void InitializeSystem2(HLERequestContext& ctx) {
127 LOG_WARNING(Service_LDN, "(STUBBED) called");
128
129 IPC::ResponseBuilder rb{ctx, 2};
130 rb.Push(ResultSuccess);
131 }
124}; 132};
125 133
126class IUserLocalCommunicationService final 134class IUserLocalCommunicationService final
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:
286 rb.Push(ResultSuccess); 286 rb.Push(ResultSuccess);
287 } 287 }
288 288
289 bool ValidateRegionForMap(Kernel::KPageTable& page_table, VAddr start, std::size_t size) const { 289 bool ValidateRegionForMap(Kernel::KProcessPageTable& page_table, VAddr start,
290 std::size_t size) const {
290 const std::size_t padding_size{page_table.GetNumGuardPages() * Kernel::PageSize}; 291 const std::size_t padding_size{page_table.GetNumGuardPages() * Kernel::PageSize};
291 const auto start_info{page_table.QueryInfo(start - 1)}; 292
293 Kernel::KMemoryInfo start_info;
294 Kernel::Svc::PageInfo page_info;
295 R_ASSERT(
296 page_table.QueryInfo(std::addressof(start_info), std::addressof(page_info), start - 1));
292 297
293 if (start_info.GetState() != Kernel::KMemoryState::Free) { 298 if (start_info.GetState() != Kernel::KMemoryState::Free) {
294 return {}; 299 return {};
@@ -298,7 +303,9 @@ public:
298 return {}; 303 return {};
299 } 304 }
300 305
301 const auto end_info{page_table.QueryInfo(start + size)}; 306 Kernel::KMemoryInfo end_info;
307 R_ASSERT(page_table.QueryInfo(std::addressof(end_info), std::addressof(page_info),
308 start + size));
302 309
303 if (end_info.GetState() != Kernel::KMemoryState::Free) { 310 if (end_info.GetState() != Kernel::KMemoryState::Free) {
304 return {}; 311 return {};
@@ -307,7 +314,7 @@ public:
307 return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize()); 314 return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize());
308 } 315 }
309 316
310 Result GetAvailableMapRegion(Kernel::KPageTable& page_table, u64 size, VAddr& out_addr) { 317 Result GetAvailableMapRegion(Kernel::KProcessPageTable& page_table, u64 size, VAddr& out_addr) {
311 size = Common::AlignUp(size, Kernel::PageSize); 318 size = Common::AlignUp(size, Kernel::PageSize);
312 size += page_table.GetNumGuardPages() * Kernel::PageSize * 4; 319 size += page_table.GetNumGuardPages() * Kernel::PageSize * 4;
313 320
@@ -391,12 +398,8 @@ public:
391 398
392 if (bss_size) { 399 if (bss_size) {
393 auto block_guard = detail::ScopeExit([&] { 400 auto block_guard = detail::ScopeExit([&] {
394 page_table.UnmapCodeMemory( 401 page_table.UnmapCodeMemory(addr + nro_size, bss_addr, bss_size);
395 addr + nro_size, bss_addr, bss_size, 402 page_table.UnmapCodeMemory(addr, nro_addr, nro_size);
396 Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange);
397 page_table.UnmapCodeMemory(
398 addr, nro_addr, nro_size,
399 Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange);
400 }); 403 });
401 404
402 const Result result{page_table.MapCodeMemory(addr + nro_size, bss_addr, bss_size)}; 405 const Result result{page_table.MapCodeMemory(addr + nro_size, bss_addr, bss_size)};
@@ -578,21 +581,17 @@ public:
578 auto& page_table{system.ApplicationProcess()->GetPageTable()}; 581 auto& page_table{system.ApplicationProcess()->GetPageTable()};
579 582
580 if (info.bss_size != 0) { 583 if (info.bss_size != 0) {
581 R_TRY(page_table.UnmapCodeMemory( 584 R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size +
582 info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address, 585 info.data_size,
583 info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); 586 info.bss_address, info.bss_size));
584 } 587 }
585 588
586 R_TRY(page_table.UnmapCodeMemory( 589 R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size + info.ro_size,
587 info.nro_address + info.text_size + info.ro_size, 590 info.src_addr + info.text_size + info.ro_size,
588 info.src_addr + info.text_size + info.ro_size, info.data_size, 591 info.data_size));
589 Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); 592 R_TRY(page_table.UnmapCodeMemory(info.nro_address + info.text_size,
590 R_TRY(page_table.UnmapCodeMemory( 593 info.src_addr + info.text_size, info.ro_size));
591 info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size, 594 R_TRY(page_table.UnmapCodeMemory(info.nro_address, info.src_addr, info.text_size));
592 Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
593 R_TRY(page_table.UnmapCodeMemory(
594 info.nro_address, info.src_addr, info.text_size,
595 Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
596 return ResultSuccess; 595 return ResultSuccess;
597 } 596 }
598 597
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp
index a71d26157..ad534177d 100644
--- a/src/core/hle/service/nfc/common/device_manager.cpp
+++ b/src/core/hle/service/nfc/common/device_manager.cpp
@@ -7,6 +7,7 @@
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hid/hid_types.h" 8#include "core/hid/hid_types.h"
9#include "core/hle/kernel/k_event.h" 9#include "core/hle/kernel/k_event.h"
10#include "core/hle/service/hid/hid_util.h"
10#include "core/hle/service/ipc_helpers.h" 11#include "core/hle/service/ipc_helpers.h"
11#include "core/hle/service/nfc/common/device.h" 12#include "core/hle/service/nfc/common/device.h"
12#include "core/hle/service/nfc/common/device_manager.h" 13#include "core/hle/service/nfc/common/device_manager.h"
@@ -24,7 +25,7 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex
24 25
25 for (u32 device_index = 0; device_index < devices.size(); device_index++) { 26 for (u32 device_index = 0; device_index < devices.size(); device_index++) {
26 devices[device_index] = 27 devices[device_index] =
27 std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, 28 std::make_shared<NfcDevice>(HID::IndexToNpadIdType(device_index), system,
28 service_context, availability_change_event); 29 service_context, availability_change_event);
29 } 30 }
30 31
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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <span>
7#include <vector>
8
9#include "common/concepts.h"
10#include "core/hle/service/nvdrv/devices/nvdevice.h"
11
12namespace Service::Nvidia::Devices {
13
14struct IoctlOneArgTraits {
15 template <typename T, typename R, typename A, typename... B>
16 static A GetFirstArgImpl(R (T::*)(A, B...));
17};
18
19struct IoctlTwoArgTraits {
20 template <typename T, typename R, typename A, typename B, typename... C>
21 static A GetFirstArgImpl(R (T::*)(A, B, C...));
22
23 template <typename T, typename R, typename A, typename B, typename... C>
24 static B GetSecondArgImpl(R (T::*)(A, B, C...));
25};
26
27struct Null {};
28
29// clang-format off
30
31template <typename FixedArg, typename VarArg, typename InlInVarArg, typename InlOutVarArg, typename F>
32NvResult WrapGeneric(F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, std::span<u8> inline_output) {
33 constexpr bool HasFixedArg = !std::is_same_v<FixedArg, Null>;
34 constexpr bool HasVarArg = !std::is_same_v<VarArg, Null>;
35 constexpr bool HasInlInVarArg = !std::is_same_v<InlInVarArg, Null>;
36 constexpr bool HasInlOutVarArg = !std::is_same_v<InlOutVarArg, Null>;
37
38 // Declare the fixed-size input value.
39 FixedArg fixed{};
40 size_t var_offset = 0;
41
42 if constexpr (HasFixedArg) {
43 // Read the fixed-size input value.
44 var_offset = std::min(sizeof(FixedArg), input.size());
45 if (var_offset > 0) {
46 std::memcpy(&fixed, input.data(), var_offset);
47 }
48 }
49
50 // Read the variable-sized inputs.
51 const size_t num_var_args = HasVarArg ? ((input.size() - var_offset) / sizeof(VarArg)) : 0;
52 std::vector<VarArg> var_args(num_var_args);
53 if constexpr (HasVarArg) {
54 if (num_var_args > 0) {
55 std::memcpy(var_args.data(), input.data() + var_offset, num_var_args * sizeof(VarArg));
56 }
57 }
58
59 const size_t num_inl_in_var_args = HasInlInVarArg ? (inline_input.size() / sizeof(InlInVarArg)) : 0;
60 std::vector<InlInVarArg> inl_in_var_args(num_inl_in_var_args);
61 if constexpr (HasInlInVarArg) {
62 if (num_inl_in_var_args > 0) {
63 std::memcpy(inl_in_var_args.data(), inline_input.data(), num_inl_in_var_args * sizeof(InlInVarArg));
64 }
65 }
66
67 // Construct inline output data.
68 const size_t num_inl_out_var_args = HasInlOutVarArg ? (inline_output.size() / sizeof(InlOutVarArg)) : 0;
69 std::vector<InlOutVarArg> inl_out_var_args(num_inl_out_var_args);
70
71 // Perform the call.
72 NvResult result = callable(fixed, var_args, inl_in_var_args, inl_out_var_args);
73
74 // Copy outputs.
75 if constexpr (HasFixedArg) {
76 if (output.size() > 0) {
77 std::memcpy(output.data(), &fixed, std::min(output.size(), sizeof(FixedArg)));
78 }
79 }
80
81 if constexpr (HasVarArg) {
82 if (num_var_args > 0 && output.size() > var_offset) {
83 const size_t max_var_size = output.size() - var_offset;
84 std::memcpy(output.data() + var_offset, var_args.data(), std::min(max_var_size, num_var_args * sizeof(VarArg)));
85 }
86 }
87
88 // Copy inline outputs.
89 if constexpr (HasInlOutVarArg) {
90 if (num_inl_out_var_args > 0) {
91 std::memcpy(inline_output.data(), inl_out_var_args.data(), num_inl_out_var_args * sizeof(InlOutVarArg));
92 }
93 }
94
95 // We're done.
96 return result;
97}
98
99template <typename Self, typename F, typename... Rest>
100NvResult WrapFixed(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) {
101 using FixedArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>;
102
103 const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
104 return (self->*callable)(fixed, std::forward<Rest>(rest)...);
105 };
106
107 return WrapGeneric<FixedArg, Null, Null, Null>(std::move(Callable), input, {}, output, {});
108}
109
110template <typename Self, typename F, typename... Rest>
111NvResult WrapFixedInlOut(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, std::span<u8> inline_output, Rest&&... rest) {
112 using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>;
113 using InlOutVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type;
114
115 const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
116 return (self->*callable)(fixed, inl_out, std::forward<Rest>(rest)...);
117 };
118
119 return WrapGeneric<FixedArg, Null, Null, InlOutVarArg>(std::move(Callable), input, {}, output, inline_output);
120}
121
122template <typename Self, typename F, typename... Rest>
123NvResult WrapVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) {
124 using VarArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>::value_type;
125
126 const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
127 return (self->*callable)(var, std::forward<Rest>(rest)...);
128 };
129
130 return WrapGeneric<Null, VarArg, Null, Null>(std::move(Callable), input, {}, output, {});
131}
132
133template <typename Self, typename F, typename... Rest>
134NvResult WrapFixedVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) {
135 using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>;
136 using VarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type;
137
138 const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
139 return (self->*callable)(fixed, var, std::forward<Rest>(rest)...);
140 };
141
142 return WrapGeneric<FixedArg, VarArg, Null, Null>(std::move(Callable), input, {}, output, {});
143}
144
145template <typename Self, typename F, typename... Rest>
146NvResult WrapFixedInlIn(Self* self, F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, Rest&&... rest) {
147 using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>;
148 using InlInVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type;
149
150 const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult {
151 return (self->*callable)(fixed, inl_in, std::forward<Rest>(rest)...);
152 };
153
154 return WrapGeneric<FixedArg, Null, InlInVarArg, Null>(std::move(Callable), input, inline_input, output, {});
155}
156
157// clang-format on
158
159} // 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 @@
11#include "core/core.h" 11#include "core/core.h"
12#include "core/hle/service/nvdrv/core/container.h" 12#include "core/hle/service/nvdrv/core/container.h"
13#include "core/hle/service/nvdrv/core/nvmap.h" 13#include "core/hle/service/nvdrv/core/nvmap.h"
14#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
14#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" 15#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
15#include "core/hle/service/nvdrv/devices/nvhost_gpu.h" 16#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
16#include "core/hle/service/nvdrv/nvdrv.h" 17#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
33 case 'A': 34 case 'A':
34 switch (command.cmd) { 35 switch (command.cmd) {
35 case 0x1: 36 case 0x1:
36 return BindChannel(input, output); 37 return WrapFixed(this, &nvhost_as_gpu::BindChannel, input, output);
37 case 0x2: 38 case 0x2:
38 return AllocateSpace(input, output); 39 return WrapFixed(this, &nvhost_as_gpu::AllocateSpace, input, output);
39 case 0x3: 40 case 0x3:
40 return FreeSpace(input, output); 41 return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output);
41 case 0x5: 42 case 0x5:
42 return UnmapBuffer(input, output); 43 return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output);
43 case 0x6: 44 case 0x6:
44 return MapBufferEx(input, output); 45 return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output);
45 case 0x8: 46 case 0x8:
46 return GetVARegions(input, output); 47 return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output);
47 case 0x9: 48 case 0x9:
48 return AllocAsEx(input, output); 49 return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output);
49 case 0x14: 50 case 0x14:
50 return Remap(input, output); 51 return WrapVariable(this, &nvhost_as_gpu::Remap, input, output);
51 default: 52 default:
52 break; 53 break;
53 } 54 }
@@ -72,7 +73,8 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
72 case 'A': 73 case 'A':
73 switch (command.cmd) { 74 switch (command.cmd) {
74 case 0x8: 75 case 0x8:
75 return GetVARegions(input, output, inline_output); 76 return WrapFixedInlOut(this, &nvhost_as_gpu::GetVARegions3, input, output,
77 inline_output);
76 default: 78 default:
77 break; 79 break;
78 } 80 }
@@ -87,10 +89,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
87void nvhost_as_gpu::OnOpen(DeviceFD fd) {} 89void nvhost_as_gpu::OnOpen(DeviceFD fd) {}
88void nvhost_as_gpu::OnClose(DeviceFD fd) {} 90void nvhost_as_gpu::OnClose(DeviceFD fd) {}
89 91
90NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> output) { 92NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
91 IoctlAllocAsEx params{};
92 std::memcpy(&params, input.data(), input.size());
93
94 LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size); 93 LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size);
95 94
96 std::scoped_lock lock(mutex); 95 std::scoped_lock lock(mutex);
@@ -141,10 +140,7 @@ NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> outpu
141 return NvResult::Success; 140 return NvResult::Success;
142} 141}
143 142
144NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> output) { 143NvResult nvhost_as_gpu::AllocateSpace(IoctlAllocSpace& params) {
145 IoctlAllocSpace params{};
146 std::memcpy(&params, input.data(), input.size());
147
148 LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages, 144 LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages,
149 params.page_size, params.flags); 145 params.page_size, params.flags);
150 146
@@ -194,7 +190,6 @@ NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> o
194 .big_pages = params.page_size != VM::YUZU_PAGESIZE, 190 .big_pages = params.page_size != VM::YUZU_PAGESIZE,
195 }; 191 };
196 192
197 std::memcpy(output.data(), &params, output.size());
198 return NvResult::Success; 193 return NvResult::Success;
199} 194}
200 195
@@ -222,10 +217,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {
222 mapping_map.erase(offset); 217 mapping_map.erase(offset);
223} 218}
224 219
225NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> output) { 220NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) {
226 IoctlFreeSpace params{};
227 std::memcpy(&params, input.data(), input.size());
228
229 LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset, 221 LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset,
230 params.pages, params.page_size); 222 params.pages, params.page_size);
231 223
@@ -264,18 +256,11 @@ NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> outpu
264 return NvResult::BadValue; 256 return NvResult::BadValue;
265 } 257 }
266 258
267 std::memcpy(output.data(), &params, output.size());
268 return NvResult::Success; 259 return NvResult::Success;
269} 260}
270 261
271NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) { 262NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
272 const auto num_entries = input.size() / sizeof(IoctlRemapEntry); 263 LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size());
273
274 LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries);
275
276 std::scoped_lock lock(mutex);
277 entries.resize_destructive(num_entries);
278 std::memcpy(entries.data(), input.data(), input.size());
279 264
280 if (!vm.initialised) { 265 if (!vm.initialised) {
281 return NvResult::BadValue; 266 return NvResult::BadValue;
@@ -317,14 +302,10 @@ NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) {
317 } 302 }
318 } 303 }
319 304
320 std::memcpy(output.data(), entries.data(), output.size());
321 return NvResult::Success; 305 return NvResult::Success;
322} 306}
323 307
324NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> output) { 308NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
325 IoctlMapBufferEx params{};
326 std::memcpy(&params, input.data(), input.size());
327
328 LOG_DEBUG(Service_NVDRV, 309 LOG_DEBUG(Service_NVDRV,
329 "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}" 310 "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
330 ", offset={}", 311 ", offset={}",
@@ -421,14 +402,10 @@ NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> out
421 mapping_map[params.offset] = mapping; 402 mapping_map[params.offset] = mapping;
422 } 403 }
423 404
424 std::memcpy(output.data(), &params, output.size());
425 return NvResult::Success; 405 return NvResult::Success;
426} 406}
427 407
428NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { 408NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
429 IoctlUnmapBuffer params{};
430 std::memcpy(&params, input.data(), input.size());
431
432 LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); 409 LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
433 410
434 std::scoped_lock lock(mutex); 411 std::scoped_lock lock(mutex);
@@ -464,9 +441,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> out
464 return NvResult::Success; 441 return NvResult::Success;
465} 442}
466 443
467NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::span<u8> output) { 444NvResult nvhost_as_gpu::BindChannel(IoctlBindChannel& params) {
468 IoctlBindChannel params{};
469 std::memcpy(&params, input.data(), input.size());
470 LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); 445 LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
471 446
472 auto gpu_channel_device = module.GetDevice<nvhost_gpu>(params.fd); 447 auto gpu_channel_device = module.GetDevice<nvhost_gpu>(params.fd);
@@ -493,10 +468,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) {
493 }; 468 };
494} 469}
495 470
496NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output) { 471NvResult nvhost_as_gpu::GetVARegions1(IoctlGetVaRegions& params) {
497 IoctlGetVaRegions params{};
498 std::memcpy(&params, input.data(), input.size());
499
500 LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, 472 LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr,
501 params.buf_size); 473 params.buf_size);
502 474
@@ -508,15 +480,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou
508 480
509 GetVARegionsImpl(params); 481 GetVARegionsImpl(params);
510 482
511 std::memcpy(output.data(), &params, output.size());
512 return NvResult::Success; 483 return NvResult::Success;
513} 484}
514 485
515NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output, 486NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions) {
516 std::span<u8> inline_output) {
517 IoctlGetVaRegions params{};
518 std::memcpy(&params, input.data(), input.size());
519
520 LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, 487 LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr,
521 params.buf_size); 488 params.buf_size);
522 489
@@ -528,9 +495,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou
528 495
529 GetVARegionsImpl(params); 496 GetVARegionsImpl(params);
530 497
531 std::memcpy(output.data(), &params, output.size()); 498 const size_t num_regions = std::min(params.regions.size(), regions.size());
532 std::memcpy(inline_output.data(), &params.regions[0], sizeof(VaRegion)); 499 for (size_t i = 0; i < num_regions; i++) {
533 std::memcpy(inline_output.data() + sizeof(VaRegion), &params.regions[1], sizeof(VaRegion)); 500 regions[i] = params.regions[i];
501 }
534 502
535 return NvResult::Success; 503 return NvResult::Success;
536} 504}
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:
139 static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2, 139 static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2,
140 "IoctlGetVaRegions is incorrect size"); 140 "IoctlGetVaRegions is incorrect size");
141 141
142 NvResult AllocAsEx(std::span<const u8> input, std::span<u8> output); 142 NvResult AllocAsEx(IoctlAllocAsEx& params);
143 NvResult AllocateSpace(std::span<const u8> input, std::span<u8> output); 143 NvResult AllocateSpace(IoctlAllocSpace& params);
144 NvResult Remap(std::span<const u8> input, std::span<u8> output); 144 NvResult Remap(std::span<IoctlRemapEntry> params);
145 NvResult MapBufferEx(std::span<const u8> input, std::span<u8> output); 145 NvResult MapBufferEx(IoctlMapBufferEx& params);
146 NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); 146 NvResult UnmapBuffer(IoctlUnmapBuffer& params);
147 NvResult FreeSpace(std::span<const u8> input, std::span<u8> output); 147 NvResult FreeSpace(IoctlFreeSpace& params);
148 NvResult BindChannel(std::span<const u8> input, std::span<u8> output); 148 NvResult BindChannel(IoctlBindChannel& params);
149 149
150 void GetVARegionsImpl(IoctlGetVaRegions& params); 150 void GetVARegionsImpl(IoctlGetVaRegions& params);
151 NvResult GetVARegions(std::span<const u8> input, std::span<u8> output); 151 NvResult GetVARegions1(IoctlGetVaRegions& params);
152 NvResult GetVARegions(std::span<const u8> input, std::span<u8> output, 152 NvResult GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions);
153 std::span<u8> inline_output);
154 153
155 void FreeMappingLocked(u64 offset); 154 void FreeMappingLocked(u64 offset);
156 155
@@ -213,7 +212,6 @@ private:
213 bool initialised{}; 212 bool initialised{};
214 } vm; 213 } vm;
215 std::shared_ptr<Tegra::MemoryManager> gmmu; 214 std::shared_ptr<Tegra::MemoryManager> gmmu;
216 Common::ScratchBuffer<IoctlRemapEntry> entries;
217 215
218 // s32 channel{}; 216 // s32 channel{};
219 // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE}; 217 // 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 @@
14#include "core/hle/kernel/k_event.h" 14#include "core/hle/kernel/k_event.h"
15#include "core/hle/service/nvdrv/core/container.h" 15#include "core/hle/service/nvdrv/core/container.h"
16#include "core/hle/service/nvdrv/core/syncpoint_manager.h" 16#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
17#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
17#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" 18#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
18#include "video_core/gpu.h" 19#include "video_core/gpu.h"
19#include "video_core/host1x/host1x.h" 20#include "video_core/host1x/host1x.h"
@@ -40,19 +41,19 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inp
40 case 0x0: 41 case 0x0:
41 switch (command.cmd) { 42 switch (command.cmd) {
42 case 0x1b: 43 case 0x1b:
43 return NvOsGetConfigU32(input, output); 44 return WrapFixed(this, &nvhost_ctrl::NvOsGetConfigU32, input, output);
44 case 0x1c: 45 case 0x1c:
45 return IocCtrlClearEventWait(input, output); 46 return WrapFixed(this, &nvhost_ctrl::IocCtrlClearEventWait, input, output);
46 case 0x1d: 47 case 0x1d:
47 return IocCtrlEventWait(input, output, true); 48 return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, true);
48 case 0x1e: 49 case 0x1e:
49 return IocCtrlEventWait(input, output, false); 50 return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, false);
50 case 0x1f: 51 case 0x1f:
51 return IocCtrlEventRegister(input, output); 52 return WrapFixed(this, &nvhost_ctrl::IocCtrlEventRegister, input, output);
52 case 0x20: 53 case 0x20:
53 return IocCtrlEventUnregister(input, output); 54 return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregister, input, output);
54 case 0x21: 55 case 0x21:
55 return IocCtrlEventUnregisterBatch(input, output); 56 return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregisterBatch, input, output);
56 } 57 }
57 break; 58 break;
58 default: 59 default:
@@ -79,25 +80,19 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {}
79 80
80void nvhost_ctrl::OnClose(DeviceFD fd) {} 81void nvhost_ctrl::OnClose(DeviceFD fd) {}
81 82
82NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output) { 83NvResult nvhost_ctrl::NvOsGetConfigU32(IocGetConfigParams& params) {
83 IocGetConfigParams params{};
84 std::memcpy(&params, input.data(), sizeof(params));
85 LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), 84 LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
86 params.param_str.data()); 85 params.param_str.data());
87 return NvResult::ConfigVarNotFound; // Returns error on production mode 86 return NvResult::ConfigVarNotFound; // Returns error on production mode
88} 87}
89 88
90NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, 89NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation) {
91 bool is_allocation) {
92 IocCtrlEventWaitParams params{};
93 std::memcpy(&params, input.data(), sizeof(params));
94 LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}", 90 LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}",
95 params.fence.id, params.fence.value, params.timeout, is_allocation); 91 params.fence.id, params.fence.value, params.timeout, is_allocation);
96 92
97 bool must_unmark_fail = !is_allocation; 93 bool must_unmark_fail = !is_allocation;
98 const u32 event_id = params.value.raw; 94 const u32 event_id = params.value.raw;
99 SCOPE_EXIT({ 95 SCOPE_EXIT({
100 std::memcpy(output.data(), &params, sizeof(params));
101 if (must_unmark_fail) { 96 if (must_unmark_fail) {
102 events[event_id].fails = 0; 97 events[event_id].fails = 0;
103 } 98 }
@@ -231,9 +226,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) {
231 return NvResult::Success; 226 return NvResult::Success;
232} 227}
233 228
234NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output) { 229NvResult nvhost_ctrl::IocCtrlEventRegister(IocCtrlEventRegisterParams& params) {
235 IocCtrlEventRegisterParams params{};
236 std::memcpy(&params, input.data(), sizeof(params));
237 const u32 event_id = params.user_event_id; 230 const u32 event_id = params.user_event_id;
238 LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); 231 LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id);
239 if (event_id >= MaxNvEvents) { 232 if (event_id >= MaxNvEvents) {
@@ -252,9 +245,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<
252 return NvResult::Success; 245 return NvResult::Success;
253} 246}
254 247
255NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output) { 248NvResult nvhost_ctrl::IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params) {
256 IocCtrlEventUnregisterParams params{};
257 std::memcpy(&params, input.data(), sizeof(params));
258 const u32 event_id = params.user_event_id & 0x00FF; 249 const u32 event_id = params.user_event_id & 0x00FF;
259 LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); 250 LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id);
260 251
@@ -262,9 +253,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::spa
262 return FreeEvent(event_id); 253 return FreeEvent(event_id);
263} 254}
264 255
265NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output) { 256NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params) {
266 IocCtrlEventUnregisterBatchParams params{};
267 std::memcpy(&params, input.data(), sizeof(params));
268 u64 event_mask = params.user_events; 257 u64 event_mask = params.user_events;
269 LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask); 258 LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask);
270 259
@@ -280,10 +269,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std
280 return NvResult::Success; 269 return NvResult::Success;
281} 270}
282 271
283NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output) { 272NvResult nvhost_ctrl::IocCtrlClearEventWait(IocCtrlEventClearParams& params) {
284 IocCtrlEventClearParams params{};
285 std::memcpy(&params, input.data(), sizeof(params));
286
287 u32 event_id = params.event_id.slot; 273 u32 event_id = params.event_id.slot;
288 LOG_DEBUG(Service_NVDRV, "called, event_id: {:X}", event_id); 274 LOG_DEBUG(Service_NVDRV, "called, event_id: {:X}", event_id);
289 275
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:
186 static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, 186 static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8,
187 "IocCtrlEventKill is incorrect size"); 187 "IocCtrlEventKill is incorrect size");
188 188
189 NvResult NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output); 189 NvResult NvOsGetConfigU32(IocGetConfigParams& params);
190 NvResult IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation); 190 NvResult IocCtrlEventRegister(IocCtrlEventRegisterParams& params);
191 NvResult IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output); 191 NvResult IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params);
192 NvResult IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output); 192 NvResult IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params);
193 NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output); 193 NvResult IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation);
194 NvResult IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output); 194 NvResult IocCtrlClearEventWait(IocCtrlEventClearParams& params);
195 195
196 NvResult FreeEvent(u32 slot); 196 NvResult FreeEvent(u32 slot);
197 197
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 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/core_timing.h" 8#include "core/core_timing.h"
9#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
9#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" 10#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
10#include "core/hle/service/nvdrv/nvdrv.h" 11#include "core/hle/service/nvdrv/nvdrv.h"
11 12
@@ -27,23 +28,23 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8>
27 case 'G': 28 case 'G':
28 switch (command.cmd) { 29 switch (command.cmd) {
29 case 0x1: 30 case 0x1:
30 return ZCullGetCtxSize(input, output); 31 return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetCtxSize, input, output);
31 case 0x2: 32 case 0x2:
32 return ZCullGetInfo(input, output); 33 return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetInfo, input, output);
33 case 0x3: 34 case 0x3:
34 return ZBCSetTable(input, output); 35 return WrapFixed(this, &nvhost_ctrl_gpu::ZBCSetTable, input, output);
35 case 0x4: 36 case 0x4:
36 return ZBCQueryTable(input, output); 37 return WrapFixed(this, &nvhost_ctrl_gpu::ZBCQueryTable, input, output);
37 case 0x5: 38 case 0x5:
38 return GetCharacteristics(input, output); 39 return WrapFixed(this, &nvhost_ctrl_gpu::GetCharacteristics1, input, output);
39 case 0x6: 40 case 0x6:
40 return GetTPCMasks(input, output); 41 return WrapFixed(this, &nvhost_ctrl_gpu::GetTPCMasks1, input, output);
41 case 0x7: 42 case 0x7:
42 return FlushL2(input, output); 43 return WrapFixed(this, &nvhost_ctrl_gpu::FlushL2, input, output);
43 case 0x14: 44 case 0x14:
44 return GetActiveSlotMask(input, output); 45 return WrapFixed(this, &nvhost_ctrl_gpu::GetActiveSlotMask, input, output);
45 case 0x1c: 46 case 0x1c:
46 return GetGpuTime(input, output); 47 return WrapFixed(this, &nvhost_ctrl_gpu::GetGpuTime, input, output);
47 default: 48 default:
48 break; 49 break;
49 } 50 }
@@ -65,9 +66,11 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
65 case 'G': 66 case 'G':
66 switch (command.cmd) { 67 switch (command.cmd) {
67 case 0x5: 68 case 0x5:
68 return GetCharacteristics(input, output, inline_output); 69 return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetCharacteristics3, input, output,
70 inline_output);
69 case 0x6: 71 case 0x6:
70 return GetTPCMasks(input, output, inline_output); 72 return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetTPCMasks3, input, output,
73 inline_output);
71 default: 74 default:
72 break; 75 break;
73 } 76 }
@@ -82,10 +85,8 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
82void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} 85void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {}
83void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} 86void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {}
84 87
85NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output) { 88NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) {
86 LOG_DEBUG(Service_NVDRV, "called"); 89 LOG_DEBUG(Service_NVDRV, "called");
87 IoctlCharacteristics params{};
88 std::memcpy(&params, input.data(), input.size());
89 params.gc.arch = 0x120; 90 params.gc.arch = 0x120;
90 params.gc.impl = 0xb; 91 params.gc.impl = 0xb;
91 params.gc.rev = 0xa1; 92 params.gc.rev = 0xa1;
@@ -123,15 +124,13 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa
123 params.gc.gr_compbit_store_base_hw = 0x0; 124 params.gc.gr_compbit_store_base_hw = 0x0;
124 params.gpu_characteristics_buf_size = 0xA0; 125 params.gpu_characteristics_buf_size = 0xA0;
125 params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) 126 params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
126 std::memcpy(output.data(), &params, output.size());
127 return NvResult::Success; 127 return NvResult::Success;
128} 128}
129 129
130NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output, 130NvResult nvhost_ctrl_gpu::GetCharacteristics3(
131 std::span<u8> inline_output) { 131 IoctlCharacteristics& params, std::span<IoctlGpuCharacteristics> gpu_characteristics) {
132 LOG_DEBUG(Service_NVDRV, "called"); 132 LOG_DEBUG(Service_NVDRV, "called");
133 IoctlCharacteristics params{}; 133
134 std::memcpy(&params, input.data(), input.size());
135 params.gc.arch = 0x120; 134 params.gc.arch = 0x120;
136 params.gc.impl = 0xb; 135 params.gc.impl = 0xb;
137 params.gc.rev = 0xa1; 136 params.gc.rev = 0xa1;
@@ -169,70 +168,47 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa
169 params.gc.gr_compbit_store_base_hw = 0x0; 168 params.gc.gr_compbit_store_base_hw = 0x0;
170 params.gpu_characteristics_buf_size = 0xA0; 169 params.gpu_characteristics_buf_size = 0xA0;
171 params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) 170 params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED)
172 171 if (!gpu_characteristics.empty()) {
173 std::memcpy(output.data(), &params, output.size()); 172 gpu_characteristics.front() = params.gc;
174 std::memcpy(inline_output.data(), &params.gc, inline_output.size()); 173 }
175 return NvResult::Success; 174 return NvResult::Success;
176} 175}
177 176
178NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output) { 177NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) {
179 IoctlGpuGetTpcMasksArgs params{};
180 std::memcpy(&params, input.data(), input.size());
181 LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); 178 LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
182 if (params.mask_buffer_size != 0) { 179 if (params.mask_buffer_size != 0) {
183 params.tcp_mask = 3; 180 params.tcp_mask = 3;
184 } 181 }
185 std::memcpy(output.data(), &params, output.size());
186 return NvResult::Success; 182 return NvResult::Success;
187} 183}
188 184
189NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output, 185NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask) {
190 std::span<u8> inline_output) {
191 IoctlGpuGetTpcMasksArgs params{};
192 std::memcpy(&params, input.data(), input.size());
193 LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); 186 LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
194 if (params.mask_buffer_size != 0) { 187 if (params.mask_buffer_size != 0) {
195 params.tcp_mask = 3; 188 params.tcp_mask = 3;
196 } 189 }
197 std::memcpy(output.data(), &params, output.size()); 190 if (!tpc_mask.empty()) {
198 std::memcpy(inline_output.data(), &params.tcp_mask, inline_output.size()); 191 tpc_mask.front() = params.tcp_mask;
192 }
199 return NvResult::Success; 193 return NvResult::Success;
200} 194}
201 195
202NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::span<u8> output) { 196NvResult nvhost_ctrl_gpu::GetActiveSlotMask(IoctlActiveSlotMask& params) {
203 LOG_DEBUG(Service_NVDRV, "called"); 197 LOG_DEBUG(Service_NVDRV, "called");
204 198
205 IoctlActiveSlotMask params{};
206 if (input.size() > 0) {
207 std::memcpy(&params, input.data(), input.size());
208 }
209 params.slot = 0x07; 199 params.slot = 0x07;
210 params.mask = 0x01; 200 params.mask = 0x01;
211 std::memcpy(output.data(), &params, output.size());
212 return NvResult::Success; 201 return NvResult::Success;
213} 202}
214 203
215NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output) { 204NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(IoctlZcullGetCtxSize& params) {
216 LOG_DEBUG(Service_NVDRV, "called"); 205 LOG_DEBUG(Service_NVDRV, "called");
217
218 IoctlZcullGetCtxSize params{};
219 if (input.size() > 0) {
220 std::memcpy(&params, input.data(), input.size());
221 }
222 params.size = 0x1; 206 params.size = 0x1;
223 std::memcpy(output.data(), &params, output.size());
224 return NvResult::Success; 207 return NvResult::Success;
225} 208}
226 209
227NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> output) { 210NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) {
228 LOG_DEBUG(Service_NVDRV, "called"); 211 LOG_DEBUG(Service_NVDRV, "called");
229
230 IoctlNvgpuGpuZcullGetInfoArgs params{};
231
232 if (input.size() > 0) {
233 std::memcpy(&params, input.data(), input.size());
234 }
235
236 params.width_align_pixels = 0x20; 212 params.width_align_pixels = 0x20;
237 params.height_align_pixels = 0x20; 213 params.height_align_pixels = 0x20;
238 params.pixel_squares_by_aliquots = 0x400; 214 params.pixel_squares_by_aliquots = 0x400;
@@ -243,53 +219,28 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8>
243 params.subregion_width_align_pixels = 0x20; 219 params.subregion_width_align_pixels = 0x20;
244 params.subregion_height_align_pixels = 0x40; 220 params.subregion_height_align_pixels = 0x40;
245 params.subregion_count = 0x10; 221 params.subregion_count = 0x10;
246 std::memcpy(output.data(), &params, output.size());
247 return NvResult::Success; 222 return NvResult::Success;
248} 223}
249 224
250NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::span<u8> output) { 225NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
251 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 226 LOG_WARNING(Service_NVDRV, "(STUBBED) called");
252
253 IoctlZbcSetTable params{};
254 std::memcpy(&params, input.data(), input.size());
255 // TODO(ogniK): What does this even actually do? 227 // TODO(ogniK): What does this even actually do?
256
257 // Prevent null pointer being passed as arg 1
258 if (output.empty()) {
259 LOG_WARNING(Service_NVDRV, "Avoiding passing null pointer to memcpy");
260 } else {
261 std::memcpy(output.data(), &params, output.size());
262 }
263 return NvResult::Success; 228 return NvResult::Success;
264} 229}
265 230
266NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::span<u8> output) { 231NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
267 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 232 LOG_WARNING(Service_NVDRV, "(STUBBED) called");
268
269 IoctlZbcQueryTable params{};
270 std::memcpy(&params, input.data(), input.size());
271 // TODO : To implement properly
272 std::memcpy(output.data(), &params, output.size());
273 return NvResult::Success; 233 return NvResult::Success;
274} 234}
275 235
276NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::span<u8> output) { 236NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) {
277 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 237 LOG_WARNING(Service_NVDRV, "(STUBBED) called");
278
279 IoctlFlushL2 params{};
280 std::memcpy(&params, input.data(), input.size());
281 // TODO : To implement properly
282 std::memcpy(output.data(), &params, output.size());
283 return NvResult::Success; 238 return NvResult::Success;
284} 239}
285 240
286NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::span<u8> output) { 241NvResult nvhost_ctrl_gpu::GetGpuTime(IoctlGetGpuTime& params) {
287 LOG_DEBUG(Service_NVDRV, "called"); 242 LOG_DEBUG(Service_NVDRV, "called");
288
289 IoctlGetGpuTime params{};
290 std::memcpy(&params, input.data(), input.size());
291 params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count()); 243 params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count());
292 std::memcpy(output.data(), &params, output.size());
293 return NvResult::Success; 244 return NvResult::Success;
294} 245}
295 246
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:
151 }; 151 };
152 static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); 152 static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size");
153 153
154 NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output); 154 NvResult GetCharacteristics1(IoctlCharacteristics& params);
155 NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output, 155 NvResult GetCharacteristics3(IoctlCharacteristics& params,
156 std::span<u8> inline_output); 156 std::span<IoctlGpuCharacteristics> gpu_characteristics);
157 157
158 NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output); 158 NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params);
159 NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output, 159 NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask);
160 std::span<u8> inline_output); 160
161 161 NvResult GetActiveSlotMask(IoctlActiveSlotMask& params);
162 NvResult GetActiveSlotMask(std::span<const u8> input, std::span<u8> output); 162 NvResult ZCullGetCtxSize(IoctlZcullGetCtxSize& params);
163 NvResult ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output); 163 NvResult ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params);
164 NvResult ZCullGetInfo(std::span<const u8> input, std::span<u8> output); 164 NvResult ZBCSetTable(IoctlZbcSetTable& params);
165 NvResult ZBCSetTable(std::span<const u8> input, std::span<u8> output); 165 NvResult ZBCQueryTable(IoctlZbcQueryTable& params);
166 NvResult ZBCQueryTable(std::span<const u8> input, std::span<u8> output); 166 NvResult FlushL2(IoctlFlushL2& params);
167 NvResult FlushL2(std::span<const u8> input, std::span<u8> output); 167 NvResult GetGpuTime(IoctlGetGpuTime& params);
168 NvResult GetGpuTime(std::span<const u8> input, std::span<u8> output);
169 168
170 EventInterface& events_interface; 169 EventInterface& events_interface;
171 170
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 @@
8#include "core/hle/service/nvdrv/core/container.h" 8#include "core/hle/service/nvdrv/core/container.h"
9#include "core/hle/service/nvdrv/core/nvmap.h" 9#include "core/hle/service/nvdrv/core/nvmap.h"
10#include "core/hle/service/nvdrv/core/syncpoint_manager.h" 10#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
11#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
11#include "core/hle/service/nvdrv/devices/nvhost_gpu.h" 12#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
12#include "core/hle/service/nvdrv/nvdrv.h" 13#include "core/hle/service/nvdrv/nvdrv.h"
13#include "core/memory.h" 14#include "core/memory.h"
@@ -52,7 +53,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
52 case 0x0: 53 case 0x0:
53 switch (command.cmd) { 54 switch (command.cmd) {
54 case 0x3: 55 case 0x3:
55 return GetWaitbase(input, output); 56 return WrapFixed(this, &nvhost_gpu::GetWaitbase, input, output);
56 default: 57 default:
57 break; 58 break;
58 } 59 }
@@ -60,25 +61,25 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
60 case 'H': 61 case 'H':
61 switch (command.cmd) { 62 switch (command.cmd) {
62 case 0x1: 63 case 0x1:
63 return SetNVMAPfd(input, output); 64 return WrapFixed(this, &nvhost_gpu::SetNVMAPfd, input, output);
64 case 0x3: 65 case 0x3:
65 return ChannelSetTimeout(input, output); 66 return WrapFixed(this, &nvhost_gpu::ChannelSetTimeout, input, output);
66 case 0x8: 67 case 0x8:
67 return SubmitGPFIFOBase(input, output, false); 68 return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, false);
68 case 0x9: 69 case 0x9:
69 return AllocateObjectContext(input, output); 70 return WrapFixed(this, &nvhost_gpu::AllocateObjectContext, input, output);
70 case 0xb: 71 case 0xb:
71 return ZCullBind(input, output); 72 return WrapFixed(this, &nvhost_gpu::ZCullBind, input, output);
72 case 0xc: 73 case 0xc:
73 return SetErrorNotifier(input, output); 74 return WrapFixed(this, &nvhost_gpu::SetErrorNotifier, input, output);
74 case 0xd: 75 case 0xd:
75 return SetChannelPriority(input, output); 76 return WrapFixed(this, &nvhost_gpu::SetChannelPriority, input, output);
76 case 0x1a: 77 case 0x1a:
77 return AllocGPFIFOEx2(input, output); 78 return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output);
78 case 0x1b: 79 case 0x1b:
79 return SubmitGPFIFOBase(input, output, true); 80 return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, true);
80 case 0x1d: 81 case 0x1d:
81 return ChannelSetTimeslice(input, output); 82 return WrapFixed(this, &nvhost_gpu::ChannelSetTimeslice, input, output);
82 default: 83 default:
83 break; 84 break;
84 } 85 }
@@ -86,9 +87,9 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
86 case 'G': 87 case 'G':
87 switch (command.cmd) { 88 switch (command.cmd) {
88 case 0x14: 89 case 0x14:
89 return SetClientData(input, output); 90 return WrapFixed(this, &nvhost_gpu::SetClientData, input, output);
90 case 0x15: 91 case 0x15:
91 return GetClientData(input, output); 92 return WrapFixed(this, &nvhost_gpu::GetClientData, input, output);
92 default: 93 default:
93 break; 94 break;
94 } 95 }
@@ -104,7 +105,8 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> inpu
104 case 'H': 105 case 'H':
105 switch (command.cmd) { 106 switch (command.cmd) {
106 case 0x1b: 107 case 0x1b:
107 return SubmitGPFIFOBase(input, inline_input, output); 108 return WrapFixedInlIn(this, &nvhost_gpu::SubmitGPFIFOBase2, input, inline_input,
109 output);
108 } 110 }
109 break; 111 break;
110 } 112 }
@@ -121,63 +123,45 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
121void nvhost_gpu::OnOpen(DeviceFD fd) {} 123void nvhost_gpu::OnOpen(DeviceFD fd) {}
122void nvhost_gpu::OnClose(DeviceFD fd) {} 124void nvhost_gpu::OnClose(DeviceFD fd) {}
123 125
124NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { 126NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) {
125 IoctlSetNvmapFD params{};
126 std::memcpy(&params, input.data(), input.size());
127 LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); 127 LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
128 128
129 nvmap_fd = params.nvmap_fd; 129 nvmap_fd = params.nvmap_fd;
130 return NvResult::Success; 130 return NvResult::Success;
131} 131}
132 132
133NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::span<u8> output) { 133NvResult nvhost_gpu::SetClientData(IoctlClientData& params) {
134 LOG_DEBUG(Service_NVDRV, "called"); 134 LOG_DEBUG(Service_NVDRV, "called");
135
136 IoctlClientData params{};
137 std::memcpy(&params, input.data(), input.size());
138 user_data = params.data; 135 user_data = params.data;
139 return NvResult::Success; 136 return NvResult::Success;
140} 137}
141 138
142NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::span<u8> output) { 139NvResult nvhost_gpu::GetClientData(IoctlClientData& params) {
143 LOG_DEBUG(Service_NVDRV, "called"); 140 LOG_DEBUG(Service_NVDRV, "called");
144
145 IoctlClientData params{};
146 std::memcpy(&params, input.data(), input.size());
147 params.data = user_data; 141 params.data = user_data;
148 std::memcpy(output.data(), &params, output.size());
149 return NvResult::Success; 142 return NvResult::Success;
150} 143}
151 144
152NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::span<u8> output) { 145NvResult nvhost_gpu::ZCullBind(IoctlZCullBind& params) {
153 std::memcpy(&zcull_params, input.data(), input.size()); 146 zcull_params = params;
154 LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, 147 LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
155 zcull_params.mode); 148 zcull_params.mode);
156
157 std::memcpy(output.data(), &zcull_params, output.size());
158 return NvResult::Success; 149 return NvResult::Success;
159} 150}
160 151
161NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::span<u8> output) { 152NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) {
162 IoctlSetErrorNotifier params{};
163 std::memcpy(&params, input.data(), input.size());
164 LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, 153 LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset,
165 params.size, params.mem); 154 params.size, params.mem);
166
167 std::memcpy(output.data(), &params, output.size());
168 return NvResult::Success; 155 return NvResult::Success;
169} 156}
170 157
171NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::span<u8> output) { 158NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) {
172 std::memcpy(&channel_priority, input.data(), input.size()); 159 channel_priority = params.priority;
173 LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); 160 LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
174
175 return NvResult::Success; 161 return NvResult::Success;
176} 162}
177 163
178NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output) { 164NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params) {
179 IoctlAllocGpfifoEx2 params{};
180 std::memcpy(&params, input.data(), input.size());
181 LOG_WARNING(Service_NVDRV, 165 LOG_WARNING(Service_NVDRV,
182 "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, " 166 "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, "
183 "unk1={:X}, unk2={:X}, unk3={:X}", 167 "unk1={:X}, unk2={:X}, unk3={:X}",
@@ -193,18 +177,14 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> out
193 177
194 params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint); 178 params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint);
195 179
196 std::memcpy(output.data(), &params, output.size());
197 return NvResult::Success; 180 return NvResult::Success;
198} 181}
199 182
200NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::span<u8> output) { 183NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
201 IoctlAllocObjCtx params{};
202 std::memcpy(&params, input.data(), input.size());
203 LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, 184 LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
204 params.flags); 185 params.flags);
205 186
206 params.obj_id = 0x0; 187 params.obj_id = 0x0;
207 std::memcpy(output.data(), &params, output.size());
208 return NvResult::Success; 188 return NvResult::Success;
209} 189}
210 190
@@ -248,8 +228,7 @@ static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementW
248 return result; 228 return result;
249} 229}
250 230
251NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, 231NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries) {
252 Tegra::CommandList&& entries) {
253 LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, 232 LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address,
254 params.num_entries, params.flags.raw); 233 params.num_entries, params.flags.raw);
255 234
@@ -290,65 +269,55 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> o
290 269
291 flags.raw = 0; 270 flags.raw = 0;
292 271
293 std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
294 return NvResult::Success; 272 return NvResult::Success;
295} 273}
296 274
297NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, 275NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
298 bool kickoff) { 276 std::span<Tegra::CommandListHeader> commands, bool kickoff) {
299 if (input.size() < sizeof(IoctlSubmitGpfifo)) { 277 if (params.num_entries > commands.size()) {
300 UNIMPLEMENTED(); 278 UNIMPLEMENTED();
301 return NvResult::InvalidSize; 279 return NvResult::InvalidSize;
302 } 280 }
303 IoctlSubmitGpfifo params{};
304 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
305 Tegra::CommandList entries(params.num_entries);
306 281
282 Tegra::CommandList entries(params.num_entries);
307 if (kickoff) { 283 if (kickoff) {
308 system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), 284 system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(),
309 params.num_entries * sizeof(Tegra::CommandListHeader)); 285 params.num_entries * sizeof(Tegra::CommandListHeader));
310 } else { 286 } else {
311 std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], 287 std::memcpy(entries.command_lists.data(), commands.data(),
312 params.num_entries * sizeof(Tegra::CommandListHeader)); 288 params.num_entries * sizeof(Tegra::CommandListHeader));
313 } 289 }
314 290
315 return SubmitGPFIFOImpl(params, output, std::move(entries)); 291 return SubmitGPFIFOImpl(params, std::move(entries));
316} 292}
317 293
318NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, 294NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,
319 std::span<u8> output) { 295 std::span<const Tegra::CommandListHeader> commands) {
320 if (input.size() < sizeof(IoctlSubmitGpfifo)) { 296 if (params.num_entries > commands.size()) {
321 UNIMPLEMENTED(); 297 UNIMPLEMENTED();
322 return NvResult::InvalidSize; 298 return NvResult::InvalidSize;
323 } 299 }
324 IoctlSubmitGpfifo params{}; 300
325 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
326 Tegra::CommandList entries(params.num_entries); 301 Tegra::CommandList entries(params.num_entries);
327 std::memcpy(entries.command_lists.data(), input_inline.data(), input_inline.size()); 302 std::memcpy(entries.command_lists.data(), commands.data(),
328 return SubmitGPFIFOImpl(params, output, std::move(entries)); 303 params.num_entries * sizeof(Tegra::CommandListHeader));
304 return SubmitGPFIFOImpl(params, std::move(entries));
329} 305}
330 306
331NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::span<u8> output) { 307NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) {
332 IoctlGetWaitbase params{};
333 std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
334 LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); 308 LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
335 309
336 params.value = 0; // Seems to be hard coded at 0 310 params.value = 0; // Seems to be hard coded at 0
337 std::memcpy(output.data(), &params, output.size());
338 return NvResult::Success; 311 return NvResult::Success;
339} 312}
340 313
341NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::span<u8> output) { 314NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) {
342 IoctlChannelSetTimeout params{};
343 std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
344 LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); 315 LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
345 316
346 return NvResult::Success; 317 return NvResult::Success;
347} 318}
348 319
349NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output) { 320NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) {
350 IoctlSetTimeslice params{};
351 std::memcpy(&params, input.data(), sizeof(IoctlSetTimeslice));
352 LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); 321 LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);
353 322
354 channel_timeslice = params.timeslice; 323 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:
186 u32_le channel_priority{}; 186 u32_le channel_priority{};
187 u32_le channel_timeslice{}; 187 u32_le channel_timeslice{};
188 188
189 NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); 189 NvResult SetNVMAPfd(IoctlSetNvmapFD& params);
190 NvResult SetClientData(std::span<const u8> input, std::span<u8> output); 190 NvResult SetClientData(IoctlClientData& params);
191 NvResult GetClientData(std::span<const u8> input, std::span<u8> output); 191 NvResult GetClientData(IoctlClientData& params);
192 NvResult ZCullBind(std::span<const u8> input, std::span<u8> output); 192 NvResult ZCullBind(IoctlZCullBind& params);
193 NvResult SetErrorNotifier(std::span<const u8> input, std::span<u8> output); 193 NvResult SetErrorNotifier(IoctlSetErrorNotifier& params);
194 NvResult SetChannelPriority(std::span<const u8> input, std::span<u8> output); 194 NvResult SetChannelPriority(IoctlChannelSetPriority& params);
195 NvResult AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output); 195 NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params);
196 NvResult AllocateObjectContext(std::span<const u8> input, std::span<u8> output); 196 NvResult AllocateObjectContext(IoctlAllocObjCtx& params);
197 NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, 197
198 Tegra::CommandList&& entries); 198 NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries);
199 NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, 199 NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
200 bool kickoff = false); 200 std::span<Tegra::CommandListHeader> commands, bool kickoff = false);
201 NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, 201 NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,
202 std::span<u8> output); 202 std::span<const Tegra::CommandListHeader> commands);
203 NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); 203
204 NvResult ChannelSetTimeout(std::span<const u8> input, std::span<u8> output); 204 NvResult GetWaitbase(IoctlGetWaitbase& params);
205 NvResult ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output); 205 NvResult ChannelSetTimeout(IoctlChannelSetTimeout& params);
206 NvResult ChannelSetTimeslice(IoctlSetTimeslice& params);
206 207
207 EventInterface& events_interface; 208 EventInterface& events_interface;
208 NvCore::Container& core; 209 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 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/service/nvdrv/core/container.h" 8#include "core/hle/service/nvdrv/core/container.h"
9#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
9#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" 10#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
10#include "video_core/renderer_base.h" 11#include "video_core/renderer_base.h"
11 12
@@ -25,18 +26,18 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
25 if (!host1x_file.fd_to_id.contains(fd)) { 26 if (!host1x_file.fd_to_id.contains(fd)) {
26 host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++; 27 host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++;
27 } 28 }
28 return Submit(fd, input, output); 29 return WrapFixedVariable(this, &nvhost_nvdec::Submit, input, output, fd);
29 } 30 }
30 case 0x2: 31 case 0x2:
31 return GetSyncpoint(input, output); 32 return WrapFixed(this, &nvhost_nvdec::GetSyncpoint, input, output);
32 case 0x3: 33 case 0x3:
33 return GetWaitbase(input, output); 34 return WrapFixed(this, &nvhost_nvdec::GetWaitbase, input, output);
34 case 0x7: 35 case 0x7:
35 return SetSubmitTimeout(input, output); 36 return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output);
36 case 0x9: 37 case 0x9:
37 return MapBuffer(input, output); 38 return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output);
38 case 0xa: 39 case 0xa:
39 return UnmapBuffer(input, output); 40 return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output);
40 default: 41 default:
41 break; 42 break;
42 } 43 }
@@ -44,7 +45,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
44 case 'H': 45 case 'H':
45 switch (command.cmd) { 46 switch (command.cmd) {
46 case 0x1: 47 case 0x1:
47 return SetNVMAPfd(input); 48 return WrapFixed(this, &nvhost_nvdec::SetNVMAPfd, input, output);
48 default: 49 default:
49 break; 50 break;
50 } 51 }
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
29 return 0; 29 return 0;
30 } 30 }
31 const size_t bytes_copied = count * sizeof(T); 31 const size_t bytes_copied = count * sizeof(T);
32 if (input.size() < offset + bytes_copied) {
33 return 0;
34 }
32 std::memcpy(dst.data(), input.data() + offset, bytes_copied); 35 std::memcpy(dst.data(), input.data() + offset, bytes_copied);
33 return bytes_copied; 36 return bytes_copied;
34} 37}
@@ -41,6 +44,9 @@ std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size
41 return 0; 44 return 0;
42 } 45 }
43 const size_t bytes_copied = src.size() * sizeof(T); 46 const size_t bytes_copied = src.size() * sizeof(T);
47 if (dst.size() < offset + bytes_copied) {
48 return 0;
49 }
44 std::memcpy(dst.data() + offset, src.data(), bytes_copied); 50 std::memcpy(dst.data() + offset, src.data(), bytes_copied);
45 return bytes_copied; 51 return bytes_copied;
46} 52}
@@ -63,18 +69,14 @@ nvhost_nvdec_common::~nvhost_nvdec_common() {
63 core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint); 69 core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint);
64} 70}
65 71
66NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) { 72NvResult nvhost_nvdec_common::SetNVMAPfd(IoctlSetNvmapFD& params) {
67 IoctlSetNvmapFD params{};
68 std::memcpy(&params, input.data(), sizeof(IoctlSetNvmapFD));
69 LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); 73 LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
70 74
71 nvmap_fd = params.nvmap_fd; 75 nvmap_fd = params.nvmap_fd;
72 return NvResult::Success; 76 return NvResult::Success;
73} 77}
74 78
75NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) { 79NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, DeviceFD fd) {
76 IoctlSubmit params{};
77 std::memcpy(&params, input.data(), sizeof(IoctlSubmit));
78 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); 80 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count);
79 81
80 // Instantiate param buffers 82 // Instantiate param buffers
@@ -85,12 +87,12 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std
85 std::vector<u32> fence_thresholds(params.fence_count); 87 std::vector<u32> fence_thresholds(params.fence_count);
86 88
87 // Slice input into their respective buffers 89 // Slice input into their respective buffers
88 std::size_t offset = sizeof(IoctlSubmit); 90 std::size_t offset = 0;
89 offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset); 91 offset += SliceVectors(data, command_buffers, params.cmd_buffer_count, offset);
90 offset += SliceVectors(input, relocs, params.relocation_count, offset); 92 offset += SliceVectors(data, relocs, params.relocation_count, offset);
91 offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset); 93 offset += SliceVectors(data, reloc_shifts, params.relocation_count, offset);
92 offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset); 94 offset += SliceVectors(data, syncpt_increments, params.syncpoint_count, offset);
93 offset += SliceVectors(input, fence_thresholds, params.fence_count, offset); 95 offset += SliceVectors(data, fence_thresholds, params.fence_count, offset);
94 96
95 auto& gpu = system.GPU(); 97 auto& gpu = system.GPU();
96 if (gpu.UseNvdec()) { 98 if (gpu.UseNvdec()) {
@@ -108,72 +110,51 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std
108 cmdlist.size() * sizeof(u32)); 110 cmdlist.size() * sizeof(u32));
109 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); 111 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
110 } 112 }
111 std::memcpy(output.data(), &params, sizeof(IoctlSubmit));
112 // Some games expect command_buffers to be written back 113 // Some games expect command_buffers to be written back
113 offset = sizeof(IoctlSubmit); 114 offset = 0;
114 offset += WriteVectors(output, command_buffers, offset); 115 offset += WriteVectors(data, command_buffers, offset);
115 offset += WriteVectors(output, relocs, offset); 116 offset += WriteVectors(data, relocs, offset);
116 offset += WriteVectors(output, reloc_shifts, offset); 117 offset += WriteVectors(data, reloc_shifts, offset);
117 offset += WriteVectors(output, syncpt_increments, offset); 118 offset += WriteVectors(data, syncpt_increments, offset);
118 offset += WriteVectors(output, fence_thresholds, offset); 119 offset += WriteVectors(data, fence_thresholds, offset);
119 120
120 return NvResult::Success; 121 return NvResult::Success;
121} 122}
122 123
123NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::span<u8> output) { 124NvResult nvhost_nvdec_common::GetSyncpoint(IoctlGetSyncpoint& params) {
124 IoctlGetSyncpoint params{};
125 std::memcpy(&params, input.data(), sizeof(IoctlGetSyncpoint));
126 LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); 125 LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param);
127
128 // const u32 id{NvCore::SyncpointManager::channel_syncpoints[static_cast<u32>(channel_type)]};
129 params.value = channel_syncpoint; 126 params.value = channel_syncpoint;
130 std::memcpy(output.data(), &params, sizeof(IoctlGetSyncpoint));
131
132 return NvResult::Success; 127 return NvResult::Success;
133} 128}
134 129
135NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::span<u8> output) { 130NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) {
136 IoctlGetWaitbase params{};
137 LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); 131 LOG_CRITICAL(Service_NVDRV, "called WAITBASE");
138 std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
139 params.value = 0; // Seems to be hard coded at 0 132 params.value = 0; // Seems to be hard coded at 0
140 std::memcpy(output.data(), &params, sizeof(IoctlGetWaitbase));
141 return NvResult::Success; 133 return NvResult::Success;
142} 134}
143 135
144NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) { 136NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries) {
145 IoctlMapBuffer params{}; 137 const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
146 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); 138 for (size_t i = 0; i < num_entries; i++) {
147 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); 139 entries[i].map_address = nvmap.PinHandle(entries[i].map_handle);
148
149 SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
150
151 for (auto& cmd_buffer : cmd_buffer_handles) {
152 cmd_buffer.map_address = nvmap.PinHandle(cmd_buffer.map_handle);
153 } 140 }
154 std::memcpy(output.data(), &params, sizeof(IoctlMapBuffer));
155 std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(),
156 cmd_buffer_handles.size() * sizeof(MapBufferEntry));
157 141
158 return NvResult::Success; 142 return NvResult::Success;
159} 143}
160 144
161NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { 145NvResult nvhost_nvdec_common::UnmapBuffer(IoctlMapBuffer& params,
162 IoctlMapBuffer params{}; 146 std::span<MapBufferEntry> entries) {
163 std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer)); 147 const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
164 std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); 148 for (size_t i = 0; i < num_entries; i++) {
165 149 nvmap.UnpinHandle(entries[i].map_handle);
166 SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); 150 entries[i] = {};
167 for (auto& cmd_buffer : cmd_buffer_handles) {
168 nvmap.UnpinHandle(cmd_buffer.map_handle);
169 } 151 }
170 152
171 std::memset(output.data(), 0, output.size()); 153 params = {};
172 return NvResult::Success; 154 return NvResult::Success;
173} 155}
174 156
175NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::span<u8> output) { 157NvResult nvhost_nvdec_common::SetSubmitTimeout(u32 timeout) {
176 std::memcpy(&submit_timeout, input.data(), input.size());
177 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 158 LOG_WARNING(Service_NVDRV, "(STUBBED) called");
178 return NvResult::Success; 159 return NvResult::Success;
179} 160}
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:
107 static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); 107 static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size");
108 108
109 /// Ioctl command implementations 109 /// Ioctl command implementations
110 NvResult SetNVMAPfd(std::span<const u8> input); 110 NvResult SetNVMAPfd(IoctlSetNvmapFD&);
111 NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output); 111 NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd);
112 NvResult GetSyncpoint(std::span<const u8> input, std::span<u8> output); 112 NvResult GetSyncpoint(IoctlGetSyncpoint& params);
113 NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); 113 NvResult GetWaitbase(IoctlGetWaitbase& params);
114 NvResult MapBuffer(std::span<const u8> input, std::span<u8> output); 114 NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries);
115 NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); 115 NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries);
116 NvResult SetSubmitTimeout(std::span<const u8> input, std::span<u8> output); 116 NvResult SetSubmitTimeout(u32 timeout);
117 117
118 Kernel::KEvent* QueryEvent(u32 event_id) override; 118 Kernel::KEvent* QueryEvent(u32 event_id) override;
119 119
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 @@
5 5
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
8#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h" 9#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h"
9 10
10namespace Service::Nvidia::Devices { 11namespace Service::Nvidia::Devices {
@@ -18,7 +19,7 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
18 case 'H': 19 case 'H':
19 switch (command.cmd) { 20 switch (command.cmd) {
20 case 0x1: 21 case 0x1:
21 return SetNVMAPfd(input, output); 22 return WrapFixed(this, &nvhost_nvjpg::SetNVMAPfd, input, output);
22 default: 23 default:
23 break; 24 break;
24 } 25 }
@@ -46,9 +47,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
46void nvhost_nvjpg::OnOpen(DeviceFD fd) {} 47void nvhost_nvjpg::OnOpen(DeviceFD fd) {}
47void nvhost_nvjpg::OnClose(DeviceFD fd) {} 48void nvhost_nvjpg::OnClose(DeviceFD fd) {}
48 49
49NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { 50NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) {
50 IoctlSetNvmapFD params{};
51 std::memcpy(&params, input.data(), input.size());
52 LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); 51 LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
53 52
54 nvmap_fd = params.nvmap_fd; 53 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:
33 33
34 s32_le nvmap_fd{}; 34 s32_le nvmap_fd{};
35 35
36 NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); 36 NvResult SetNVMAPfd(IoctlSetNvmapFD& params);
37}; 37};
38 38
39} // namespace Service::Nvidia::Devices 39} // 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 @@
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/service/nvdrv/core/container.h" 7#include "core/hle/service/nvdrv/core/container.h"
8#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
8#include "core/hle/service/nvdrv/devices/nvhost_vic.h" 9#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
9#include "video_core/renderer_base.h" 10#include "video_core/renderer_base.h"
10 11
@@ -25,16 +26,16 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
25 if (!host1x_file.fd_to_id.contains(fd)) { 26 if (!host1x_file.fd_to_id.contains(fd)) {
26 host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++; 27 host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++;
27 } 28 }
28 return Submit(fd, input, output); 29 return WrapFixedVariable(this, &nvhost_vic::Submit, input, output, fd);
29 } 30 }
30 case 0x2: 31 case 0x2:
31 return GetSyncpoint(input, output); 32 return WrapFixed(this, &nvhost_vic::GetSyncpoint, input, output);
32 case 0x3: 33 case 0x3:
33 return GetWaitbase(input, output); 34 return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output);
34 case 0x9: 35 case 0x9:
35 return MapBuffer(input, output); 36 return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output);
36 case 0xa: 37 case 0xa:
37 return UnmapBuffer(input, output); 38 return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output);
38 default: 39 default:
39 break; 40 break;
40 } 41 }
@@ -42,7 +43,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
42 case 'H': 43 case 'H':
43 switch (command.cmd) { 44 switch (command.cmd) {
44 case 0x1: 45 case 0x1:
45 return SetNVMAPfd(input); 46 return WrapFixed(this, &nvhost_vic::SetNVMAPfd, input, output);
46 default: 47 default:
47 break; 48 break;
48 } 49 }
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 @@
13#include "core/hle/kernel/k_process.h" 13#include "core/hle/kernel/k_process.h"
14#include "core/hle/service/nvdrv/core/container.h" 14#include "core/hle/service/nvdrv/core/container.h"
15#include "core/hle/service/nvdrv/core/nvmap.h" 15#include "core/hle/service/nvdrv/core/nvmap.h"
16#include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
16#include "core/hle/service/nvdrv/devices/nvmap.h" 17#include "core/hle/service/nvdrv/devices/nvmap.h"
17#include "core/memory.h" 18#include "core/memory.h"
18 19
@@ -31,17 +32,17 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
31 case 0x1: 32 case 0x1:
32 switch (command.cmd) { 33 switch (command.cmd) {
33 case 0x1: 34 case 0x1:
34 return IocCreate(input, output); 35 return WrapFixed(this, &nvmap::IocCreate, input, output);
35 case 0x3: 36 case 0x3:
36 return IocFromId(input, output); 37 return WrapFixed(this, &nvmap::IocFromId, input, output);
37 case 0x4: 38 case 0x4:
38 return IocAlloc(input, output); 39 return WrapFixed(this, &nvmap::IocAlloc, input, output);
39 case 0x5: 40 case 0x5:
40 return IocFree(input, output); 41 return WrapFixed(this, &nvmap::IocFree, input, output);
41 case 0x9: 42 case 0x9:
42 return IocParam(input, output); 43 return WrapFixed(this, &nvmap::IocParam, input, output);
43 case 0xe: 44 case 0xe:
44 return IocGetId(input, output); 45 return WrapFixed(this, &nvmap::IocGetId, input, output);
45 default: 46 default:
46 break; 47 break;
47 } 48 }
@@ -69,9 +70,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, st
69void nvmap::OnOpen(DeviceFD fd) {} 70void nvmap::OnOpen(DeviceFD fd) {}
70void nvmap::OnClose(DeviceFD fd) {} 71void nvmap::OnClose(DeviceFD fd) {}
71 72
72NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) { 73NvResult nvmap::IocCreate(IocCreateParams& params) {
73 IocCreateParams params;
74 std::memcpy(&params, input.data(), sizeof(params));
75 LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); 74 LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size);
76 75
77 std::shared_ptr<NvCore::NvMap::Handle> handle_description{}; 76 std::shared_ptr<NvCore::NvMap::Handle> handle_description{};
@@ -85,13 +84,10 @@ NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) {
85 params.handle = handle_description->id; 84 params.handle = handle_description->id;
86 LOG_DEBUG(Service_NVDRV, "handle: {}, size: 0x{:X}", handle_description->id, params.size); 85 LOG_DEBUG(Service_NVDRV, "handle: {}, size: 0x{:X}", handle_description->id, params.size);
87 86
88 std::memcpy(output.data(), &params, sizeof(params));
89 return NvResult::Success; 87 return NvResult::Success;
90} 88}
91 89
92NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) { 90NvResult nvmap::IocAlloc(IocAllocParams& params) {
93 IocAllocParams params;
94 std::memcpy(&params, input.data(), sizeof(params));
95 LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); 91 LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address);
96 92
97 if (!params.handle) { 93 if (!params.handle) {
@@ -133,14 +129,10 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {
133 handle_description->size, 129 handle_description->size,
134 Kernel::KMemoryPermission::None, true, false) 130 Kernel::KMemoryPermission::None, true, false)
135 .IsSuccess()); 131 .IsSuccess());
136 std::memcpy(output.data(), &params, sizeof(params));
137 return result; 132 return result;
138} 133}
139 134
140NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) { 135NvResult nvmap::IocGetId(IocGetIdParams& params) {
141 IocGetIdParams params;
142 std::memcpy(&params, input.data(), sizeof(params));
143
144 LOG_DEBUG(Service_NVDRV, "called"); 136 LOG_DEBUG(Service_NVDRV, "called");
145 137
146 // See the comment in FromId for extra info on this function 138 // 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) {
157 } 149 }
158 150
159 params.id = handle_description->id; 151 params.id = handle_description->id;
160 std::memcpy(output.data(), &params, sizeof(params));
161 return NvResult::Success; 152 return NvResult::Success;
162} 153}
163 154
164NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) { 155NvResult nvmap::IocFromId(IocFromIdParams& params) {
165 IocFromIdParams params;
166 std::memcpy(&params, input.data(), sizeof(params));
167
168 LOG_DEBUG(Service_NVDRV, "called, id:{}", params.id); 156 LOG_DEBUG(Service_NVDRV, "called, id:{}", params.id);
169 157
170 // Handles and IDs are always the same value in nvmap however IDs can be used globally given the 158 // 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) {
188 return result; 176 return result;
189 } 177 }
190 params.handle = handle_description->id; 178 params.handle = handle_description->id;
191 std::memcpy(output.data(), &params, sizeof(params));
192 return NvResult::Success; 179 return NvResult::Success;
193} 180}
194 181
195NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) { 182NvResult nvmap::IocParam(IocParamParams& params) {
196 enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; 183 enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 };
197 184
198 IocParamParams params;
199 std::memcpy(&params, input.data(), sizeof(params));
200
201 LOG_DEBUG(Service_NVDRV, "called type={}", params.param); 185 LOG_DEBUG(Service_NVDRV, "called type={}", params.param);
202 186
203 if (!params.handle) { 187 if (!params.handle) {
@@ -237,14 +221,10 @@ NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) {
237 return NvResult::BadValue; 221 return NvResult::BadValue;
238 } 222 }
239 223
240 std::memcpy(output.data(), &params, sizeof(params));
241 return NvResult::Success; 224 return NvResult::Success;
242} 225}
243 226
244NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) { 227NvResult nvmap::IocFree(IocFreeParams& params) {
245 IocFreeParams params;
246 std::memcpy(&params, input.data(), sizeof(params));
247
248 LOG_DEBUG(Service_NVDRV, "called"); 228 LOG_DEBUG(Service_NVDRV, "called");
249 229
250 if (!params.handle) { 230 if (!params.handle) {
@@ -267,7 +247,6 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {
267 // This is possible when there's internal dups or other duplicates. 247 // This is possible when there's internal dups or other duplicates.
268 } 248 }
269 249
270 std::memcpy(output.data(), &params, sizeof(params));
271 return NvResult::Success; 250 return NvResult::Success;
272} 251}
273 252
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:
99 }; 99 };
100 static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); 100 static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size");
101 101
102 NvResult IocCreate(std::span<const u8> input, std::span<u8> output); 102 NvResult IocCreate(IocCreateParams& params);
103 NvResult IocAlloc(std::span<const u8> input, std::span<u8> output); 103 NvResult IocAlloc(IocAllocParams& params);
104 NvResult IocGetId(std::span<const u8> input, std::span<u8> output); 104 NvResult IocGetId(IocGetIdParams& params);
105 NvResult IocFromId(std::span<const u8> input, std::span<u8> output); 105 NvResult IocFromId(IocFromIdParams& params);
106 NvResult IocParam(std::span<const u8> input, std::span<u8> output); 106 NvResult IocParam(IocParamParams& params);
107 NvResult IocFree(std::span<const u8> input, std::span<u8> output); 107 NvResult IocFree(IocFreeParams& params);
108 108
109private: 109private:
110 /// Id to use for the next handle that is created. 110 /// Id to use for the next handle that is created.
diff --git a/src/core/hle/service/nvnflinger/buffer_item.h b/src/core/hle/service/nvnflinger/buffer_item.h
index 3da8cc3aa..7fd808f54 100644
--- a/src/core/hle/service/nvnflinger/buffer_item.h
+++ b/src/core/hle/service/nvnflinger/buffer_item.h
@@ -15,7 +15,7 @@
15 15
16namespace Service::android { 16namespace Service::android {
17 17
18struct GraphicBuffer; 18class GraphicBuffer;
19 19
20class BufferItem final { 20class BufferItem final {
21public: 21public:
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
index 51291539d..d91886bed 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
@@ -5,7 +5,6 @@
5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp 5// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/hle/service/nvdrv/core/nvmap.h"
9#include "core/hle/service/nvnflinger/buffer_item.h" 8#include "core/hle/service/nvnflinger/buffer_item.h"
10#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" 9#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
11#include "core/hle/service/nvnflinger/buffer_queue_core.h" 10#include "core/hle/service/nvnflinger/buffer_queue_core.h"
@@ -14,9 +13,8 @@
14 13
15namespace Service::android { 14namespace Service::android {
16 15
17BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, 16BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
18 Service::Nvidia::NvCore::NvMap& nvmap_) 17 : core{std::move(core_)}, slots{core->slots} {}
19 : core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {}
20 18
21BufferQueueConsumer::~BufferQueueConsumer() = default; 19BufferQueueConsumer::~BufferQueueConsumer() = default;
22 20
@@ -136,8 +134,6 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
136 134
137 slots[slot].buffer_state = BufferState::Free; 135 slots[slot].buffer_state = BufferState::Free;
138 136
139 nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true);
140
141 listener = core->connected_producer_listener; 137 listener = core->connected_producer_listener;
142 138
143 LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot); 139 LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
@@ -175,6 +171,25 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_
175 return Status::NoError; 171 return Status::NoError;
176} 172}
177 173
174Status BufferQueueConsumer::Disconnect() {
175 LOG_DEBUG(Service_Nvnflinger, "called");
176
177 std::scoped_lock lock{core->mutex};
178
179 if (core->consumer_listener == nullptr) {
180 LOG_ERROR(Service_Nvnflinger, "no consumer is connected");
181 return Status::BadValue;
182 }
183
184 core->is_abandoned = true;
185 core->consumer_listener = nullptr;
186 core->queue.clear();
187 core->FreeAllBuffersLocked();
188 core->SignalDequeueCondition();
189
190 return Status::NoError;
191}
192
178Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { 193Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
179 if (out_slot_mask == nullptr) { 194 if (out_slot_mask == nullptr) {
180 LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr"); 195 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 50ed0bb5f..0a61e8dbd 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
@@ -13,10 +13,6 @@
13#include "core/hle/service/nvnflinger/buffer_queue_defs.h" 13#include "core/hle/service/nvnflinger/buffer_queue_defs.h"
14#include "core/hle/service/nvnflinger/status.h" 14#include "core/hle/service/nvnflinger/status.h"
15 15
16namespace Service::Nvidia::NvCore {
17class NvMap;
18} // namespace Service::Nvidia::NvCore
19
20namespace Service::android { 16namespace Service::android {
21 17
22class BufferItem; 18class BufferItem;
@@ -25,19 +21,18 @@ class IConsumerListener;
25 21
26class BufferQueueConsumer final { 22class BufferQueueConsumer final {
27public: 23public:
28 explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, 24 explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
29 Service::Nvidia::NvCore::NvMap& nvmap_);
30 ~BufferQueueConsumer(); 25 ~BufferQueueConsumer();
31 26
32 Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); 27 Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
33 Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); 28 Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
34 Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app); 29 Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app);
30 Status Disconnect();
35 Status GetReleasedBuffers(u64* out_slot_mask); 31 Status GetReleasedBuffers(u64* out_slot_mask);
36 32
37private: 33private:
38 std::shared_ptr<BufferQueueCore> core; 34 std::shared_ptr<BufferQueueCore> core;
39 BufferQueueDefs::SlotsType& slots; 35 BufferQueueDefs::SlotsType& slots;
40 Service::Nvidia::NvCore::NvMap& nvmap;
41}; 36};
42 37
43} // namespace Service::android 38} // namespace Service::android
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;
14 14
15BufferQueueCore::~BufferQueueCore() = default; 15BufferQueueCore::~BufferQueueCore() = default;
16 16
17void BufferQueueCore::NotifyShutdown() {
18 std::scoped_lock lock{mutex};
19
20 is_shutting_down = true;
21
22 SignalDequeueCondition();
23}
24
25void BufferQueueCore::SignalDequeueCondition() { 17void BufferQueueCore::SignalDequeueCondition() {
26 dequeue_possible.store(true); 18 dequeue_possible.store(true);
27 dequeue_condition.notify_all(); 19 dequeue_condition.notify_all();
28} 20}
29 21
30bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) { 22bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) {
31 if (is_shutting_down) {
32 return false;
33 }
34
35 dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); 23 dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); });
36 dequeue_possible.store(false); 24 dequeue_possible.store(false);
37 25
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:
34 BufferQueueCore(); 34 BufferQueueCore();
35 ~BufferQueueCore(); 35 ~BufferQueueCore();
36 36
37 void NotifyShutdown();
38
39private: 37private:
40 void SignalDequeueCondition(); 38 void SignalDequeueCondition();
41 bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk); 39 bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk);
@@ -74,7 +72,6 @@ private:
74 u32 transform_hint{}; 72 u32 transform_hint{};
75 bool is_allocating{}; 73 bool is_allocating{};
76 mutable std::condition_variable_any is_allocating_condition; 74 mutable std::condition_variable_any is_allocating_condition;
77 bool is_shutting_down{};
78}; 75};
79 76
80} // namespace Service::android 77} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
index 6e7a49658..5d8762d25 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
@@ -13,7 +13,6 @@
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/service/hle_ipc.h" 14#include "core/hle/service/hle_ipc.h"
15#include "core/hle/service/kernel_helpers.h" 15#include "core/hle/service/kernel_helpers.h"
16#include "core/hle/service/nvdrv/core/nvmap.h"
17#include "core/hle/service/nvnflinger/buffer_queue_core.h" 16#include "core/hle/service/nvnflinger/buffer_queue_core.h"
18#include "core/hle/service/nvnflinger/buffer_queue_producer.h" 17#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
19#include "core/hle/service/nvnflinger/consumer_listener.h" 18#include "core/hle/service/nvnflinger/consumer_listener.h"
@@ -533,8 +532,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
533 item.is_droppable = core->dequeue_buffer_cannot_block || async; 532 item.is_droppable = core->dequeue_buffer_cannot_block || async;
534 item.swap_interval = swap_interval; 533 item.swap_interval = swap_interval;
535 534
536 nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true);
537
538 sticky_transform = sticky_transform_; 535 sticky_transform = sticky_transform_;
539 536
540 if (core->queue.empty()) { 537 if (core->queue.empty()) {
@@ -744,19 +741,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
744 return Status::NoError; 741 return Status::NoError;
745 } 742 }
746 743
747 // HACK: We are not Android. Remove handle for items in queue, and clear queue.
748 // Allows synchronous destruction of nvmap handles.
749 for (auto& item : core->queue) {
750 nvmap.FreeHandle(item.graphic_buffer->BufferId(), true);
751 }
752 core->queue.clear();
753
754 switch (api) { 744 switch (api) {
755 case NativeWindowApi::Egl: 745 case NativeWindowApi::Egl:
756 case NativeWindowApi::Cpu: 746 case NativeWindowApi::Cpu:
757 case NativeWindowApi::Media: 747 case NativeWindowApi::Media:
758 case NativeWindowApi::Camera: 748 case NativeWindowApi::Camera:
759 if (core->connected_api == api) { 749 if (core->connected_api == api) {
750 core->queue.clear();
760 core->FreeAllBuffersLocked(); 751 core->FreeAllBuffersLocked();
761 core->connected_producer_listener = nullptr; 752 core->connected_producer_listener = nullptr;
762 core->connected_api = NativeWindowApi::NoConnectedApi; 753 core->connected_api = NativeWindowApi::NoConnectedApi;
@@ -785,7 +776,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
785} 776}
786 777
787Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, 778Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
788 const std::shared_ptr<GraphicBuffer>& buffer) { 779 const std::shared_ptr<NvGraphicBuffer>& buffer) {
789 LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); 780 LOG_DEBUG(Service_Nvnflinger, "slot {}", slot);
790 781
791 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { 782 if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
@@ -796,7 +787,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
796 787
797 slots[slot] = {}; 788 slots[slot] = {};
798 slots[slot].fence = Fence::NoFence(); 789 slots[slot].fence = Fence::NoFence();
799 slots[slot].graphic_buffer = buffer; 790 slots[slot].graphic_buffer = std::make_shared<GraphicBuffer>(nvmap, buffer);
800 slots[slot].frame_number = 0; 791 slots[slot].frame_number = 0;
801 792
802 // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for 793 // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for
@@ -839,7 +830,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
839 } 830 }
840 case TransactionId::SetPreallocatedBuffer: { 831 case TransactionId::SetPreallocatedBuffer: {
841 const auto slot = parcel_in.Read<s32>(); 832 const auto slot = parcel_in.Read<s32>();
842 const auto buffer = parcel_in.ReadObject<GraphicBuffer>(); 833 const auto buffer = parcel_in.ReadObject<NvGraphicBuffer>();
843 834
844 status = SetPreallocatedBuffer(slot, buffer); 835 status = SetPreallocatedBuffer(slot, buffer);
845 break; 836 break;
@@ -867,7 +858,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
867 858
868 status = RequestBuffer(slot, &buf); 859 status = RequestBuffer(slot, &buf);
869 860
870 parcel_out.WriteFlattenedObject(buf); 861 parcel_out.WriteFlattenedObject<NvGraphicBuffer>(buf.get());
871 break; 862 break;
872 } 863 }
873 case TransactionId::QueueBuffer: { 864 case TransactionId::QueueBuffer: {
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
index d4201c104..64c17d56c 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
@@ -38,6 +38,7 @@ namespace Service::android {
38 38
39class BufferQueueCore; 39class BufferQueueCore;
40class IProducerListener; 40class IProducerListener;
41struct NvGraphicBuffer;
41 42
42class BufferQueueProducer final : public IBinder { 43class BufferQueueProducer final : public IBinder {
43public: 44public:
@@ -65,7 +66,7 @@ public:
65 bool producer_controlled_by_app, QueueBufferOutput* output); 66 bool producer_controlled_by_app, QueueBufferOutput* output);
66 67
67 Status Disconnect(NativeWindowApi api); 68 Status Disconnect(NativeWindowApi api);
68 Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer); 69 Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<NvGraphicBuffer>& buffer);
69 70
70private: 71private:
71 BufferQueueProducer(const BufferQueueProducer&) = delete; 72 BufferQueueProducer(const BufferQueueProducer&) = delete;
diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h
index d8c9dec3b..d25bca049 100644
--- a/src/core/hle/service/nvnflinger/buffer_slot.h
+++ b/src/core/hle/service/nvnflinger/buffer_slot.h
@@ -13,7 +13,7 @@
13 13
14namespace Service::android { 14namespace Service::android {
15 15
16struct GraphicBuffer; 16class GraphicBuffer;
17 17
18enum class BufferState : u32 { 18enum class BufferState : u32 {
19 Free = 0, 19 Free = 0,
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 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "common/common_funcs.h"
6#include "common/common_types.h" 7#include "common/common_types.h"
7 8
8namespace Service::android { 9namespace Service::android {
@@ -21,5 +22,6 @@ enum class BufferTransformFlags : u32 {
21 /// Rotate source image 270 degrees clockwise 22 /// Rotate source image 270 degrees clockwise
22 Rotate270 = 0x07, 23 Rotate270 = 0x07,
23}; 24};
25DECLARE_ENUM_FLAG_OPERATORS(BufferTransformFlags);
24 26
25} // namespace Service::android 27} // 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) {
27 consumer->Connect(shared_from_this(), controlled_by_app); 27 consumer->Connect(shared_from_this(), controlled_by_app);
28} 28}
29 29
30void ConsumerBase::Abandon() {
31 LOG_DEBUG(Service_Nvnflinger, "called");
32
33 std::scoped_lock lock{mutex};
34
35 if (!is_abandoned) {
36 this->AbandonLocked();
37 is_abandoned = true;
38 }
39}
40
41void ConsumerBase::AbandonLocked() {
42 for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
43 this->FreeBufferLocked(i);
44 }
45 // disconnect from the BufferQueue
46 consumer->Disconnect();
47 consumer = nullptr;
48}
49
30void ConsumerBase::FreeBufferLocked(s32 slot_index) { 50void ConsumerBase::FreeBufferLocked(s32 slot_index) {
31 LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index); 51 LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index);
32 52
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;
24class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> { 24class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> {
25public: 25public:
26 void Connect(bool controlled_by_app); 26 void Connect(bool controlled_by_app);
27 void Abandon();
27 28
28protected: 29protected:
29 explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); 30 explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
@@ -34,6 +35,7 @@ protected:
34 void OnBuffersReleased() override; 35 void OnBuffersReleased() override;
35 void OnSidebandStreamChanged() override; 36 void OnSidebandStreamChanged() override;
36 37
38 void AbandonLocked();
37 void FreeBufferLocked(s32 slot_index); 39 void FreeBufferLocked(s32 slot_index);
38 Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); 40 Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when);
39 Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer); 41 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 2e29bc848..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,
71 R_SUCCEED(); 71 R_SUCCEED();
72} 72}
73 73
74template <typename T>
75std::span<u8> SerializeIoc(T& params) {
76 return std::span(reinterpret_cast<u8*>(std::addressof(params)), sizeof(T));
77}
78
79Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { 74Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) {
80 // Create a handle. 75 // Create a handle.
81 Nvidia::Devices::nvmap::IocCreateParams create_in_params{ 76 Nvidia::Devices::nvmap::IocCreateParams create_params{
82 .size = size, 77 .size = size,
83 .handle = 0, 78 .handle = 0,
84 }; 79 };
85 Nvidia::Devices::nvmap::IocCreateParams create_out_params{}; 80 R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success,
86 R_UNLESS(nvmap.IocCreate(SerializeIoc(create_in_params), SerializeIoc(create_out_params)) ==
87 Nvidia::NvResult::Success,
88 VI::ResultOperationFailed); 81 VI::ResultOperationFailed);
89 82
90 // Assign the output handle. 83 // Assign the output handle.
91 *out_nv_map_handle = create_out_params.handle; 84 *out_nv_map_handle = create_params.handle;
92 85
93 // We succeeded. 86 // We succeeded.
94 R_SUCCEED(); 87 R_SUCCEED();
@@ -96,13 +89,10 @@ Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap,
96 89
97Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { 90Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) {
98 // Free the handle. 91 // Free the handle.
99 Nvidia::Devices::nvmap::IocFreeParams free_in_params{ 92 Nvidia::Devices::nvmap::IocFreeParams free_params{
100 .handle = handle, 93 .handle = handle,
101 }; 94 };
102 Nvidia::Devices::nvmap::IocFreeParams free_out_params{}; 95 R_UNLESS(nvmap.IocFree(free_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed);
103 R_UNLESS(nvmap.IocFree(SerializeIoc(free_in_params), SerializeIoc(free_out_params)) ==
104 Nvidia::NvResult::Success,
105 VI::ResultOperationFailed);
106 96
107 // We succeeded. 97 // We succeeded.
108 R_SUCCEED(); 98 R_SUCCEED();
@@ -111,7 +101,7 @@ Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) {
111Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, 101Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer,
112 u32 size) { 102 u32 size) {
113 // Assign the allocated memory to the handle. 103 // Assign the allocated memory to the handle.
114 Nvidia::Devices::nvmap::IocAllocParams alloc_in_params{ 104 Nvidia::Devices::nvmap::IocAllocParams alloc_params{
115 .handle = handle, 105 .handle = handle,
116 .heap_mask = 0, 106 .heap_mask = 0,
117 .flags = {}, 107 .flags = {},
@@ -119,10 +109,7 @@ Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::Proce
119 .kind = 0, 109 .kind = 0,
120 .address = GetInteger(buffer), 110 .address = GetInteger(buffer),
121 }; 111 };
122 Nvidia::Devices::nvmap::IocAllocParams alloc_out_params{}; 112 R_UNLESS(nvmap.IocAlloc(alloc_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed);
123 R_UNLESS(nvmap.IocAlloc(SerializeIoc(alloc_in_params), SerializeIoc(alloc_out_params)) ==
124 Nvidia::NvResult::Success,
125 VI::ResultOperationFailed);
126 113
127 // We succeeded. 114 // We succeeded.
128 R_SUCCEED(); 115 R_SUCCEED();
@@ -179,7 +166,7 @@ constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
179}(); 166}();
180 167
181void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { 168void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
182 auto buffer = std::make_shared<android::GraphicBuffer>(); 169 auto buffer = std::make_shared<android::NvGraphicBuffer>();
183 buffer->width = SharedBufferWidth; 170 buffer->width = SharedBufferWidth;
184 buffer->height = SharedBufferHeight; 171 buffer->height = SharedBufferHeight;
185 buffer->stride = SharedBufferBlockLinearStride; 172 buffer->stride = SharedBufferBlockLinearStride;
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) {
47 vsync_signal.Wait(); 47 vsync_signal.Wait();
48 48
49 const auto lock_guard = Lock(); 49 const auto lock_guard = Lock();
50 Compose(); 50
51 if (!is_abandoned) {
52 Compose();
53 }
51 } 54 }
52} 55}
53 56
@@ -98,7 +101,6 @@ Nvnflinger::~Nvnflinger() {
98 } 101 }
99 102
100 ShutdownLayers(); 103 ShutdownLayers();
101 vsync_thread = {};
102 104
103 if (nvdrv) { 105 if (nvdrv) {
104 nvdrv->Close(disp_fd); 106 nvdrv->Close(disp_fd);
@@ -106,12 +108,20 @@ Nvnflinger::~Nvnflinger() {
106} 108}
107 109
108void Nvnflinger::ShutdownLayers() { 110void Nvnflinger::ShutdownLayers() {
109 const auto lock_guard = Lock(); 111 // Abandon consumers.
110 for (auto& display : displays) { 112 {
111 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { 113 const auto lock_guard = Lock();
112 display.GetLayer(layer).Core().NotifyShutdown(); 114 for (auto& display : displays) {
115 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
116 display.GetLayer(layer).GetConsumer().Abandon();
117 }
113 } 118 }
119
120 is_abandoned = true;
114 } 121 }
122
123 // Join the vsync thread, if it exists.
124 vsync_thread = {};
115} 125}
116 126
117void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { 127void 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:
140 140
141 s32 swap_interval = 1; 141 s32 swap_interval = 1;
142 142
143 bool is_abandoned = false;
144
143 /// Event that handles screen composition. 145 /// Event that handles screen composition.
144 std::shared_ptr<Core::Timing::EventType> multi_composition_event; 146 std::shared_ptr<Core::Timing::EventType> multi_composition_event;
145 std::shared_ptr<Core::Timing::EventType> single_composition_event; 147 std::shared_ptr<Core::Timing::EventType> single_composition_event;
diff --git a/src/core/hle/service/nvnflinger/status.h b/src/core/hle/service/nvnflinger/status.h
index 7af166c40..3fa0fe15b 100644
--- a/src/core/hle/service/nvnflinger/status.h
+++ b/src/core/hle/service/nvnflinger/status.h
@@ -19,7 +19,7 @@ enum class Status : s32 {
19 Busy = -16, 19 Busy = -16,
20 NoInit = -19, 20 NoInit = -19,
21 BadValue = -22, 21 BadValue = -22,
22 InvalidOperation = -37, 22 InvalidOperation = -38,
23 BufferNeedsReallocation = 1, 23 BufferNeedsReallocation = 1,
24 ReleaseAllBuffers = 2, 24 ReleaseAllBuffers = 2,
25}; 25};
diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp
new file mode 100644
index 000000000..ce70946ec
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp
@@ -0,0 +1,34 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/nvdrv/core/nvmap.h"
5#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
6
7namespace Service::android {
8
9static NvGraphicBuffer GetBuffer(std::shared_ptr<NvGraphicBuffer>& buffer) {
10 if (buffer) {
11 return *buffer;
12 } else {
13 return {};
14 }
15}
16
17GraphicBuffer::GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
18 : NvGraphicBuffer(width_, height_, format_, usage_), m_nvmap(nullptr) {}
19
20GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
21 std::shared_ptr<NvGraphicBuffer> buffer)
22 : NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) {
23 if (this->BufferId() > 0) {
24 m_nvmap->DuplicateHandle(this->BufferId(), true);
25 }
26}
27
28GraphicBuffer::~GraphicBuffer() {
29 if (m_nvmap != nullptr && this->BufferId() > 0) {
30 m_nvmap->FreeHandle(this->BufferId(), true);
31 }
32}
33
34} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h
index 3eac5cedd..da430aa75 100644
--- a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h
+++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h
@@ -6,16 +6,22 @@
6 6
7#pragma once 7#pragma once
8 8
9#include <memory>
10
9#include "common/common_funcs.h" 11#include "common/common_funcs.h"
10#include "common/common_types.h" 12#include "common/common_types.h"
11#include "core/hle/service/nvnflinger/pixel_format.h" 13#include "core/hle/service/nvnflinger/pixel_format.h"
12 14
15namespace Service::Nvidia::NvCore {
16class NvMap;
17} // namespace Service::Nvidia::NvCore
18
13namespace Service::android { 19namespace Service::android {
14 20
15struct GraphicBuffer final { 21struct NvGraphicBuffer {
16 constexpr GraphicBuffer() = default; 22 constexpr NvGraphicBuffer() = default;
17 23
18 constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) 24 constexpr NvGraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
19 : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_}, 25 : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_},
20 usage{static_cast<s32>(usage_)} {} 26 usage{static_cast<s32>(usage_)} {}
21 27
@@ -93,6 +99,17 @@ struct GraphicBuffer final {
93 u32 offset{}; 99 u32 offset{};
94 INSERT_PADDING_WORDS(60); 100 INSERT_PADDING_WORDS(60);
95}; 101};
96static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size"); 102static_assert(sizeof(NvGraphicBuffer) == 0x16C, "NvGraphicBuffer has wrong size");
103
104class GraphicBuffer final : public NvGraphicBuffer {
105public:
106 explicit GraphicBuffer(u32 width, u32 height, PixelFormat format, u32 usage);
107 explicit GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
108 std::shared_ptr<NvGraphicBuffer> buffer);
109 ~GraphicBuffer();
110
111private:
112 Service::Nvidia::NvCore::NvMap* m_nvmap{};
113};
97 114
98} // namespace Service::android 115} // namespace Service::android
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index ec3af80af..f5edfdc8b 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -19,19 +19,8 @@
19 19
20namespace Service::Set { 20namespace Service::Set {
21 21
22namespace { 22Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
23constexpr u64 SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET = 0x05; 23 GetFirmwareVersionType type) {
24
25enum class GetFirmwareVersionType {
26 Version1,
27 Version2,
28};
29
30void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx,
31 GetFirmwareVersionType type) {
32 ASSERT_MSG(ctx.GetWriteBufferSize() == 0x100,
33 "FirmwareVersion output buffer must be 0x100 bytes in size!");
34
35 constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809; 24 constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809;
36 auto& fsc = system.GetFileSystemController(); 25 auto& fsc = system.GetFileSystemController();
37 26
@@ -52,39 +41,34 @@ void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx,
52 FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId)); 41 FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId));
53 } 42 }
54 43
55 const auto early_exit_failure = [&ctx](std::string_view desc, Result code) { 44 const auto early_exit_failure = [](std::string_view desc, Result code) {
56 LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).", 45 LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).",
57 desc); 46 desc);
58 IPC::ResponseBuilder rb{ctx, 2}; 47 return code;
59 rb.Push(code);
60 }; 48 };
61 49
62 const auto ver_file = romfs->GetFile("file"); 50 const auto ver_file = romfs->GetFile("file");
63 if (ver_file == nullptr) { 51 if (ver_file == nullptr) {
64 early_exit_failure("The system version archive didn't contain the file 'file'.", 52 return early_exit_failure("The system version archive didn't contain the file 'file'.",
65 FileSys::ERROR_INVALID_ARGUMENT); 53 FileSys::ERROR_INVALID_ARGUMENT);
66 return;
67 } 54 }
68 55
69 auto data = ver_file->ReadAllBytes(); 56 auto data = ver_file->ReadAllBytes();
70 if (data.size() != 0x100) { 57 if (data.size() != sizeof(FirmwareVersionFormat)) {
71 early_exit_failure("The system version file 'file' was not the correct size.", 58 return early_exit_failure("The system version file 'file' was not the correct size.",
72 FileSys::ERROR_OUT_OF_BOUNDS); 59 FileSys::ERROR_OUT_OF_BOUNDS);
73 return;
74 } 60 }
75 61
62 std::memcpy(&out_firmware, data.data(), sizeof(FirmwareVersionFormat));
63
76 // If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will 64 // If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will
77 // zero out the REVISION_MINOR field. 65 // zero out the REVISION_MINOR field.
78 if (type == GetFirmwareVersionType::Version1) { 66 if (type == GetFirmwareVersionType::Version1) {
79 data[SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET] = 0; 67 out_firmware.revision_minor = 0;
80 } 68 }
81 69
82 ctx.WriteBuffer(data); 70 return ResultSuccess;
83
84 IPC::ResponseBuilder rb{ctx, 2};
85 rb.Push(ResultSuccess);
86} 71}
87} // Anonymous namespace
88 72
89void SET_SYS::SetLanguageCode(HLERequestContext& ctx) { 73void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
90 IPC::RequestParser rp{ctx}; 74 IPC::RequestParser rp{ctx};
@@ -98,12 +82,32 @@ void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
98 82
99void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { 83void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) {
100 LOG_DEBUG(Service_SET, "called"); 84 LOG_DEBUG(Service_SET, "called");
101 GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version1); 85
86 FirmwareVersionFormat firmware_data{};
87 const auto result =
88 GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version1);
89
90 if (result.IsSuccess()) {
91 ctx.WriteBuffer(firmware_data);
92 }
93
94 IPC::ResponseBuilder rb{ctx, 2};
95 rb.Push(result);
102} 96}
103 97
104void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) { 98void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) {
105 LOG_DEBUG(Service_SET, "called"); 99 LOG_DEBUG(Service_SET, "called");
106 GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version2); 100
101 FirmwareVersionFormat firmware_data{};
102 const auto result =
103 GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version2);
104
105 if (result.IsSuccess()) {
106 ctx.WriteBuffer(firmware_data);
107 }
108
109 IPC::ResponseBuilder rb{ctx, 2};
110 rb.Push(result);
107} 111}
108 112
109void SET_SYS::GetAccountSettings(HLERequestContext& ctx) { 113void SET_SYS::GetAccountSettings(HLERequestContext& ctx) {
@@ -431,8 +435,7 @@ void SET_SYS::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
431void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) { 435void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) {
432 u8 battery_percentage_flag{1}; 436 u8 battery_percentage_flag{1};
433 437
434 LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}", 438 LOG_DEBUG(Service_SET, "(STUBBED) called, battery_percentage_flag={}", battery_percentage_flag);
435 battery_percentage_flag);
436 439
437 IPC::ResponseBuilder rb{ctx, 3}; 440 IPC::ResponseBuilder rb{ctx, 3};
438 rb.Push(ResultSuccess); 441 rb.Push(ResultSuccess);
@@ -492,6 +495,29 @@ void SET_SYS::GetChineseTraditionalInputMethod(HLERequestContext& ctx) {
492 rb.PushEnum(ChineseTraditionalInputMethod::Unknown0); 495 rb.PushEnum(ChineseTraditionalInputMethod::Unknown0);
493} 496}
494 497
498void SET_SYS::GetHomeMenuScheme(HLERequestContext& ctx) {
499 LOG_DEBUG(Service_SET, "(STUBBED) called");
500
501 const HomeMenuScheme default_color = {
502 .main = 0xFF323232,
503 .back = 0xFF323232,
504 .sub = 0xFFFFFFFF,
505 .bezel = 0xFFFFFFFF,
506 .extra = 0xFF000000,
507 };
508
509 IPC::ResponseBuilder rb{ctx, 7};
510 rb.Push(ResultSuccess);
511 rb.PushRaw(default_color);
512}
513
514void SET_SYS::GetHomeMenuSchemeModel(HLERequestContext& ctx) {
515 LOG_WARNING(Service_SET, "(STUBBED) called");
516
517 IPC::ResponseBuilder rb{ctx, 3};
518 rb.Push(ResultSuccess);
519 rb.Push(0);
520}
495void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) { 521void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) {
496 LOG_WARNING(Service_SET, "(STUBBED) called"); 522 LOG_WARNING(Service_SET, "(STUBBED) called");
497 523
@@ -674,7 +700,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
674 {171, nullptr, "SetChineseTraditionalInputMethod"}, 700 {171, nullptr, "SetChineseTraditionalInputMethod"},
675 {172, nullptr, "GetPtmCycleCountReliability"}, 701 {172, nullptr, "GetPtmCycleCountReliability"},
676 {173, nullptr, "SetPtmCycleCountReliability"}, 702 {173, nullptr, "SetPtmCycleCountReliability"},
677 {174, nullptr, "GetHomeMenuScheme"}, 703 {174, &SET_SYS::GetHomeMenuScheme, "GetHomeMenuScheme"},
678 {175, nullptr, "GetThemeSettings"}, 704 {175, nullptr, "GetThemeSettings"},
679 {176, nullptr, "SetThemeSettings"}, 705 {176, nullptr, "SetThemeSettings"},
680 {177, nullptr, "GetThemeKey"}, 706 {177, nullptr, "GetThemeKey"},
@@ -685,7 +711,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
685 {182, nullptr, "SetT"}, 711 {182, nullptr, "SetT"},
686 {183, nullptr, "GetPlatformRegion"}, 712 {183, nullptr, "GetPlatformRegion"},
687 {184, nullptr, "SetPlatformRegion"}, 713 {184, nullptr, "SetPlatformRegion"},
688 {185, nullptr, "GetHomeMenuSchemeModel"}, 714 {185, &SET_SYS::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"},
689 {186, nullptr, "GetMemoryUsageRateFlag"}, 715 {186, nullptr, "GetMemoryUsageRateFlag"},
690 {187, nullptr, "GetTouchScreenMode"}, 716 {187, nullptr, "GetTouchScreenMode"},
691 {188, nullptr, "SetTouchScreenMode"}, 717 {188, nullptr, "SetTouchScreenMode"},
diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h
index c7dba2a9e..5f770fd32 100644
--- a/src/core/hle/service/set/set_sys.h
+++ b/src/core/hle/service/set/set_sys.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include "common/uuid.h" 6#include "common/uuid.h"
7#include "core/hle/result.h"
7#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
8#include "core/hle/service/time/clock_types.h" 9#include "core/hle/service/time/clock_types.h"
9 10
@@ -12,6 +13,29 @@ class System;
12} 13}
13 14
14namespace Service::Set { 15namespace Service::Set {
16enum class LanguageCode : u64;
17enum class GetFirmwareVersionType {
18 Version1,
19 Version2,
20};
21
22struct FirmwareVersionFormat {
23 u8 major;
24 u8 minor;
25 u8 micro;
26 INSERT_PADDING_BYTES(1);
27 u8 revision_major;
28 u8 revision_minor;
29 INSERT_PADDING_BYTES(2);
30 std::array<char, 0x20> platform;
31 std::array<u8, 0x40> version_hash;
32 std::array<char, 0x18> display_version;
33 std::array<char, 0x80> display_title;
34};
35static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size");
36
37Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
38 GetFirmwareVersionType type);
15 39
16class SET_SYS final : public ServiceFramework<SET_SYS> { 40class SET_SYS final : public ServiceFramework<SET_SYS> {
17public: 41public:
@@ -269,6 +293,16 @@ private:
269 }; 293 };
270 static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size"); 294 static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size");
271 295
296 /// This is nn::settings::system::HomeMenuScheme
297 struct HomeMenuScheme {
298 u32 main;
299 u32 back;
300 u32 sub;
301 u32 bezel;
302 u32 extra;
303 };
304 static_assert(sizeof(HomeMenuScheme) == 0x14, "HomeMenuScheme is incorrect size");
305
272 void SetLanguageCode(HLERequestContext& ctx); 306 void SetLanguageCode(HLERequestContext& ctx);
273 void GetFirmwareVersion(HLERequestContext& ctx); 307 void GetFirmwareVersion(HLERequestContext& ctx);
274 void GetFirmwareVersion2(HLERequestContext& ctx); 308 void GetFirmwareVersion2(HLERequestContext& ctx);
@@ -305,6 +339,8 @@ private:
305 void GetKeyboardLayout(HLERequestContext& ctx); 339 void GetKeyboardLayout(HLERequestContext& ctx);
306 void GetChineseTraditionalInputMethod(HLERequestContext& ctx); 340 void GetChineseTraditionalInputMethod(HLERequestContext& ctx);
307 void GetFieldTestingFlag(HLERequestContext& ctx); 341 void GetFieldTestingFlag(HLERequestContext& ctx);
342 void GetHomeMenuScheme(HLERequestContext& ctx);
343 void GetHomeMenuSchemeModel(HLERequestContext& ctx);
308 344
309 AccountSettings account_settings{ 345 AccountSettings account_settings{
310 .flags = {}, 346 .flags = {},
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) {
39 } 39 }
40} 40}
41 41
42template <typename T>
43T GetValue(std::span<const u8> buffer) {
44 T t{};
45 std::memcpy(&t, buffer.data(), std::min(sizeof(T), buffer.size()));
46 return t;
47}
48
49template <typename T>
50void PutValue(std::span<u8> buffer, const T& t) {
51 std::memcpy(buffer.data(), &t, std::min(sizeof(T), buffer.size()));
52}
53
42} // Anonymous namespace 54} // Anonymous namespace
43 55
44void BSD::PollWork::Execute(BSD* bsd) { 56void BSD::PollWork::Execute(BSD* bsd) {
@@ -316,22 +328,12 @@ void BSD::SetSockOpt(HLERequestContext& ctx) {
316 const s32 fd = rp.Pop<s32>(); 328 const s32 fd = rp.Pop<s32>();
317 const u32 level = rp.Pop<u32>(); 329 const u32 level = rp.Pop<u32>();
318 const OptName optname = static_cast<OptName>(rp.Pop<u32>()); 330 const OptName optname = static_cast<OptName>(rp.Pop<u32>());
319 331 const auto optval = ctx.ReadBuffer();
320 const auto buffer = ctx.ReadBuffer();
321 const u8* optval = buffer.empty() ? nullptr : buffer.data();
322 size_t optlen = buffer.size();
323
324 std::array<u64, 2> values;
325 if ((optname == OptName::SNDTIMEO || optname == OptName::RCVTIMEO) && buffer.size() == 8) {
326 std::memcpy(values.data(), buffer.data(), sizeof(values));
327 optlen = sizeof(values);
328 optval = reinterpret_cast<const u8*>(values.data());
329 }
330 332
331 LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level, 333 LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level,
332 static_cast<u32>(optname), optlen); 334 static_cast<u32>(optname), optval.size());
333 335
334 BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval)); 336 BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
335} 337}
336 338
337void BSD::Shutdown(HLERequestContext& ctx) { 339void BSD::Shutdown(HLERequestContext& ctx) {
@@ -521,18 +523,19 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco
521 523
522std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, 524std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
523 s32 nfds, s32 timeout) { 525 s32 nfds, s32 timeout) {
524 if (write_buffer.size() < nfds * sizeof(PollFD)) { 526 if (nfds <= 0) {
525 return {-1, Errno::INVAL};
526 }
527
528 if (nfds == 0) {
529 // When no entries are provided, -1 is returned with errno zero 527 // When no entries are provided, -1 is returned with errno zero
530 return {-1, Errno::SUCCESS}; 528 return {-1, Errno::SUCCESS};
531 } 529 }
530 if (read_buffer.size() < nfds * sizeof(PollFD)) {
531 return {-1, Errno::INVAL};
532 }
533 if (write_buffer.size() < nfds * sizeof(PollFD)) {
534 return {-1, Errno::INVAL};
535 }
532 536
533 const size_t length = std::min(read_buffer.size(), write_buffer.size());
534 std::vector<PollFD> fds(nfds); 537 std::vector<PollFD> fds(nfds);
535 std::memcpy(fds.data(), read_buffer.data(), length); 538 std::memcpy(fds.data(), read_buffer.data(), nfds * sizeof(PollFD));
536 539
537 if (timeout >= 0) { 540 if (timeout >= 0) {
538 const s64 seconds = timeout / 1000; 541 const s64 seconds = timeout / 1000;
@@ -580,7 +583,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
580 for (size_t i = 0; i < num; ++i) { 583 for (size_t i = 0; i < num; ++i) {
581 fds[i].revents = Translate(host_pollfds[i].revents); 584 fds[i].revents = Translate(host_pollfds[i].revents);
582 } 585 }
583 std::memcpy(write_buffer.data(), fds.data(), length); 586 std::memcpy(write_buffer.data(), fds.data(), nfds * sizeof(PollFD));
584 587
585 return Translate(result); 588 return Translate(result);
586} 589}
@@ -608,8 +611,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
608 new_descriptor.is_connection_based = descriptor.is_connection_based; 611 new_descriptor.is_connection_based = descriptor.is_connection_based;
609 612
610 const SockAddrIn guest_addr_in = Translate(result.sockaddr_in); 613 const SockAddrIn guest_addr_in = Translate(result.sockaddr_in);
611 const size_t length = std::min(sizeof(guest_addr_in), write_buffer.size()); 614 PutValue(write_buffer, guest_addr_in);
612 std::memcpy(write_buffer.data(), &guest_addr_in, length);
613 615
614 return {new_fd, Errno::SUCCESS}; 616 return {new_fd, Errno::SUCCESS};
615} 617}
@@ -619,8 +621,7 @@ Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
619 return Errno::BADF; 621 return Errno::BADF;
620 } 622 }
621 ASSERT(addr.size() == sizeof(SockAddrIn)); 623 ASSERT(addr.size() == sizeof(SockAddrIn));
622 SockAddrIn addr_in; 624 auto addr_in = GetValue<SockAddrIn>(addr);
623 std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
624 625
625 return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); 626 return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
626} 627}
@@ -631,8 +632,7 @@ Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
631 } 632 }
632 633
633 UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn)); 634 UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn));
634 SockAddrIn addr_in; 635 auto addr_in = GetValue<SockAddrIn>(addr);
635 std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
636 636
637 return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in))); 637 return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
638} 638}
@@ -650,7 +650,7 @@ Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
650 650
651 ASSERT(write_buffer.size() >= sizeof(guest_addrin)); 651 ASSERT(write_buffer.size() >= sizeof(guest_addrin));
652 write_buffer.resize(sizeof(guest_addrin)); 652 write_buffer.resize(sizeof(guest_addrin));
653 std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); 653 PutValue(write_buffer, guest_addrin);
654 return Translate(bsd_errno); 654 return Translate(bsd_errno);
655} 655}
656 656
@@ -667,7 +667,7 @@ Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
667 667
668 ASSERT(write_buffer.size() >= sizeof(guest_addrin)); 668 ASSERT(write_buffer.size() >= sizeof(guest_addrin));
669 write_buffer.resize(sizeof(guest_addrin)); 669 write_buffer.resize(sizeof(guest_addrin));
670 std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); 670 PutValue(write_buffer, guest_addrin);
671 return Translate(bsd_errno); 671 return Translate(bsd_errno);
672} 672}
673 673
@@ -725,7 +725,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
725 optval.size() == sizeof(Errno), { return Errno::INVAL; }, 725 optval.size() == sizeof(Errno), { return Errno::INVAL; },
726 "Incorrect getsockopt option size"); 726 "Incorrect getsockopt option size");
727 optval.resize(sizeof(Errno)); 727 optval.resize(sizeof(Errno));
728 memcpy(optval.data(), &translated_pending_err, sizeof(Errno)); 728 PutValue(optval, translated_pending_err);
729 } 729 }
730 return Translate(getsockopt_err); 730 return Translate(getsockopt_err);
731 } 731 }
@@ -735,7 +735,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
735 } 735 }
736} 736}
737 737
738Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) { 738Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval) {
739 if (!IsFileDescriptorValid(fd)) { 739 if (!IsFileDescriptorValid(fd)) {
740 return Errno::BADF; 740 return Errno::BADF;
741 } 741 }
@@ -748,17 +748,15 @@ Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, con
748 Network::SocketBase* const socket = file_descriptors[fd]->socket.get(); 748 Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
749 749
750 if (optname == OptName::LINGER) { 750 if (optname == OptName::LINGER) {
751 ASSERT(optlen == sizeof(Linger)); 751 ASSERT(optval.size() == sizeof(Linger));
752 Linger linger; 752 auto linger = GetValue<Linger>(optval);
753 std::memcpy(&linger, optval, sizeof(linger));
754 ASSERT(linger.onoff == 0 || linger.onoff == 1); 753 ASSERT(linger.onoff == 0 || linger.onoff == 1);
755 754
756 return Translate(socket->SetLinger(linger.onoff != 0, linger.linger)); 755 return Translate(socket->SetLinger(linger.onoff != 0, linger.linger));
757 } 756 }
758 757
759 ASSERT(optlen == sizeof(u32)); 758 ASSERT(optval.size() == sizeof(u32));
760 u32 value; 759 auto value = GetValue<u32>(optval);
761 std::memcpy(&value, optval, sizeof(value));
762 760
763 switch (optname) { 761 switch (optname) {
764 case OptName::REUSEADDR: 762 case OptName::REUSEADDR:
@@ -862,7 +860,7 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess
862 } else { 860 } else {
863 ASSERT(addr.size() == sizeof(SockAddrIn)); 861 ASSERT(addr.size() == sizeof(SockAddrIn));
864 const SockAddrIn result = Translate(addr_in); 862 const SockAddrIn result = Translate(addr_in);
865 std::memcpy(addr.data(), &result, sizeof(result)); 863 PutValue(addr, result);
866 } 864 }
867 } 865 }
868 866
@@ -886,8 +884,7 @@ std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> mes
886 Network::SockAddrIn* p_addr_in = nullptr; 884 Network::SockAddrIn* p_addr_in = nullptr;
887 if (!addr.empty()) { 885 if (!addr.empty()) {
888 ASSERT(addr.size() == sizeof(SockAddrIn)); 886 ASSERT(addr.size() == sizeof(SockAddrIn));
889 SockAddrIn guest_addr_in; 887 auto guest_addr_in = GetValue<SockAddrIn>(addr);
890 std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in));
891 addr_in = Translate(guest_addr_in); 888 addr_in = Translate(guest_addr_in);
892 p_addr_in = &addr_in; 889 p_addr_in = &addr_in;
893 } 890 }
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:
163 Errno ListenImpl(s32 fd, s32 backlog); 163 Errno ListenImpl(s32 fd, s32 backlog);
164 std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg); 164 std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg);
165 Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval); 165 Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval);
166 Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval); 166 Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval);
167 Errno ShutdownImpl(s32 fd, s32 how); 167 Errno ShutdownImpl(s32 fd, s32 how);
168 std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); 168 std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
169 std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, 169 std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
index 9fc01ea90..7149fffeb 100644
--- a/src/core/hle/service/time/clock_types.h
+++ b/src/core/hle/service/time/clock_types.h
@@ -11,6 +11,11 @@
11#include "core/hle/service/time/errors.h" 11#include "core/hle/service/time/errors.h"
12#include "core/hle/service/time/time_zone_types.h" 12#include "core/hle/service/time/time_zone_types.h"
13 13
14// Defined by WinBase.h on Windows
15#ifdef GetCurrentTime
16#undef GetCurrentTime
17#endif
18
14namespace Service::Time::Clock { 19namespace Service::Time::Clock {
15 20
16enum class TimeType : u8 { 21enum class TimeType : u8 {
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index f0b5eff8a..d30f49877 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -35,7 +35,7 @@ static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_cont
35 return { 35 return {
36 buffer_queue_core, 36 buffer_queue_core,
37 std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), 37 std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
38 std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)}; 38 std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
39} 39}
40 40
41Display::Display(u64 id, std::string name_, 41Display::Display(u64 id, std::string name_,